6. Kontrollstrukturen
  Mit Kontrollstrukturen sind die Befehle und Zeichenfolgen gemeint, die den Ablauf des
  Programms steuern. Dazu gehören im wesentlichen verschiedene Verzweigungen und
  Schleifen.
  
6.1. Sequenzen
  Diese Struktur ist schon bekannt: das Semikolon (";"). Jede Anweisung
  muss mit einem Semikolon abgeschlossen sein, damit der C-Compiler weiß, an welcher Stelle
  die Anweisung zu Ende ist.
  Es können mehrere Operationen hintereinander gestellt werden, wenn sie durch Kommata
  voneinander getrennt werden. Diese Operationen werden von links nach rechts ausgewertet;
  das Ergebnis der letzten Operation ist gleichzeitig das Ergebnis der gesamten Operation.
  Diese Eigenschaft wird weiter unten bei der for-Schleife ausgenutzt.
  Beispiel:
   kap06_01.c
  kap06_01.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    char c_alt, c_neu, c = 'z';
  06 
  07    c_neu = (c_alt = c, c = 'a');
  08    printf("c = %c\n", c);
  09    printf("c_alt = %c\n", c_alt);
  10    printf("c_neu = %c\n", c_neu);
  11 
  12    return 0;
  13 }
  
  Ausgegeben wird:
     c = a
   c_alt = z
   c_neu = a
  In der Klammer in Zeile 7 wird zuerst der Inhalt von c der Variable
  c_alt zugewiesen ('z'). Dann erhält
  c den neuen Wert ('a'). Dieser Wert ist
  gleichzeitig das Ergebnis des gesamten Klammerausdrucks und wird der Variablen
  c_neu zugewiesen.
  Hinweis:
  Die Klammer ist dringend notwendig, da der Komma-Operator die geringste Priorität hat.
  Würde die Klammer weggelassen werden, entspräche es folgender Zeile:
     (c_neu = c_alt = c), c = 'a';
  c_neu hätte damit das 'z' und nicht das
  'a' als Inhalt.
  
