Mit dem bisherigen Wissen, können wir unsere Programme immer nur sequentiell ablaufen lassen. Unsere Programme liefen also immer Zeile für Zeile ab. In diesem Teil wollen wir nun den sequentiellen Programmfluss brechen. C C++ C/C++ Kontrollstrukturen Verzweigungen Schleifen Sprünge if else for do while break continue Kontrollstrukturen - Verzweigungen Schleifen Sprünge if else for do while break continue Kapitel 11: Kontrollstrukturen

11.8. Die while-Schleife            zurück  Ein Kapitel tiefer  zum Inhaltsverzeichnis

Mit Schleifen können Sie Anweisungsblöcke mehrfach hintereinander ausführen lassen. Das Grundgerüst der Schleifenbedingung while sieht folgendermaßen aus:

while(Bedingung==wahr)
   {
      /*Abarbeiten von Befehlen bis Bedingung ungleich wahr*/
   }

Ist die Bedingung, die in den Klammern nach while folgt, wahr, so wird der Anweisungsblock in geschwungenen Klammern (oft auch "curly brackets" genannt) ausgeführt. Diese Anweisungen werden sooft ausgeführt, bis die Bedingung in den Klammern falsch, also unwahr ist. Der zugehörige Programmablaufplan sieht so aus:

Abbildung 11.9: Programmablaufplan der while-Schleife
Abbildung 11.9: Programmablaufplan der while-Schleife

Üblicherweise läuft die while-Schleife in drei Schritten ab:

In der Praxis sieht dies etwa so aus:

int var=0;           /* Initialisieren */
while(var < 10)      /* Solange var kleiner als 10 - Bedingung */
   {
      /* weitere Anweisungen */
      var++;         /* Reinitialisieren */
   }

Jetzt folgt ein Listing mit einer while-Schleife:

#include <stdio.h>

int main()
{
   int zahl=1, tmp=0;

   while(zahl<=10)
      {
         tmp=tmp+zahl;
         printf("%d+",zahl++);     /*Zahl + 1*/
      }
   printf("\b = %d\n",tmp);
   return 0;
}

Das Programm führt die while-Schleife so lange aus, bis die Variable zahl kleiner oder gleich 10 ist. Hier ein kurzer Durchgang des Programms Schritt für Schritt:

while(zahl<=10)  

Ist die Zahl kleiner oder gleich 10? Die Zahl hat den Wert 1, also wird in den Anweisungsblock gesprungen. Hier wird zuerst die Addition tmp=tmp+zahl durchgeführt. Somit ist der Wert von tmp 1. Jetzt wird die Variable zahl um 1 erhöht (zahl++). Der while-Anweisungsblock endet, und das Programm springt zurück zum Anfang der while-Anweisung. Es erfolgt eine erneute Überprüfung daraufhin, ob die Zahl immer noch kleiner oder gleich 10 ist. Da sie jetzt den Wert 2 hat, geht es wie vorher schon im Anweisungsblock weiter. Das wird so lange wiederholt, bis zahl den Wert 11 erreicht hat. Denn dann ist die Bedingung, ob zahl kleiner oder gleich 10 ist, falsch (unwahr). Das Programm läuft nach dem while-Anweisungsblock weiter und gibt das Ergebnis 55 aus.

11.8.1 Endlosschleife (while)
Die while-Schleife wird oft absichtlich in Form einer Endlosschleife implementiert. Für die Beendung einer Endlosschleife sorgt dann nicht die Schleifenbedingung, sondern das Schlüsselwort break. Mit der break-Anweisung können Sie die Schleife jederzeit verlassen. Ein Beispiel einer Endlosschleife:

#include <stdio.h>

int main()
{
   int zahl, summe=0;
   printf("Summenberechnung\nBeenden der Eingabe mit 0 \n");

   while(1)     /* Endlosschleife, weil: 1 ist immer wahr */
      {
         printf("Bitte Wert eingeben > ");
         scanf("%d", &zahl);
         if(zahl == 0)   /* Haben wir 0 eingegeben.... */
            break;        /*...dann raus aus der Schleife */
         else
            summe+=zahl;
      }
   printf("Die Summe aller Werte beträgt: %d\n", summe);
   return 0;
}

