C-Tutorial (C oder C++, Vorwort, Installation, Kapitel 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)

Schleifen

8.1. for-Schleife

Schleifen gehören zu den Kontrollstrukturen. Ihr Zweck ist, Anweisungen kontrolliert oft wiederholen zu lassen. Das heißt, eine Anweisung oder ein Anweisungsblock (der sog. Schleifenrumpf) wird so oft ausgeführt, solange eine angegebene Bedingung erfüllt ist.

In C stehen drei verschiedene Schleifen zur Verfügung: Die for-, die while- und die do-while-Schleife.

In (fast) jeder Programmiersprache existiert eine Zählschleife. In C trifft das am meisten auf die for-Schleife zu, wobei sich alle Schleifentypen als Zählschleife einsetzen lassen. Dazu benötigt man zunächste eine Variable, die mitzählt, wie oft die Schleife bereits durchlaufen wurde: Die Zählervariable. Sie wird zu Beginn, wenn aufwärts gezählt werden soll, häufig mit 0 (Null) initialisiert. Hier ist aber auch 1 oder jeder andere Wert möglich. In der Informatik wird oft bei 0 (und nicht 1) zu zählen begonnen, daher ist 0 gebräuchlich.

Daneben benötigen Sie eine Bedingung, die erfüllt sein muss, solange die Schleife läuft. Die Bedingung ist ein Ausdruck, wie Sie ihn schon aus Kapitel 6 kennen. Ist die Bedingung beim nächsten Durchlauf nicht mehr erfüllt, wird der Schleifenrumpf nicht (nochmal) ausgeführt, und die Programmausführung geht - darunter - normal weiter.

Die Syntax der for-Schleife sieht allgemein folgendermaßen aus:

for (Initialisierung(en); Bedingung(en); Danach)
  Anweisung;

Ein Beispiel wäre:

for (i = 1; i <= 10; i++)
  printf ("%d\n",i);

Das Beispiel zählt von 1 bis 10 und gibt die Werte untereinander aus. Die Variable i ist der Schleifenzähler und muss vor der Ausführung bereits deklariert worden sein. Zunächst wird i mit 1 initialisiert, d.h. i bekommt den Wert 1 zugewiesen. Dafür sorgt der erste Teil des Schleifenkopfes (der Teil vom ersten Semikolon). Danach folgt die Bedingung, im Beispiel ist das i <= 10, gefolgt von einem Semikolon. Solange die Bedingung erfüllt ist, wird immer wieder die Zeile printf ("%d ",i); ausgeführt!

Der dritte Teil ist eine Anweisung, die ausgeführt wird, nachdem der Schleifenrumpf durchlaufen wurde. Hier wird der Wert von i um 1 erhöht (inkrementiert). Danach beginnt der Ablauf wieder von vorne: Die Bedingung wird überprüft. Ist sie wahr, wird der Anweisungsblock (Schleifenrumpf) ausgeführt. i wird erneut inkrementiert, es wird wieder die Bedingung überprüft, usw.

Selbstverständlich kann statt einer Zeile auch ein Anweisungsblock mit { } angegeben werden. Zählen, so lange es der Benutzer wünscht:

#include <stdio.h>
 
int main()
{
  int abbruch, i;   /* Wichtig: i deklarieren! */
 
  printf ("Zählen von 0 bis (inklusive): ");
  scanf ("%d",&abbruch);
 
  for (i = 0; i <= abbruch; i++)
  {    /* Anweisungsblock, hier nur mit einer Zeile */
    printf ("%d\n", i);
  }
 
  return 0;
}

Als Zählervariable wurde i verwendet, was in der Programmierung üblich ist. Für weitere Zählervariablen verwendet man dann häufig j, k, l usw. Als Bedingung wurde i <= abbruch angegeben. Die Schleife läuft so lange, so lange i kleiner oder gleich dem Wert von abbruch ist.

Es muss jedoch nicht alles angegeben werden. Sogar die folgende Variante ist gültig:

for (;;)
  ;

Hierbei ist lediglich darauf zu achten, dass in Klammer zwei Semikolone stehen bleiben. Da keine Bedingung angegeben wurde, handelt es sich hierbei um eine Endlosschleife. Sie wird so lange laufen, bis das Programm "brutal" gestoppt wird. Das geht unter Linux einfach mit Strg+C, kann auf anderen Betriebssystemen aber abweichen. Testen Sie neben Strg+C vor allem Strg+Untbr, Strg+D und Strg+Z. Killen Sie den Prozess, wenn alles nichts hilft. Aufgrund ihrer Funktion bezeichnet man diese Form der for-Schleife auch als forever-Schleife.

Lassen wir nun den ersten Wert, die Initialisierung, weg:

for (; i < 1000; i++)
  ;

Da hier der erste Wert weggelassen wurde, muss ein Semikolon stehen bleiben. Die Bedingung ist mit i < 1000 angegeben. Je nachdem, welchen Wert i enthält, bevor es zum Schleifeneintritt kommt, wird die Schleife unterschiedlich oft durchlaufen. Die Initialisierung im Kopf der for-Schleife hilft dem Programmierer lediglich, sich etwas Arbeit zu ersparen. Diese Versionen sind gleichwertig:

i = 0;
for (; i < 1000; i++)
  ;

for (i = 0; i < 1000; i++)
  ;

Im nächsten Beispiel wurde die Bedingung weggelassen:

for (i = 0; ; i++)
  ;

Auch hierbei handelt es sich um eine Endlosschleife, nur dass im Gegensatz zur "forever"-Version, i mit 0 initialisiert und bei jedem Durchlaufen der Schleife um 1 erhöht wird. Und auch das ist möglich:

for (i = 0; i < 1000; )
{
    /* 
       beliebige Anweisungen ...
    */

  i++;
}

Das i++ wurde hier aus dem Schleifenkopf in den Schleifenrumpf ausgelagert. Auch hier eine Zeile, die Sie sich sparen können.

Es ist auch möglich, mehrere Zählervariablen gleichzeitig zu verwenden. Im nächsten Beispiel wird zeitgleich aufwärts und abwärts gezählt, was für Ungeübte etwas verwirrend sein kann. Bedenken Sie: In der Programmierung gibt es häufig mehrere Möglichkeiten, und nicht immer ist die kürzeste Form die beste.

#include <stdio.h>
 
int main()
{
  int i, j;   /* Zaehlervariablen deklarieren! */
 
  for (i = 1, j = 100;    i <= 100, j >= 1;    i++, j--) 
    printf ("i: %d, j: %d\n", i, j);
 
  return 0;
}

Hier werden i mit 1 und j mit 100 initialisiert. Beide Initialisierungen werden mit einem Beistrich (,) getrennt! Gleiches gilt für die Bedingung und das Inkrementieren und Dekrementieren danach. Beachten Sie, dass auch in der Bedingung beide Teil-Bedingungen/-Ausdrücke durch einen Beistrich getrennt werden. && funktioniert aber genauso.

8.2. while-Schleife

Eine weitere Schleife ist die while-Schleife. Sie wird so lange durchlaufen, solange die angegebene Bedingung erfüllt ist:

while (Bedingung)
  Anweisung;

Sollen mehrere Anweisungen ausgeführt werden, wie üblich mit Anweisungsblock:

while (Bedingung)
{
  Anweisung1;
  Anweisung2;
  ...
  ...
}

Der Anweisungsblock wird nur dann ausgeführt, wenn die Bedingung erfüllt ist. Das gilt auch für die erste Ausführung! Das heißt, ist die Bedingung bereits zu Beginn nicht erfüllt, werden die Anweisungen im Schleifenrumpf überhaupt nie ausgeführt. Bei der for-Schleife war das genauso. Beide, die for- und while-Schleife, gehören zu den abweisenden Schleifen, da die Bedingung ZU BEGINN geprüft wird. Ein Beispiel:

...
i = 5000;
...
while (i < 1000)
  TueEtwas();

In diesem fiktiven Codeausschnitt enthält i bereits bevor es zur Schleife kommt, den Wert 5000, womit die Bedingung i < 1000 nicht erfüllt ist. Die Funktion TueEtwas() wird somit nie ausgeführt!

Im nächsten Beispiel wird die while-Schleife so lange durchlaufen, solange der Benutzer einen Zahlenwert ungleich 0 (Null) eingibt. Gibt er 0 ein, wird die Schleife abgebrochen, da die Bedingung nicht mehr erfüllt ist. Vorsicht: Geben Sie etwas anderes als einen Zahlenwert ein, kann es zu einer Endlosschleife kommen, da der Buffer nicht geleert wird. Beenden Sie in so einem Fall das Programm mit Strg+C (oder Strg+D, Strg+Untbr, Strg+Z) bzw. killen Sie den entsprechenden Prozess (Strg+Alt+Entf für den Windows-Taskmanager).

#include <stdio.h>
 
int main()
{
  int eingabe = 1;   /* mit einem Wert ungleich 0 initialisieren, sonst evtl. sofortiges Ende */
 
  while (eingabe != 0)
  {
    printf ("Geben Sie 0 ein, um das Programm zu beenden: ");
    scanf ("%d", &eingabe);
  }
 
  return 0;
}

In diesem Beispiel gibt es nichts Neues. Es geht allerdings auch folgende Variante:

#include <stdio.h>
 
int main()
{
  int eingabe = 0;   /* hier ist Null-Setzen moeglich! */
 
  while (1)  /* Endlosschleife */
  {
    printf ("Geben Sie 0 ein, um das Programm zu beenden: ");
    scanf ("%d", &eingabe);
 
    if (eingabe == 0)
      break;   /* Schleife abbrechen! */
  }
 
  return 0;
}

break kennen Sie bereits, allerdings in anderem Zusammenhang. break bricht mit sofortiger Wirkung die Schleife ab, unabhängig davon, ob die Bedingung erfüllt ist oder nicht (sie wird gar nicht geprüft). Wo break folgt, wird der Anweisungsblock beendet. Die danach im Schleifenrumpf folgenden Zeilen werden nicht mehr ausgeführt.

Das Gegenstück zu break ist continue. Mit continue können Sie die Schleife erneut durchlaufen lassen. Das heißt, die im Schleifen-Anweisungsblock folgenden Zeilen werden übersprungen! Danach wird die Schleifenbedingung erneut geprüft. Wenn erfüllt, wird der Schleifenrumpf von Beginn an ausgeführt.

8.3. do-while-Schleife

Die do-while-Schleife ist der while-Schleife sehr ähnlich. Der einzige Unterschied besteht darin, dass die Bedingung zum ersten Mal geprüft wird, wenn der Schleifenrumpf bereits einmal durchlaufen wurde. Die Schleife wird also mindestens einmal ausgeführt. Da die Bedingung erst AM ENDE geprüft wird, ist do-while eine nicht-abweisende Schleife.

do
{
  Anweisung1;
  Anweisung2;
  ...
  ...
}
while (Bedingung);

Abschließend ein besonders einfallsreiches Beispiel. Zählen bis 10:

#include <stdio.h>
 
int main()
{
  int i = 1;
 
  do
  {
    printf ("%d\n", i);
    i++;
  }
  while (i <= 10);
 
  return 0;
}
Vorheriges Kapitel Nächstes Kapitel