6.2. Verzweigung: if-Anweisung
  Oft ist es nötig, Anweisungen in Abhängigkeit von Bedingungen auszuführen.
  Der einfachste Befehl zum Abfragen von Bedingungen und anschließendem Verzweigen in
  Abhängigkeit der Bedingung ist die if-Anweisung bzw.
  if-Abfrage (auf keinen Fall if-Schleife!). Sie hat
  folgende Syntax:
  
  if (Bedingung)
     Anweisung1;
  else
     Anweisung2;
  Gelesen wird dieser Block folgendermaßen: Wenn die Bedingung wahr ist, dann
  führe Anweisung1 aus, sonst führe
  Anweisung2 aus. Dabei kann der else-Teil
  (also else Anweisung2) weggelassen werden. Wichtig ist,
  dass nur hinter den Anweisungen ein Semikolon gesetzt wird aber nicht hinter
  if (Bedingung) und else.
  Beispiel:
   kap06_02.c
  kap06_02.c
  
  01 /***********************************************
  02  * Dieses Programm liest drei ganze Zahlen ein
  03  * und ermittelt das Maximum der drei Zahlen.
  04  * Eingabe: Zahl1, Zahl2, Zahl3
  05  * Ausgabe: Maximum
  06  ***********************************************/
  07 #include <stdio.h>
  08 
  09 int main()
  10 {
  11    long Zahl1, Zahl2, Zahl3, Maximum;
  12 
  13    printf("Dieses Programm ermittelt das Maximum ");
  14    printf("von drei eingegebenen Zahlen.\n");
  15    printf("Bitte geben Sie drei ganze Zahlen ein: ");
  16    scanf("%ld %ld %ld", &Zahl1, &Zahl2, &Zahl3);
  17    if (Zahl1 > Zahl2)
  18       Maximum = Zahl1;
  19    else
  20       Maximum = Zahl2;
  21    if (Zahl3 > Maximum)
  22       Maximum = Zahl3;
  23    printf("Das Maximum der drei Zahlen lautet: ");
  24    printf("%li\n", Maximum);
  25 
  26    return 0;
  27 }
  
  Um anstelle der Anweisung1 und
  Anweisung2 mehrere Anweisungen durchführen zu lassen,
  müssen diese Anweisungen jeweils in einen Block geschrieben werden, d.h. sie
  müssen in geschweifte Klammern gesetzt werden. Die Syntax sieht dann
  folgendermaßen aus:
  
  if (Bedingung)
  {
     Anweisung1a;
     Anweisung1b;
     Anweisung1c;
  }
  else
  {
     Anweisung2a;
     Anweisung2b;
  }
  if-Anweisungen können auch geschachtelt werden. Dabei muss
  allerdings sehr genau darauf geachtet werden, welches else zu welchem
  if gehört. Durch das Einrücken der Anweisungen wird die
  Zugehörigkeit sehr deutlich sichtbar.
  
  if (Bedingung)
  {
     Anweisung1;
     if (Bedingung1)
     {
        Anweisung11a;
        Anweisung11b;
     }
     else
     {
        Anweisung12a;
        Anweisung12b;
     }
  }
  else
  {
     if (Bedingung2)
     {
        Anweisung21a;
        if (Bedingung21)
           Anweisung211;
     }
     else
     {
        Anweisung22a;
        Anweisung22b;
     }
     Anweisung2;
  }
  Beispiel:
   kap06_03.c
  kap06_03.c
  
  01 /***********************************************
  02  * Dieses Programm liest vier ganze Zahlen ein
  03  * und ermittelt das Maximum der vier Zahlen.
  04  * Eingabe: Zahl1, Zahl2, Zahl3, Zahl4
  05  * Ausgabe: Maximum
  06  ***********************************************/
  07 #include <stdio.h>
  08 
  09 int main()
  10 {
  11    long Zahl1, Zahl2, Zahl3, Zahl4, Maximum;
  12 
  13    printf("Dieses Programm ermittelt das Maximum ");
  14    printf("von vier eingegebenen Zahlen.\n");
  15    printf("Bitte geben Sie vier ganze Zahlen ein: ");
  16    scanf("%ld %ld %ld %ld", &Zahl1, &Zahl2, &Zahl3, &Zahl4);
  17    if (Zahl1 > Zahl2)
  18       if (Zahl3 > Zahl4)
  19          if (Zahl1 > Zahl3)
  20             Maximum = Zahl1;
  21          else
  22             Maximum = Zahl3;
  23       else
  24          if (Zahl1 > Zahl4)
  25             Maximum = Zahl1;
  26          else
  27             Maximum = Zahl4;
  28    else
  29       if (Zahl3 > Zahl4)
  30          if (Zahl2 > Zahl3)
  31             Maximum = Zahl2;
  32          else
  33             Maximum = Zahl3;
  34       else
  35          if (Zahl2 > Zahl4)
  36             Maximum = Zahl2;
  37          else
  38             Maximum = Zahl4;
  39    printf("Das Maximum der vier Zahlen lautet: ");
  40    printf("%li\n", Maximum);
  41 
  42    return 0;
  43 }
  
  Eine Mehrfachverzweigung kann als eine Serie von
  if-else-Anweisungen angesehen werden. Dabei ist in
  jedem (außer im letzten) else-Zweig eine weitere
  if-Anweisung enthalten. Dies sieht wie folgt aus:
  
     if (Bedingung1)
        Anweisung1;
     else
        if (Bedingung2)
           Anweisung2;
        else
           if (Bedingung3)
              Anweisung3;
           else
              Anweisung4;
  Dabei kann es bei vielen Verzweigung dazu führen, dass der Quelltext sehr weit nach
  rechts eingerückt wird. Dies führt beim Ausdrucken unter Umständen zu sehr
  unleserlichen Quelltexten und auch auf dem Bildschirm muss unter Umständen viel nach
  links und rechts geblättert werden. Daher sollte die Einrückung bei
  Mehrfachverzweigungen etwas variiert werden:
  
     if (Bedingung1)
        Anweisung1;
     else if (Bedingung2)
        Anweisung2;
     else if (Bedingung3)
        Anweisung3;
     else
        Anweisung4;
  