Die Zeile

while(1)

verkörpert die Endlosschleife. Der Inhalt dieser Schleife ist immer wahr, da Sie hier den Wert 1 haben. Sie könnten dort jede beliebige Zahl außer 0 hinschreiben. Sie haben in den vorangegangenen Kapiteln gesehen, dass 1 (und alle anderen Werte ungleich 0) für "wahr" (true) und 0 für "unwahr" (false) steht. Zurück zu dem Programm. Sie werden so lange aufgefordert eine Zahl einzugeben, bis Sie den Wert 0 verwenden:

if(zahl == 0) /* Falls 0 eingegeben wurde... */
   break;     /*...dann Schleife verlassen */

Hat die Variable zahl den Wert 0, wird mit der Anweisung break aus dem Anweisungsblock herausgesprungen.

11.8.2 Fehlervermeidung bei while Schleifen
Natürlich können Sie mit Schleifen auch diverse Fehler machen. Im Folgenden sollen daher einige häufig auftretende Fehler angesprochen werden.

Schließen Sie eine Schleife niemals mit einem Semikolon ab. Folgendes Beispiel erzeugt ungewollt eine Endlosschleife:

int x=0;
while(x > 10); /* Fehler durch Semikolon am Ende */
   {
      printf("Der Wert von x beträgt %d\n", x);
      x++;
   }

Die Variable x wird niemals im Anweisungsblock inkrementiert werden, da die while-Schleife nichts anderes tut, als ständig die Bedingung zu prüfen, ob x größer als 10 ist.

Vermeiden Sie außerdem - wenn möglich - Überprüfungen auf Gleichheit in den Schleifen:

int x=2;
while(x == 10)
   {
      printf("Der Wert von x beträgt %d \n", x);
      x*=x;
   }

Die Bedingung der while-Schleife wird nie erfüllt. Verwenden Sie in einem solchen Fall besser die Überprüfung auf kleiner oder gleich, etwa wie folgt:

while(x <= 10) 

Eine weitere Fehlerquelle können die logischen Operatoren in der while-Schleife darstellen, wie das folgende Programmbeispiel verdeutlicht:

#include <stdio.h>

int main()
{
   int zahl1=0, zahl2=0;
   while((zahl1++ < 5) || (zahl2++ < 5) )
      printf("Wert von zahl1: %d zahl2: %d \n ", zahl1, zahl2);
   return 0;
}

Da hier der erste Ausdruck fünfmal wahr ist, wird wegen des logischen ODER-Operators der zweite Ausdruck nicht ausgewertet. Erst wenn also der erste Ausdruck unwahr, also 5 ist, wird der zweite Ausdruck fünfmal durchlaufen. Als Nebeneffekt wird aber gleichzeitig der erste Ausdruck bei jedem Schleifendurchlauf inkrementiert. Und so kommt es, dass die Variable zahl1 am Ende den Wert 10 hat, statt 5 wie ursprünglich beabsichtigt.

11.9. Die do-while Schleife            zurück  Ein Kapitel tiefer  Ein Kapitel höher  zum Inhaltsverzeichnis

Die Schleife do while verhält sich wie die while-Schleife, nur dass die Bedingung am Ende des Anweisungsblocks überprüft wird. Hier die Syntax:

do {
       /* Anweisungen */
   }while(BEDINGUNG==wahr);

Der Anweisungsblock wird mit dem Schlüsselwort do eingeleitet. Im Block werden dann Anweisungen ausgeführt. Am Ende des Anweisungsblocks steht der bereits bekannte Ausdruck while, bei dem überprüft wird, ob die angegebene Bedingung wahr ist. Ist die Bedingung wahr, wird der Anweisungsblock erneut ausgeführt und es beginnt wieder bei do. Wenn die Bedingung unwahr ist, geht es weiter hinter der while-Bedingung.

Achten Sie auch darauf, dass Sie die do while-Schleife am Ende von while mit einem Semikolon abschließen. Dies ist ein häufig gemachter Fehler. Der Programmablaufplan zur do while-Schleife:

Abbildung 11.10: Programmablaufplan der do while-Schleife
Abbildung 11.10: Programmablaufplan der do while-Schleife

