Schleifen/Iterationen

Einleitung

Angenommen, man möchte ein Programm entwickeln, dass an einer Stelle die gleichen Befehle mehrmals wiederholen muss. Wie geht man vor? Eine Möglichkeit wäre, diese Befehle immer wieder in den Quelltext hineinzuschreiben. Sollen diese Befehle nur zweimal abgearbeitet werden, ist das kein Problem. Sollen diese Anweisungen aber wesentlich häufiger wiederholt werden, für diese Möglichkeit zu einem großen Chaos. Quelltexte werden so unendlich lang und die Gefahr von Programmierfehlern steigt drastisch. Deswegen wurden sogenannte Schleifen entwickelt. Man nennt diese auch Iterationen. Es gibt drei Arten von Schleifen: Die Kopfgesteuerte, die Fußgesteuerte und die Zählschleife.

Kopfgesteuerte Schleifen

Die Kopfgesteuerte ist die am häufigsten verwendete Schleife. Sie ist folgendermaßen aufgebaut:

  while([Ausdruck])
  {
    /* Zu wiederholende Anweisung */
  }

Das Wort while bedeutet soviel wie 'solange'. Daraus kann man folgenden Satz schlussfolgern: „Solange die Bedingung erfüllt ist, wiederhole die Anweisung.“ Schleifen können, ähnlich wie Wenn-dann-sonst-Anweisungen, sowohl eine zu wiederholende Anweisung, als auch einen zu wiederholenden Block aus geschweiften Klammern enthalten. Das folgende Beispiel demonstriert ein Programm, welches zehnmal den Text „Hello World“ ausgibt:

  #include <stdio.h>
 
  int main()
  {
    int i = 0;  /* Schleifenzähler */
 
    while( i < 10 )  /* Durchlaufbedingung */
    {
      printf( "Hello World\n" );
      i = i + 1;  /* Erhöhung des Zählers */
    }
 
    return 0;
  }

In diesem Beispiel wird ein Schleifenzähler benötigt. Dieser ist eine Variable, üblich vom Typ int, welche dafür sorgt, dass der Ausdruck falsch wird. Ansonsten würde es zu einer Endlosschleife führen, welche nur durch einen manuellen Abbruch beendet werden kann. Namen wie i, j und k werden sehr häufig für Schleifenzähler verwendet. Deswegen sollte man diese Bezeichner nicht für andere Variablen nehmen. Der Ausdruck i = i + 1 ist rein mathematisch gesehen, völlig falsch. Programmiertechnisch ist das aber eine gültige Anweisung. Zur Erinnerung: Das einfache Gleichheitszeichen ist in C ein Zuweisungsoperator. Daraus folgt, dass die Variable i um eins erhöht wird. Nun eine genauere Ablaufbeschreibung:

  while( i < 10 )

In dieser Anweisung wird geprüft, ob der Ausdruck wahr ist. Dazu muss der Schleifenzähler i kleiner als 10 sein. Nach der Überprüfung führt die Schleife die Anweisungen im Block durch. Also die Ausgabe von „Hello World“ und die Erhöhung des Zählers. Danach springt das Programm zu dem Schleifenkopf zurück und überprüft nochmals den Ausdruck. Ist der Ausdruck falsch, also der Wert gleich zehn, so springt das Programm in die nächste Zeile nach der Schleife. Da der Zähler mit dem Wert 0 initialisiert wird, läuft die Schleife zehnmal durch.

Das alles mag vielleicht etwas kompliziert klingen, ist aber, wenn man es verstanden hat, sehr einfach.

Hier noch eine Zusammenfassung der kopfgesteuerten Schleife: Das Programm prüft im Schleifenkopf die den Ausdruck. Ist dieser wahr, so führt es die Anweisungen im Rumpf aus.Danach springt es zurück zum Schleifenkopf und prüft wieder den Ausdruck. Das geht solange weiter, bis der Ausdruck falsch ist.

Die kopfgesteuerte Schleife sollte man immer dann verwenden, wenn es möglich sein könnte, dass ihr Inhalt gar nicht ausgeführt werden soll.

Fußgesteuerte Schleifen

Die fußgesteuerte Schleife wird eher selten verwendet, kann aber trotzdem äußerst nützlich sein. Ziel der fußgesteuerten Schleife ist es, im Gegensatz zur Kopfgesteuerten, ihren Inhalt mindestens einmal auszuführen. Die Syntax sieht folgendermaßen aus:

  do
  {
    /* Anweisung */
  }
  while([Ausdruck]);