6.3. Verzweigung: ? : -Anweisung
  Diese Anweisung ist eine Kurzform der if-Anweisung und sieht wie folgt
  aus:
  
  (Bedingung) ? Anweisung1 : Anweisung2;
  
  Die entsprechende if-Anweisung sieht folgendermaßen aus:
  
  if (Bedingung)
     Anweisung1;
  else
     Anweisung2;
  
  Aber nicht nur Anweisungen sondern auch einfache Ausdrücke (wie Zahlen, Zeichen, usw.)
  lassen im Gegensatz zur if-Anweisung hier einsetzen. Als Ergebnis kann
  dann der erste oder der zweite Ausdruck einer Variablen zugeordnet oder in einer Abfrage
  verwendet werden. Dadurch können kleine Verzweigungen in einer Zeile geschrieben
  werden. Das nächste Beispiel greift noch einmal die erste Variante der
  Maximumsbestimmung auf. Jetzt werden aber die if-Anweisungen durch
  ?:-Anweisungen ersetzt.
  Beispiel:
   kap06_04.c
  kap06_04.c
  
  01 /***********************************************
  02  * Dieses Programm liest drei ganze Zahlen ein
  03  * und ermittelt das Maximum der drei Zahlen.
  04  * Eingabe: Zahl1, Zahl2, Zahl3
  05  * Ausgabe: Maximum
  06  ***********************************************/
  07 #include <stdio.h>
  08 
  09 int main()
  10 {
  11    long Zahl1, Zahl2, Zahl3, Maximum;
  12 
  13    printf("Dieses Programm ermittelt das Maximum ");
  14    printf("von drei eingegebenen Zahlen.\n");
  15    printf("Bitte geben Sie drei ganze Zahlen ein: ");
  16    scanf("%ld %ld %ld", &Zahl1, &Zahl2, &Zahl3);
  17    Maximum = (Zahl1 > Zahl2) ? Zahl1 : Zahl2;
  18    Maximum = (Zahl3 > Maximum) ? Zahl3 : Maximum;
  19    printf("Das Maximum der drei Zahlen lautet: ");
  20    printf("%li\n", Maximum);
  21 
  22    return 0;
  23 }
  
6.4. Fallunterscheidung: switch-Anweisung
  Die if-Anweisung ist besonders für Aufgaben geeignet, die nur ein
  oder zwei Bedingungen betreffen. Durch mehrere gleichwertige Bedingungen (d.h. als
  Bedingung wird immer wieder die gleiche Variable abgefragt) wird der Programmcode
  durch die Verschachtelung schnell unübersichtlich. Hierfür gibt es die
  switch-Anweisung. Ihre Syntax sieht wie folgt aus:
  
  switch (Ausdruck)
  {
     case Wert1:
        Anweisungen1;
        break;
     case Wert2:
        Anweisungen2;
        break;
     case Wert3:
        Anweisungen3;
        break;
     ...
     default:
        Ersatzanweisungen;
  }
  Der Datentyp von Ausdruck muß eine ganze Zahl (int)
  sein oder muss sich in eine ganze Zahl umwandeln lassen, z.B. ein Zeichen
  (char). Reelle Zahlen und Zeichenketten sind nicht zugelassen!
  Die Werte hinter dem case müssen konstante Werte sein. Dabei
  können die Werte als ganze Zahl oder als Zeichen angegeben werden.
  Mit Hilfe des break; wird die switch-Anweisung
  beendet. Andernfalls werden die Anweisungen der weiteren case-Zeilen
  auch durchgeführt. Dieses kann auch dazu verwendet werden, um verschiedenen Fälle
  zusammenzufassen, d.h. in verschiedenen Fällen werden die gleichen Anweisungen
  ausgeführt (siehe das folgende Beispiel).
  Beispiel:
   kap06_05.c
  kap06_05.c
  
  01 /***********************************************
  02  * Dieses Programm fragt das Geschlecht ab und
  03  * gibt das Ergebnis auf dem Bildschirm aus.
  04  * Eingabe: Geschlecht
  05  * Ausgabe: "weiblich" oder "maennlich"
  06  ***********************************************/
  07 #include <stdio.h>
  08 
  09 int main()
  10 {
  11    char Geschlecht;
  12 
  13    printf("Geben Sie bitte Ihr Geschlecht ein.\n");
  14    printf("(w: weiblich, m: maennlich): ");
  15    scanf("%c", &Geschlecht);
  16    switch (Geschlecht)
  17    {
  18       case 'w':
  19       case 'W':
  20          printf("weiblich\n");
  21          break;
  22       case 'm':
  23       case 'M':
  24          printf("maennlich\n");
  25          break;
  26       default:
  27          printf("keine Angabe\n");
  28    }
  29 
  30    return 0;
  31 }
  
  Neben der break-Anweisung kann die switch-Anweisung
  auch mit den Anweisungen continue (siehe Abschnitt break und continue
  in diesem Kapitel), goto und return beendet
  werden.
  Die Reihenfolge, in der der switch-Ausdruck mit den
  case-Ausdrücken verglichen wird, ist nicht definiert. Auch die
  Umsetzung der Vergleiche in die Maschinensprache hängt von der Anzahl und den Werten
  der case-Ausdrücke ab. D.h., die switch-Anweisung
  kann nicht als Folge von if-Anweisungen angesehen werden!
  Die Anzahl der case-Ausdrücke, die in einer
  switch-Anweisung verwendet werden dürfen, ist begrenzt. In C89
  dürfen maximal 257, in C99 maximal 1023 case-Ausdrücke verwendet
  werden.
  Obwohl für den Datentypen des Ausdrucks alle Typen von ganzen Zahlen zugelassen sind, gibt
  es einige ältere Compiler, die die Datentypen long und
  unsigned long für den Ausdruck nicht zulassen.
  