Zur Veranschaulichung ein weiteres Listing:

#include <stdio.h>
#include <stdlib.h>  /* für rand() */

int main()
{
   int ratezahl, count=0, erraten=0;
   int zufall=rand()%10; /* Pseudo-Zufallszahl von 1-10*/

   do{  /* Start der do while-Schleife */
      printf("Zahleingabe bitte (1-10): ");
      scanf("%d", &ratezahl);
      if(ratezahl==zufall) /*Zahl richtig geraten? */
         {
            erraten=1; /* Ja, die Zahl ist richtig */
            count++;
         }
      else
         {
            (ratezahl>zufall) ? printf("kleiner\n")
             :printf("grösser\n");
            count++;
         }
      }while( (erraten != 1) && (count != 3) );

   if(erraten == 0)
      {
         printf("Sie haben 3 Chancen vertan ;) \n");
         printf("Die Zahl wäre %d gewesen: \n", zufall);
      }
   else
      printf("Mit %d Versuchen erraten!\n",count);
   return 0;
}

In diesem Programm wird die Headerdatei

#include <stdlib.h> 

für die Funktion

rand()%10;

verwendet, womit eine (Pseudo-) Zufallszahl zwischen 1-10 erzeugt wurde, deren Wert Sie an die Variable zufall übergeben.

Die do while-Schleife wird so lange wiederholt, bis die beiden Ausdrücke in while wahr sind:

while( (erraten != 1) && (count != 3) );

Die Bedingung für das Spiel lautet also: Sie haben maximal 3 Versuche (count != 3) , in denen Sie die Zahl erraten müssen. Solange Sie die Variable von erraten auf dem Wert 0 UND den Zähler für die Versuche count noch nicht auf 3 stehen haben, beginnt der Anweisungsblock wieder von Neuem. Ist eine dieser Bedingungen unwahr, haben Sie entweder die Zahl erraten oder mehr als drei Versuche benötigt. Dies wird anschließend nach dem Anweisungsblock ausgewertet.

Aber warum lassen Sie nicht den Computer eine Zahl raten, die Sie sich ausgedacht haben? Künstliche Intelligenz und zu kompliziert, denken Sie? Solch ein Spiel lässt sich einfacher realisieren als Sie denken. Hier das Spiel andersherum:

#include <stdio.h>

int main()
{
   char response;
   printf("Denk Dir eine Nummer zwischen 1 und 100 aus.\n");
   printf("Das errate ich in 7 oder weniger Versuchen \n\n");
   do
      {
         int lo = 1, hi = 100;
         int guess;
         while (lo <= hi)
            {
               guess = (lo + hi) / 2;
               printf("Ist es %d ",guess);
               printf(" ((h)oeher/(n)iedriger/(j)a): ");
               fflush(stdout);
               scanf("%c%*c",&response);

               if (response == 'h')
                  lo = guess + 1;
               else if (response == 'n')
                  hi = guess - 1;
               else if (response != 'j')
                  printf("Erraten ... :-)");
               else
                  break;
            }
         /* Resultat ausgeben */
         if (lo > hi)
            printf("Du schummelst!\n");
         else
            printf("Deine Nummer lautet: %d\n",guess);
         printf("Noch ein Spiel (j)a/nein : ");
         fflush(stdout);
         scanf("%c%*c",&response);
      }while(response == 'j');
   return 0;
}

Der Computer errät dabei Ihre Zahl immer in maximal sieben Versuchen. Verwendet wird dabei wird ein so genanntes Teile-und-herrsche-Prinzip. Die Variable guess erhält durch die Berechnung (lo+hi)/2 zuerst den Wert 50. Ist die von Ihnen gesuchte Zahl jetzt höher, erhält die Variable lo einen neuen Wert mit guess+1, also 51. Somit beginnt das Teilen und Herrschen von Neuem mit (lo+hi)/2, in Zahlen (51+100)/2, also 75. Ist jetzt die gesuchte Zahl niedriger, bekommt hi einen neuen Wert mit guess-1. Es ergibt sich beim nächsten Schleifendurchlauf (lo+hi)/2, in Zahlen (51+74)/2, also 62. Und so weiter, bis die Zahl erraten wurde. Auf dieses Teile-und-herrsche-Prinzip werden Sie noch einige Mal in diesem Buch stoßen.