Hinweis: Am Ende der Schleife muss ein Semikolon stehen. Wie man sieht, beginnt diese Schleife direkt mit der Anweisung und überprüft erst danach den Ausdruck. Also wird die Anweisung mindestens einmal ausgeführt. Diese Abfrage befindet sich nicht mehr im Kopf, sondern im Fuß. Daher ist es eine fußgesteuerte Schleife. Auch hier ein Beispiel, was zehnmal „Hello World“ ausgibt:

  #include <stdio.h>
 
  int main()
  {
    int i = 0;
 
    do
    {
      printf( "Hello World\n" );
      i = i + 1;
    }
    while( i < 10 );
 
    return 0;
  }

Hier eine Ablaufbeschreibung: Das Schlüsselwort „do“ macht dem Programm deutlich, dass es sich hier um einen Schleifenrumpf handelt. Die Anweisungen werden nun ausgeführt. Im Fuß, also while(i<10) wird nun der Ausdruck geprüft. Ist diese wahr, springt das Programm wieder zu der Zeile, die nach dem do erscheint.

Zählschleifen

Die Zählschleife ist eine besondere Form der kopfgesteuerten Schleifen. Die Syntax sieht folgendermaßen aus:

  for([Zählerinitialisierung];[Ausdruck];[Schlussanweisung])
  {
    /* Anweisung */
  }

Das sieht jetzt ziemlich verwirrend aus, ist aber recht einfach. Auch hier ein Beispiel, das „Hello World“ zehnmal ausgibt.

  #include <stdio.h>
 
  int main()
  {
    int i;
 
    for( i = 0; i < 10; i++ )
      printf( "Hello World\n" );
 
    return 0;
  }

Innerhalb des Schleifenkopfes befinden sich drei verschiedene Arten von Befehlen. Der erste Teil, welcher nur einmal ausgeführt wird, initialisiert den Zähler, der zweite Teil ist der Ausdruck und der dritte Teil ist die Anweisung, die in einem Durchlauf zuletzt ausgeführt wird. Nun der Ablauf: Der Zähler wird initialisiert. Danach wird der Ausdruck überprüft. Die Ausgabe wird ausgeführt und erst jetzt wird der Zähler erhöht. Es ist nicht notwendig, alle drei Arten von Anweisungen zu schreiben. So könnte man z.B. die Schleife auch verwenden:

  #include <stdio.h>
 
  int main()
  {
    int i = 0;
 
    for( ; i < 10; i++ )
      printf("Hello World\n");
 
    return 0;
  }

Auffällig ist, dass am Anfang des Kopfes ein Semikolon steht. Es ist zwar nicht notwendig, die Anweisungen zu schreiben, trotzdem müssen mindestens zwei Semikolons im Kopf stehen. Die folgende Schleife wäre also eine Endlosschleife, ließe sich aber trotzdem kompilieren:

  for(;;)
    printf("Hello World\n");

break

Manchmal ist es nicht unbedingt sinnvoll, eine Schleife nur durch den Ausdruck zu beenden. Das kann z.B. dann vorkommen, wenn eine weitere Abbruchbedingung nicht im Kopf definiert wurde. In diesem Fall hilft der Befehl 'break'. Erscheint dieser Befehl, wird die Schleife abgebrochen.

continue

Es kann vorkommen, dass bestimmte Anweisungen in einem Schleifenrumpf nicht bei jedem Durchlauf ausgeführt werden sollen. Dabei hilft das Schlüsselwort 'continue'. Es ist eine Sprunganweisung. Wird dieser Befehl ausgewertet, springt die Schleife wieder zum Anfang. Dabei ist es egal, ob noch einige Anweisungen folgen.

Geschachtelte Schleifen

Schleifen lassen sich natürlich auch schachteln. Das folgende Beispielprogramm gibt jeweils in zehn Spalten und zehn Zeilen ein Pluszeichen aus:

  #include <stdio.h>
 
  int main()
  {
      int i, j;
      for( i = 0; i < 10; i++ )     /* Äußere Schleife */
      { 
          for( j = 0; j < 10; j++ ) /* Innere Schleife */
              printf("+");
 
          printf("\n");
      }
  }

Hierbei wird der Kopf der äußeren Schleife zuerst ausgewertet, danach der der inneren Schleife. Nun wird die innere Schleife komplett ausgeführt, danach der Rest der äußeren. Das gleiche geschieht danach noch neun Mal. Schleifen lassen sich noch tiefer schachteln, was aber eher seltener vorkommt. Je häufiger eine Schleife geschachtelt ist, umso größer die Gefahr einer Endlosschleife. Ist eine Schleife beispielsweise vierfach geschachtelt, so kann der Quelltext schnell unübersichtlich werden, wenn jede dieser Schleifen ein break enthält. Dagegen kann der Befehl goto, welcher in einem späteren Kapitel behandelt wird, helfen.


|Autorendiskussion