6.5. Schleifen: while-Schleifen
  Soll ein Programmteil mehrmals wiederholt werden, wird eine sogenannte
  Schleife verwendet. In C gibt es drei verschiedene Schleifen:
  while-, do-while- und
  for-Schleifen. Die beiden letzten lassen sich auch durch die
  while-Schleife darstellen.
  Die while-Schleife hat folgende Syntax:
  while (Bedingung)
     Anweisung;
  Ähnlich wie bei der if-Anweisung sollte die
  Anweisung eingerückt werden, um schneller zu erkennen, an
  welcher Stelle die while-Schleife zu Ende ist. Sollen mehrere
  Anweisungen in einer Schleife wiederholt werden, werden diese (wie bei der
  if-Anweisung) in einen Block geschrieben. Dies sieht dann wie folgt
  aus:
  while (Bedingung)
  {
     Anweisung1;
     Anweisung2;
     Anweisung3;
  }
  Dabei wird die Anweisung bzw. der Anweisungsblock so lange
  wiederholt ausgeführt, bis die Bedingung nicht mehr wahr ist. Ist die
  Bedingung von vornherein nicht erfüllt, wird die
  Anweisung bzw. der Anweisungsblock in der
  while-Schleife überhaupt nicht ausgeführt. Anders herum: Wird
  die Bedingung niemals falsch, wird die Schleife auch niemals beendet. Dies wird eine
  Endlosschleife genannt.
  Beispiel:
   kap06_06.c
  kap06_06.c
  
  01 /*******************************************
  02  * Dieses Programm berechnet die Fakultaet
  03  * einer eingegebenen Zahl und gibt das
  04  * Ergebnis auf dem Bildschirm aus.
  05  * Eingabe: Zahl
  06  * Ausgabe: Fakult
  07  *******************************************/
  08 #include <stdio.h>
  09 
  10 int main()
  11 {
  12    unsigned int Zahl, Zaehler = 1;
  13    unsigned long Fakult = 1;
  14 
  15    printf("Dieses Programm berechnet die ");
  16    printf("Fakultaet einer ganzen Zahl.\n");
  17    printf("Geben Sie bitte eine ganze Zahl ein: ");
  18    scanf("%d", &Zahl);
  19    while (Zaehler <= Zahl)
  20    {
  21       Fakult = Fakult * Zaehler;
  22       Zaehler++;
  23    }
  24    printf("%u! = %lu\n", Zahl, Fakult);
  25 
  26    return 0;
  27 }
  
  Mit Hilfe der Kurzform-Operatoren und der Inkrementierung von Variablen kann die
  while-Schleife (Zeile 19 bis 23) drastisch verkürzt werden:
  
     while (Zaehler <= Zahl)
        Fakult *= Zaehler++;
  Genauso wie if-Anweisungen lassen sich
  while-Schleifen schachteln. Auch hierbei hilft das Einrücken der
  Anweisungen innerhalb der Schleife, um den Überblick über die jeweiligen
  Schleifenenden zu haben. Im folgenden Beispiel wird um die Schleife der
  Fakultätsberechnung eine weitere Schleife herumgelegt.
  Beispiel:
   kap06_07.c
  kap06_07.c
  
  01 /*******************************************
  02  * Dieses Programm berechnet die Fakultaet
  03  * einer eingegebenen Zahl und gibt das
  04  * Ergebnis auf dem Bildschirm aus.
  05  * Eingabe: Zahl
  06  * Ausgabe: Fakult
  07  *******************************************/
  08 #include <stdio.h>
  09 
  10 int main()
  11 {
  12    unsigned int Zahl, Zaehler;
  13    unsigned long Fakult;
  14    char c = 'j';
  15 
  16    printf("Dieses Programm berechnet die ");
  17    printf("Fakultaet einer ganzen Zahl.\n");
  18    while (c == 'j' || c == 'J')
  19    {
  20       printf("Geben Sie bitte eine ganze Zahl ein: ");
  21       scanf("%d", &Zahl);
  22 
  23       Zaehler = 1;
  24       Fakult = 1;
  25       while (Zaehler <= Zahl)
  26          Fakult *= Zaehler++;
  27       printf("%u! = %lu\n", Zahl, Fakult);
  28       printf("Moechten Sie eine weitere Zahl ");
  29       printf("berechnen? (j/n) ");
  30       c = 0;
  31       while (c != 'j' && c != 'J' && c != 'n' && c != 'N')
  32          scanf("%c", &c);
  33    }
  34 
  35    return 0;
  36 }
  
  Im Gegensatz zum vorigen Beispielprogramm ist zu beachten, dass es jetzt nicht mehr
  ausreicht, die Variablen Zaehler und Fakult
  einmalig mit 1 zu initialisieren. Da die Berechnung mehrmals
  durchgeführt werden kann, ist es wichtig, diese beiden Variablen direkt vor
  der Berechnung auf den Startwert zu setzen.
  Bei der äußeren while-Schleife ist es von Nachteil,
  dass die Variable c zuvor mit dem Zeichen 'j'
  initialisiert sein muss. Dies ist bei der do-while-Schleife
  anders.
  