Ein weiteres praktisches Anwendungsbeispiel der do while-Schleife ist ein Benutzermenü für die Konsole:

#include <stdio.h>

int main()
{
   int auswahl;

   do{
      printf("-1- Auswahl1\n");
      printf("-2- Auswahl2\n");
      printf("-3- Auswahl3\n");
      printf("-4- Programmende \n\n");
      printf("\n\n Ihre Auswahl: ");
      scanf("%d", &auswahl);
      switch(auswahl)
        {
           case 1:  printf("\n Das war Auswahl 1 \n"); break;
           case 2:  printf("\n Das war Auswahl 2 \n"); break;
           case 3:  printf("\n Das war Auswahl 3 \n"); break;
           case 4:  printf("\n Programmende \n");       break;
           default: printf("\n Unbekannte Auswahl \n");
        }
   }while(auswahl!=4);
   return 0;
}

Meist stellt sich nach einem solchen Menübeispiel die Frage, wie der Bildschirm gelöscht werden kann. In ANSI-C ist aber keine Funktion dafür vorgesehen. Das bedeutet, dass es von Compiler und Betriebssystem abhängt, ob eine (nicht standardisierte) Funktion hierfür existiert. Wenn Sie eine solche verwenden wollen, halten Sie Ausschau nach Funktionen wie clrscr() für Microsoft Windows oder der Bibliothek <ncurses.h> für Linux/UNIX.

11.10. Die for - Schleife            zurück  Ein Kapitel tiefer  Ein Kapitel höher  zum Inhaltsverzeichnis

Mit der for-Schleife können Sie - wie schon mit der while-Schleife - Anweisungsblöcke mehrfach hintereinander ausführen. Der Unterschied ist jedoch, dass bei der for-Schleife die Initialisierung, die Bedingung und die Reinitialisierung der Schleifenvariable schon in der for-Anweisung erfolgt. Die Syntax zur for-Schleife:

for(Initialisierung; Bedingung; Reinitialisierung)
   {
      /* Anweisungen */
   }

Beim Ablauf der for-Schleife wird in der Regel zuerst die Schleifenvariable initialisiert. Dies geschieht aber nur einmal, unabhängig davon, wie oft sich die Schleife wiederholt. Danach findet typischerweise eine Bedingungsüberprüfung statt. Ergibt diese "wahr", geht die Ausführung im Anweisungsblock mit weiteren Anweisungen weiter. Hat der Anweisungsblock alle Anweisungen ausgeführt, wird die Reinitialisierung der Schleifenvariable ausgeführt. Dann wird erneut die Schleifen-Bedingung überprüft, und alles beginnt von vorne. Die for-Schleife wird beendet, wenn die Schleifen-Bedingung nicht mehr wahr ist.

Die Arbeitsweise einer for-Schleife lässt sich gut anhand des folgenden Beispiels demonstrieren:

#include <stdio.h>

int main()
{
   int i;
   for(i=1; i <= 5; i++)
      printf("for(i=1; %d <= 5; %d++) \n", i, i);
   return 0;
}

Das Programm zeigt jeweils den aktuellen Variableninhalt von i in der for-Schleife. Wie in diesem Beispiel gesehen, kann auch bei den Schleifen der Anweisungsblock mit den geschweiften Klammern weggelassen werden, wenn dieser nur aus einer Anweisung besteht. Der Programmablaufplan der for-Schleife sieht wie folgt aus:

Abbildung 11.11: Programmablaufplan der for-Schleife
Abbildung 11.11: Programmablaufplan der for-Schleife

Mit for-Schleifen lassen sich aber nicht nur Schleifen zum Dekrementieren (--) bzw. Inkrementieren (++) realisieren. Sie können in der for-Schleife auch weitere Rechenoperationen vornehmen. Hier ein Programm, dass immer die letzte Dezimalstelle eines Werts abschneidet. Die Ergebniszahl soll danach spiegelverkehrt ausgegeben werden:

#include <stdio.h>

int main()
{
   int zahl;

   for(zahl=1234; zahl >= 1; zahl/=10)
      printf("%d", zahl%10);
   printf("\n");
   return 0;
}