6.6. Schleifen: do-while-Schleifen
  Bei der do-while-Schleife ist die Abfrage der Bedingung am Ende.
  Dadurch wird die Anweisung bzw. der Anweisungsblock innerhalb der Schleife auf jeden
  Fall mindestens einmal ausgeführt (Motto: Erst zuschlagen, dann fragen), während bei
  der while-Schleife die Anweisung bzw. der Anweisungsblock bei
  falscher Bedingung überhaupt nicht ausgeführt wird. Die Syntax für
  die do-while-Schleife sieht folgendermaßen aus:
  do
     Anweisung;
  while (Bedingung);
  Entsprechend die Syntax mit einem Anweisungsblock:
  do
  {
     Anweisung1;
     Anweisung2;
     Anweisung3;
  } while (Bedingung);
  Wichtig: Im Gegensatz zur while-Schleife wird hier
  hinter while (Bedingung); ein Semikolon gesetzt!
  Im folgenden Beispiel werden zwei der drei while-Schleifen vom vorigen
  Beispiel durch do-while-Schleifen ersetzt. Dadurch fällt die
  Initialisierung der Variablen in der Bedingung weg.
  Beispiel:
   kap06_08.c
  kap06_08.c
  
  01 /*******************************************
  02  * Dieses Programm berechnet die Fakultaet
  03  * einer eingegebenen Zahl und gibt das
  04  * Ergebnis auf dem Bildschirm aus.
  05  * Eingabe: Zahl
  06  * Ausgabe: Fakult
  07  *******************************************/
  08 #include <stdio.h>
  09 
  10 int main()
  11 {
  12    unsigned int Zahl, Zaehler;
  13    unsigned long Fakult;
  14    char c;
  15 
  16    printf("Dieses Programm berechnet die ");
  17    printf("Fakultaet einer ganzen Zahl.\n");
  18    do
  19    {
  20       printf("Geben Sie bitte eine ganze Zahl ein: ");
  21       scanf("%d", &Zahl);
  22 
  23       Zaehler = 1;
  24       Fakult = 1;
  25       while (Zaehler <= Zahl)
  26          Fakult *= Zaehler++;
  27       printf("%u! = %lu\n", Zahl, Fakult);
  28       printf("Moechten Sie eine weitere Zahl ");
  29       printf("berechnen? (j/n) ");
  30       do
  31          scanf("%c", &c);
  32       while (c != 'j' && c != 'J' && c != 'n' && c != 'N');
  33    } while (c == 'j' || c == 'J');
  34 
  35    return 0;
  36 }
  
6.7: Schleifen: for-Schleifen
  Die dritte Schleife ist die for-Schleife und ist eine sogenannte
  Zählschleife. Der Name kommt daher, dass ursprünglich
  bei dieser Schleifenform mit Hilfe einer Zahlenvariablen mitgezählt wurde, wie oft
  die Schleife ausgeführt werden soll. Entsprechend wird in der Bedingung die
  Zahlenvariable abgefragt, ob die gewünschte Anzahl von Schleifendurchläufen
  bereits erreicht ist. In C/C++ sieht die for-Schleife etwas anders aus
  als in anderen Programmiersprachen. Dadurch ist es möglich, auch
  for-Schleifen ohne Zähler zu konstruieren.
  Die Syntax sieht folgendermaßen aus:
  for ([Variablen-Initialisierung];[Bedingung];[Veränderung])
     Anweisung;
  bzw. mit mehreren Anweisungen in einem Anweisungsblock:
  for ([Variablen-Initialisierung];[Bedingung]; [Veränderung])
  {
     Anweisung1;
     Anweisung2;
     Anweisung3;
  }
  Das folgende Beispiel gibt alle Buchstaben von 'A' bis 'Z' auf dem Bildschirm aus. In
  diesem Fall ist die Zählvariable die char-Variable
  c.
  Beispiel:
   kap06_09.c
  kap06_09.c
  
  01 /********************************************
  02  * Dieses Programm gibt alle Buchstaben von
  03  * 'A' bis 'Z' auf dem Bildschirm aus.
  04  ********************************************/
  05 #include <stdio.h>
  06 
  07 int main()
  08 {
  09    char c;
  10 
  11    printf("Dieses Programm gibt alle Buchstaben ");
  12    printf("von 'A' bis 'Z' aus.\n");
  13    for (c = 'A'; c <= 'Z'; c++)
  14       printf("%c ", c);
  15    printf("\n");
  16 
  17    return 0;
  18 }
  
  In der Syntax sind die Variablen-Initialisierung, die Bedingung und die
  Veränderung jeweils in eckigen Klammern angegeben, d.h. sie sind optional. So
  kann zum Beispiel die Variablen-Initialisierung entfallen, wenn die Variablen
  bereits vorher initialisiert wurden. Die Veränderung des Zählers kann
  entfallen, z.B. wenn er innerhalb der Schleife verändert wird. Auch die Bedingung kann
  weggelassen werden, allerdings ist dann die Schleife eine Endlosschleife! Im folgenden
  Beispiel werden Variablen-Initialisierung und Veränderung weggelassen
  (oder besser gesagt: an andere Stellen umgesetzt). Trotzdem müssen die Semikolons
  gesetzt werden.
  Beispiel:
   kap06_10.c
  kap06_10.c
  
  01 /********************************************
  02  * Dieses Programm gibt alle Buchstaben von
  03  * 'A' bis 'Z' auf dem Bildschirm aus.
  04  ********************************************/
  05 #include <stdio.h>
  06 
  07 int main()
  08 {
  09    char c = 'A'; /* Variablen-Initialisierung */
  10 
  11    printf("Dieses Programm gibt alle Buchstaben ");
  12    printf("von 'A' bis 'Z' aus.\n");
  13    for ( ; c <= 'Z'; )
  14       printf("%c ", c++);
  15    printf("\n");
  16 
  17    return 0;
  18 }
  
  Für Variablen-Initialisierung, Bedingung und Veränderung
  können aber auch mehrere Einträge gemacht werden. Diese müssen mit
  Kommata voneinander getrennt werden (siehe Abschnitt Sequenzen am Anfang dieses Kapitels).
  Werden mehrere Befehle oder Abfragen als Bedingung angegeben, muss darauf geachtet werden,
  dass nur das Ergebnis des letzten Befehls bzw. der letzten Abfrage für die Bedingung
  verwendet wird. Im folgenden Beispiel wird eine Berechnung innerhalb einer
  for-Schleife in mehreren Schritten so weit verkürzt, dass
  keine Anweisung innerhalb der Schleife mehr übrigbleibt. In diesem Fall muss ein
  Semikolon (sozusagen eine Leeranweisung) als Anweisung für die
  for-Schleife gesetzt werden.
  Beispiel:
   kap06_11.c
  kap06_11.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    unsigned long a, b = 1, c = 1;
  06    /* a wird in der for-Schleife initialisiert */
  07 
  08    printf("         a |          b |          c\n");
  09    printf("-------------------------------------\n");
  10    for (a = 1; a < 10; a = a + 1)
  11    {
  12       b = b * c;
  13       c = c + a;
  14       printf("%10lu | %10lu | %10lu\n", a, b, c);
  15       c = c + 1;
  16    }
  17    printf("-------------------------------------\n");
  18 
  19    return 0;
  20 }
  
  Im ersten Schritt beim Verkürzen der for-Schleife werden die
  Kurzform-Operatoren eingesetzt. Ferner werden auch die Startwerte der Variablen
  b und c in der for-Schleife
  gesetzt.
   kap06_12.c
  kap06_12.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    unsigned long a, b, c;
  06 
  07    printf("         a |          b |          c\n");
  08    printf("-------------------------------------\n");
  09    for (a = 1, b = 1, c = 1; a < 10; a++)
  10    {
  11       b *= c;
  12       c += a;
  13       printf("%10lu | %10lu | %10lu\n", a, b, c);
  14       c++;
  15    }
  16    printf("-------------------------------------\n");
  17 
  18    return 0;
  19 }
  
  Im zweiten Schritt werden die Initialisierungen zu einer zusammengefasst.
  Außerdem wird das c++ zu den Veränderungen
  verschoben.
   kap06_13.c
  kap06_13.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    unsigned long a, b, c;
  06 
  07    printf("         a |          b |          c\n");
  08    printf("-------------------------------------\n");
  09    for (a = b = c = 1; a < 10; a++, c++)
  10    {
  11       b *= c;
  12       c += a;
  13       printf("%10lu | %10lu | %10lu\n", a, b, c);
  14    }
  15    printf("-------------------------------------\n");
  16 
  17    return 0;
  18 }
  
  Im letzten Schritt werden die drei Anweisungen in die Bedingung verschoben. Wichtig
  ist, dass die ursprüngliche Bedingung die letzte ist. Nun werden aber vor der
  Abfrage der Bedingung die drei Anweisungen ausgeführt. Der Ablauf ist damit
  ähnlich wie bei der do-while-Schleife. Deshalb muss die
  Anzahl der Schleifendurchgänge um eins verringert werden.
   kap06_14.c
  kap06_14.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    unsigned long a, b, c;
  06 
  07    printf("         a |          b |          c\n");
  08    printf("-------------------------------------\n");
  09    for (a = b = c = 1; b *= c, c += a, printf("%10lu | %10lu | "
  10                            "%10lu\n", a, b, c), a < 9; a++, c++)
  11       ;
  12    printf("-------------------------------------\n");
  13 
  14    return 0;
  15 }
  
  Natürlich ist diese komprimierte Schreibweise nicht sehr leserlich, sehr
  fehleranfällig und daher auch nicht zu empfehlen!
  Genau wie bei den beiden anderen Schleifenformen können auch
  for-Schleifen beliebig verschachtelt werden. Zur besseren
  Übersicht sollten auch hier die Anweisungen innerhalb der Schleife eingerückt
  werden.
  