Typische Fehler bei der Verwendung einer for-Schleife:

11.10.1 Beispiele für eine for-Schleife
Als Anregung und Übung sollen im Anschluss 10 verschiedene Möglichkeiten der Verwendung einer for-Schleife gezeigt werden.

1. Möglichkeit

#include <stdio.h>

int main()
{
   int sek;
   for(sek=5; sek>0; sek--)
      printf("%d Sekunden!\n", sek);
   printf("Die Zeit ist abgelaufen! \n");
   return 0;
}

Hier benutzen Sie den Dekrement-Operator zum Rückwärtszählen. Die Schleife zählt so lange rückwärts, bis der Wert sek gleich 0 ist.

2. Möglichkeit

#include <stdio.h>

int main()
{
   int n;
   for(n=0; n<=60; n=n+10)
      printf("%d\n",n);
   return 0;
}

Sie können innerhalb der Schleife nicht nur inkrementieren und dekrementieren, sondern auch rechnen. In diesem Fall werden die Zahlen in 10er-Schritten ausgegeben - von 0 bis 60.

3. Möglichkeit

#include <stdio.h>

int main()
{
   char ch;
   for(ch='A'; ch<='Z'; ch++)
      printf("%c, ", ch);
   printf("\n");
   return 0;
}

Diese Möglichkeit funktioniert auch sehr gut mit dem Datentyp char. Dann wird das Alphabet in Großbuchstaben ausgegeben.

4. Möglichkeit

#include <stdio.h>

int main()
{
   int cube;
   for(cube=1; cube*cube*cube<=216; cube++)
      printf("n=%d Volumen : %d \n", cube, cube*cube*cube);
   return 0;
}

Als Abbruchbedingung können Sie ebenso eine Berechnung verwenden. In diesem Fall soll das Volumen eines Würfels bis zur Größe von maximal 216 berechnet werden. Die Abbruchbedingung ist also erreicht, wenn cube bis 7 hochgezählt wurde, da 7*7*7 größer ist als 216.

5. Möglichkeit

#include <stdio.h>

int main()
{
   double zs;
   for(zs=100.0; zs<150.0; zs=zs*1.1)
      printf("%.2f\n", zs);
   return 0;
}

Bei dieser Möglichkeit werden immer 10% vom jeweiligen Gesamtwert berechnet. Sie haben zum Beispiel 100€ auf der Bank und bekommen darauf 10% Zinsen im Jahr. Sie wollen wissen, nach wie vielen Jahren der Betrag in die Nähe von 150 € kommt.

6. Möglichkeit

#include <stdio.h>

int main()
{
   int x,y=50;
   for(x=0; y<=75; y=(++x*5)+50)
      printf("%d\n", y);
   return 0;
}

Diese etwas komplex anmutende Schleife nimmt nichts anderes vor, als einen Wert in 5er-Schritten von 50-75 auszugeben. Zuerst wird in den Klammern (x*5) berechnet und anschließend 50 addiert. Da x sich bei jedem Durchlauf um den Wert 1 erhöht und mit 5 multipliziert wird, ergeben sich Werte in 5er-Sprüngen.

7. Möglichkeit

#include <stdio.h>

int main()
{
   int x,y;
   x=2;
   for(y=2; x<20;)
      {
         x=x*y;
         printf("%d\n",x++);
      }
   return 0;
}

Sie sehen hier, dass nicht unbedingt alle Variablen einer for-Schleife deklariert werden müssen. Lediglich die beiden Semikolons müssen immer in der for-Schleife stehen.

8. Möglichkeit

#include <stdio.h>

int main()
{
   for(;;)
      printf("Endlosschleife!!\n");
   return 0;
}

Hier ein Beispiel, bei dem überhaupt nichts in der for-Schleife steht. Wenn Sie dieses Programm ausführen, wird so lange auf dem Bildschirm der String "Endlosschleife" ausgegeben, bis Sie das Programm selbst gewaltsam abbrechen. Die Schreibweise for(;;) ist gleichwertig mit while(1). Beides sind Formen von Endlosschleifen.

9. Möglichkeit

#include <stdio.h>