6.8: break und continue
  Mit den Befehlen break und continue gibt es noch
  zwei Befehle, mit denen der Ablauf innerhalb von Schleifen beeinflusst werden kann.
  Der break-Befehl wurde bereits in der
  switch-Anweisung verwendet, um aus dieser herauszuspringen. Genauso ist
  es auch bei den Schleifen: Mit Hilfe des break-Befehls wird die
  Schleife unabhängig von der Bedingung beendet und mit dem nächsten Befehl
  nach der Schleife fortgefahren. Dies gilt für alle drei Schleifenformen. Als Beispiel
  dient noch einmal das Programm zur Berechnung der Fakultät.
  Beispiel:
   kap06_15.c
  kap06_15.c
  
  01 /*******************************************
  02  * Dieses Programm berechnet die Fakultaet
  03  * einer eingegebenen Zahl und gibt das
  04  * Ergebnis auf dem Bildschirm aus.
  05  * Eingabe: Zahl
  06  * Ausgabe: Fakult
  07  *******************************************/
  08 #include <stdio.h>
  09 
  10 int main()
  11 {
  12    unsigned int Zahl, Zaehler;
  13    unsigned long Fakult;
  14    char c;
  15 
  16    printf("Dieses Programm berechnet die ");
  17    printf("Fakultaet einer ganzen Zahl.\n");
  18    while (1) /* 1 => Wahr => Endlosschleife! */
  19    {
  20       printf("Geben Sie bitte eine ganze Zahl ein: ");
  21       scanf("%d", &Zahl);
  22 
  23       Zaehler = 1;
  24       Fakult = 1;
  25       while (Zaehler <= Zahl)
  26          Fakult *= Zaehler++;
  27       printf("%u! = %lu\n", Zahl, Fakult);
  28       printf("Moechten Sie eine weitere Zahl ");
  29       printf("berechnen? (j/n) ");
  30       do
  31          scanf("%c", &c);
  32       while (c != 'j' && c != 'J' && c != 'n' && c != 'N');
  33       if (c == 'n' || c == 'N')
  34          break;    /* hier wird die Schleife verlassen */
  35    }
  36 
  37    return 0;
  38 }
  
  Der continue-Befehl ist mehr oder weniger das Gegenteil des
  break-Befehls: Mit ihm wird zum Ende des Schleifenkörpers gesprungen.
  Bei while- und do-while-Schleifen wird nach
  continue die Bedingung abgefragt, bei
  for-Schleifen wird nach continue erst die
  Veränderung aufgerufen und dann die Bedingung abgefragt.
  Als Beispiel wird das Programm zur Berechnung der Fakultät erweitert: Nach der
  Benutzereingabe der ganzen Zahl wird diese geprüft, ob sie größer oder
  gleich eins ist. Wenn nicht, wird mit continue die Schleife neu
  gestartet.
  Beispiel:
   kap06_16.c
  kap06_16.c
  
  01 /*******************************************
  02  * Dieses Programm berechnet die Fakultaet
  03  * einer eingegebenen Zahl und gibt das
  04  * Ergebnis auf dem Bildschirm aus.
  05  * Eingabe: Zahl
  06  * Ausgabe: Fakult
  07  *******************************************/
  08 #include <stdio.h>
  09 
  10 int main()
  11 {
  12    int Zahl, Zaehler;
  13    unsigned long Fakult;
  14    char c;
  15 
  16    printf("Dieses Programm berechnet die ");
  17    printf("Fakultaet einer ganzen Zahl.\n");
  18    while (1) /* 1 => Wahr => Endlosschleife! */
  19    {
  20       printf("Geben Sie bitte eine ganze Zahl ein: ");
  21       scanf("%d", &Zahl);
  22       if (Zahl < 1)
  23          continue;   /* Schleife von vorne beginnen */
  24       Zaehler = 1;
  25       Fakult = 1;
  26       while (Zaehler <= Zahl)
  27          Fakult *= Zaehler++;
  28       printf("%u! = %lu\n", Zahl, Fakult);
  29       printf("Moechten Sie eine weitere Zahl ");
  30       printf("berechnen? (j/n) ");
  31       do
  32          scanf("%c", &c);
  33       while (c != 'j' && c != 'J' && c != 'n' && c != 'N');
  34       if (c == 'n' || c == 'N')
  35          break;   /* hier wird die Schleife verlassen */
  36    }
  37 
  38    return 0;
  39 }
  
6.9: goto
  So wie im guten alten Basic gibt es auch in C/C++ den goto-Befehl. Im
  Normalfall kommt man ohne diesen Befehl aus, aber es gibt ja immer die berühmten
  Ausnahmen. Generell werden Programme mit goto-Befehlen sehr schnell
  unübersichtlich!
  Die Syntax lautet:
  goto Labelname;
  Dabei ist Labelname ein beliebiger Name, der irgendwo im Programm (zumindest in
  der gleichen Funktion!) definiert sein muss. Ein Label wird ganz einfach definiert.
  Dazu wird der Labelname gefolgt von einem Doppelpunkt vor den Befehl bzw. vor die
  Anweisung geschrieben, zu der der goto-Befehl springen soll. Damit
  diese Labels später schneller wiedergefunden werden, sollten sie direkt an den Anfang
  der Zeile geschrieben werden. Der Befehl dahinter bleibt wie bisher
  eingerückt.
  Als Beispiel wird das vorige Programm genommen. Hier wird der
  continue-Befehl durch den goto-Befehl ersetzt. Das
  Label wird vor der ersten Anweisung in der while-Schleife
  geschrieben.
  Beispiel:
   kap06_17.c
  kap06_17.c
  
  01 /*******************************************
  02  * Dieses Programm berechnet die Fakultaet
  03  * einer eingegebenen Zahl und gibt das
  04  * Ergebnis auf dem Bildschirm aus.
  05  * Eingabe: Zahl
  06  * Ausgabe: Fakult
  07  *******************************************/
  08 #include <stdio.h>
  09 
  10 int main()
  11 {
  12    int Zahl, Zaehler;
  13    unsigned long Fakult;
  14    char c;
  15 
  16    printf("Dieses Programm berechnet die ");
  17    printf("Fakultaet einer ganzen Zahl.\n");
  18    while (1) /* 1 => Wahr => Endlosschleife! */
  19    {
  20 neu:  printf("Geben Sie bitte eine ganze Zahl ein: ");
  21       scanf("%d", &Zahl);
  22       if (Zahl < 1)
  23          goto neu;   /* Schleife von vorne beginnen */
  24       Zaehler = 1;
  25       Fakult = 1;
  26       while (Zaehler <= Zahl)
  27          Fakult *= Zaehler++;
  28       printf("%u! = %lu\n", Zahl, Fakult);
  29       printf("Moechten Sie eine weitere Zahl ");
  30       printf("berechnen? (j/n) ");
  31       do
  32          scanf("%c", &c);
  33       while (c != 'j' && c != 'J' && c != 'n' && c != 'N');
  34       if (c == 'n' || c == 'N')
  35          break;   /* hier wird die Schleife verlassen */
  36    }
  37 
  38    return 0;
  39 }
  
  Ein sehr gefährliches Feature der goto-Anweisung ist die
  Möglichkeit, mitten in Blöcke springen zu können. Dabei wird auch die
  Initialisierung von Variablen, die am Blockanfang definiert werden, übersprungen
  (zumindest von den meisten Compilern). Das Ergebnis ist, dass der Inhalt der Variablen
  nicht vorhersehbar ist.
  Beispiel:
   kap06_18.c
  kap06_18.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    goto Label;
  06 
  07    {
  08       int Zahl = 10;
  09 
  10 Label:
  11       printf("Zahl = %i\n", Zahl); // irgendeine Zahl wird ausgegeben!
  12    }
  13 
  14    return 0;
  15 }
  
  
  Voriges Kapitel: 5. Einfache Ein- und Ausgabe in C
  
Nächstes Kapitel: 7. Strukturierte Datentypen