int main()
{
   int n;
   for(printf("Bitte eine Zahl eingeben: ");n!=5;)
      scanf("%d",&n);
   printf("Diese Zahl wollte ich\n");
   return 0;
}

Hier benutzen Sie die for-Schleife zur Abfrage einer Zahl. Die Schleife wird beendet, wenn Sie die Zahl 5 eingeben.

10. Möglichkeit

#include <stdio.h>

int main()
{
   int n1,n2;
   for(n1=1,n2=2; n1<=10; n1++)
      printf("%d\n",n1*n2);
   return 0;
}

Es ist auch möglich, mehrere Werte innerhalb einer for-Schleife zu initialisieren. Natürlich war dies nur eine Auswahl von Verwendungsmöglichkeiten einer for-Schleife. Der Abschnitt sollte jedoch zeigen, wie flexibel sich for-Schleifen verwenden lassen.

11.11. Kontrollierte Sprünge            zurück  Ein Kapitel tiefer  Ein Kapitel höher  zum Inhaltsverzeichnis

Es gibt vier Möglichkeiten, eine Ablaufstruktur, wie etwa Schleifen, Funktionen, Bedingungen oder gar das Programm, unmittelbar zu verlassen. Über sie kann aber nicht in eine bestimmte Anweisung verzweigt werden, sondern lediglich zur nächsten Ablaufstruktur.

Es sei angemerkt, dass exit und return keine schleifentypischen Anweisungen sind, im Gegensatz zu break und continue. Auf continue und break soll noch etwas genauer eingegangen werden.

11.11.1 continue
Die continue-Anweisung beendet nur die aktuelle Schleifenausführung. Das bedeutet, dass ab dem Aufruf von continue im Anweisungsblock der Schleife alle anderen Anweisungen übersprungen werden und die Programmausführung zur Schleife mit der nächsten Ausführung zurückspringt:

#include <stdio.h>

int main()
{
   int i;
   for(i=1; i<=20; i++)
      {
         if(i%2)        /* Rest bedeutet ungerade Zahl */
            continue;   /* printf überspringen */
         printf("%d ",i);
      }
   printf("\n");
   return 0;
}

Bei diesem Beispiel überprüfen Sie, ob es sich bei der Variable i um eine ungerade Zahl handelt. In diesem Fall wird die continue-Anweisung ausgeführt. Die printf-Anweisung wird dabei übersprungen, und es geht zum nächsten Schleifendurchlauf. Die Ausgabe des Programms bestätigt Ihnen, dass nur die geraden Zahlen durchkommen. So konnten Sie sich mit continue praktisch eine else-Anweisung ersparen.

Bitte achten Sie bei continue auf die folgenden eventuell ungünstigen Seiteneffekte:

#include <stdio.h>

int main()
{
   int i=2;
   while(i<=10)
      {
         if(i%2)        /* Rest bedeutet ungerade Zahl */
            continue;   /* printf überspringen */
         printf("%d ", i);
         i++;
      }
   return 0;
}

Dieses Programm hätte dasselbe ausführen sollen wie schon das Programmbeispiel zuvor. Mit dem Unterschied, dass es sich hier um eine Endlosschleife handelt. Denn sobald

if(i%2)

wahr ist, also der Wert ungerade ist, springt das Programm wieder zum Schleifenanfang. Die Iteration (i++) wird danach nie mehr ausgeführt, da sich der Wert der Variable i nicht mehr ändern kann und somit immer ungerade bleibt.

11.11.2 break
Bisher haben Sie die break-Anweisung nur bei der switch case-Verzweigung verwendet. Mit break können aber auch Schleifen vorzeitig beendet werden, allerdings sollte dies nur ausnahmsweise erfolgen. Denn im Regelfall sollten Sie eine Schleife immer mit einer Bedingung beenden.

Achtung
 

Ein oft gemachter Fehler ist das Setzen von break in einer verschachtelten Schleife. Wenn break in der innersten Schleife verwendet wird, wird auch nur diese Schleife abgebrochen.

11.12. Direkte Sprünge mit goto            zurück  Ein Kapitel tiefer  Ein Kapitel höher  zum Inhaltsverzeichnis

Ich habe mir lange überlegt, ob ich goto überhaupt in diesem Buch erwähnen soll, da die Verwendung von goto gemeinhin als sehr schlechter Stil angesehen wird und Sie diesen Befehl nach Möglichkeit nicht benutzen sollten. Da ich aber ein möglichst vollständiges Werk zur C-Sprache vorlegen wollte, habe ich das goto-Thema als Ergänzung hinzugefügt.

Der goto-Sprungbefehl gilt heute bei vielen Programmierern als verpönt. Die Geschichte von goto begann, da es für die Programmiersprache C keine genauen Zeilennummern wie in anderen Programmiersprachen gab. Mit der goto-Labelanweisung konnte man ein genaues Sprungziel festlegen. Es ist dabei egal, ob das Sprungziel vor oder nach dem goto-Statement im Programm aufgeführt ist. Einzige Bedingung ist dabei, dass die Sprunganweisungen und Marken in derselben Funktion liegen müssen.

Nützlich (dies sei vorsichtig betont) kann goto sein, um aus tief verschachtelten Schleifen oder als Reaktion auf Programmfehler herauszuspringen.

Die Syntax für goto sieht folgendermaßen aus:

goto LABEL;
LABEL : Anweisung;

Mit goto LABEL wird zur Marke LABEL gesprungen, und die dortigen Anweisungen werden ausgeführt. Ein Beispiel zu goto:

#include <stdio.h>

int main()
{
   int i,j,k;
   for(i=1; i<10; i++){
      for(j=1; j<10; j++){
         for(k=1; k<10; k++){
            printf("Wir befinden uns in der tiefsten "
                   "Verschachtelungsebene\n");
            goto RAUS;
         }
      }
   }
   RAUS : printf("Mit einem Sprung raus hier \n");
   return 0;
}

In diesem Beispiel wird, sobald Sie in der innersten Verschachtelung angekommen sind, mittels der goto-Sprunganweisung zum Label RAUS am Ende des Programms gesprungen.

Warum also ist goto so verpönt? Aus Performancegründen! Durch goto wird der normale Ablauf des Programms einfach unterbrochen. Ein weiterer Grund, goto nicht zu verwenden: Wenn mit goto in einen Anweisungsblock gesprungen wird, der lokale Variablen beinhaltet, ist das Verhalten systemabhängig.

Es gibt wohl kaum ein Problem, das sich nicht auch ohne goto lösen lässt. Man kann sagen, dass ein goto mit einem Sprung nach vorne nichts ausmacht. Von einem goto, das aber zurückspringt, kann nur abgeraten werden. In solch einem Fall (zurückspringen) können Sie die do while-Schleife als bessere Alternative verwenden.

Sprünge über Funktionsgrenzen sind mit goto ohnehin nicht möglich. Dafür gibt es die Funktionen setjmp und longjmp.

11.13. Notationsstil            zurück  Ein Kapitel höher  zum Inhaltsverzeichnis

Vielleicht noch ein paar Sätze zur Notationsform von strukturierten Anweisungen. Als Beispiel soll die for-Schleife verwendet werden. Folgende Stile finden Sie häufiger vor:

11.13.1 K&R-Stil:

for(i=0; i < 10; i++){
        /* Anweisungen */
   }

11.13.2 Whitesmith-Stil

for(i=0; i < 10; i++)
           {
             /* Anweisungen */
           }

11.13.3 Allman-Stil

for(i=0; i < 10; i++)
{
           /* Anweisungen */
}

11.13.4 GNU EMACS-Stil

for(i=0; i < 10; i++)
           {
                     /* Anweisungen */
           }

11.13.5 Der Stil des Autors ;)

for(i=0; i < 10; i++)
   {
      /* Anweisungen */
   }

Welchen Notationsstil Sie letztendlich verwenden, ist wohl eine Frage des eigenen Geschmacks. Arbeiten Sie allerdings an einem größeren Projekt mit mehreren Personen, so sollte der Stil vorher abgesprochen werden, um eine Vermischung zu vermeiden.

Tipp
 

Verwenden Sie möglichst immer nur eine Anweisung pro Zeile. Im Fall eines Fehlers ist es dann viel einfacher, diesen zu finden.

Weiter mit Kapitel 12: Funktionen            zum Inhaltsverzeichnis