Schleifen

Definition: Schleife

In der Programmierung ist das wiederholte ausführen von Instruktionen eine zentrale Funktion, die man mithilfe von Schleifen realisiert.

Eine Schleife (loop) ist ein Block von Anweisungen, der so lange mehrfach nacheinander ausgeführt wird, wie ein Vergleichsausdruck, mit dem die Schleife kontrolliert wird, wahr ist.
G. Büchel, Praktische Informatik

while-Schleife

Bei den Schleifen bietet C wieder die gewohnte Kost, die wir bereits aus anderen Programmiersprachen kennen; mit der while-Schleife als einfachste Form.

  • while-Schleife (while loop) prüft vor jedem Durchlauf eine Bedingung (Vergleichsausdruck)
  • kopfgesteuert und abweisend
  • Syntax: while (BEDINGUNG) { ANWEISUNGEN }
while (antwort < 42) {
    antwort++;
}

Der Rumpf der while-Schleife wird nur betreten, wenn die Bedingung des Ausdrucks wahr ist. Wenn man eine Schleife wünscht, die mindestens einmal durchlaufen wird, muss man die do/while-Schleife wählen. Die Variable auf die getestet wird sollte richtig initialisiert sein und man sollte nicht vergessen, sie im Schleifenrumpf zu verändern, da man andernfalls in einer Endlosschleife landet.

Wie bei allen Kontrollstrukturen in C ist die Bedingung wieder ein Ausdruck, der als Ganzzahl interpretiert werden kann mit der Regel, dass 0 als false und alle anderen Werte als true gelten.

Wenn die Anzahl der Schleifendurchläufe schon im Voraus feststeht, sollten Sie die for-Schleife verwenden. Das hier gewählte Beispiel ist also nicht optimal, da man es besser mit for implementiert hätte. while ist gut geeignet für Schleifen, bei denen währende des Durchlaufens erst festgestellt werden kann, wann der Abbruch erfolgen soll, z. B. bei linearen Suchen etc.

/* Beispiel: Gib alle Zahlen von 1 bis 10 aus */
int i = 1;
while (i <= 10) {
    printf("%d\n", i);
    i++;
}
/* Beispiel: Berechne Summe der Zahlen von 1 bis 10 */
int i = 1;
int summe = 0;
while (i <= 10) {
    summe += i;
    i++;
}
printf("%d\n", summe);

do-while-Schleife

Die while-Schleife ist immer dann sinnvoll, wenn man den Rumpf nur betreten will, wenn die Bedingung mindestens ein mal wahr ist. In Fällen, in denen der Rumpf aber erst einmal durchlaufen werden soll, um dann am Ende die Bedingung zu prüfen, bietet sich die do-while-Schleife an.

do-while-Schleife (do-loop) ist fußgesteuert (nicht abweisend)

  • Syntax: do { ANWEISUNGEN } while (BEDINGUNG);
do {
    n = readNatuerlicheZahl();
} while (n >= 0);

Der Rumpf der do/while-Schleife wird immer mindestens einmal betreten, da der Test erst am Ende erfolgt. Wenn man eine Schleife wünscht, die die Bedingung vorher testet, muss man die while-Schleife verwenden. Die Variable, auf die getestet wird, sollte im Schleifenrumpf verändert werden, da man andernfalls in einer Endlosschleife landet.

Wenn die Anzahl der Schleifendurchläufe schon im Voraus feststeht, sollten Sie die for-Schleife verwenden. Das hier gewählte Beispiel ist also nicht optimal, da man es besser mit for implementiert hätte.

/* Beispiel: Gib alle Zahlen von 1 bis 10 aus */
int i = 1;
do {
    printf("%d\n", i);
    i++;
} while (i <= 10);
/* Beispiel: Berechne Summe der Zahlen von 1 bis 10 */
int i = 1;
int summe = 0;
do {
    summe += i;
    i++;
} while (i <= 10);

printf("%d\n", summe);

for-Schleife

Die vielseitigste Schleife wird in C durch die for-Schleife zur Verfügung gestellt. Sie bietet mehr Kontrolle über den Ablauf der Wiederholung und ist besonders gut geeignet, wenn man die Anzahl der Schleifendurchläufe im Vorfeld kennt.

for-Schleife (for-loop) ist kopfgesteuerte (abweisende Schleife)

  • bietet mehr Möglichkeiten als die while-Schleife
  • Syntax: for (INIT; BEDINGUNG; UPDATE) { ANWEISUNGEN }
    • INIT: initialisiert Variablen (optional)
    • BEDINGUNG: Schleife läuft, solange die Bedingung wahr ist
    • UPDATE: Operationen, die nach jedem Durchlauf durchgeführt werden
int i;
for (i = 0; i < 10; i++) {
    /* tu was */
}

Wenn man Java gewöhnt ist, wird man sich wundern, warum die Variable i nicht in der for-Schleife deklariert wird. Der Grund liegt darin, dass bis zum C99-Standard Variablen nur am Anfang eines Blocks deklariert werden durften. Erst mit C99 kam die Möglichkeit, Variablen auch an anderer Stelle, z. B. in dem Initialisierungsteil einer for-Schleife, erstmals einzuführen. Der vorhergehende Standard (ANSI-C bzw. C89) kannte diese Erweiterung noch nicht.

Wenn Sie nicht wissen, auf welcher Plattform, mit welchem C-Compiler Ihr Code später einmal compiliert werden wird, sollten Sie auf die Deklaration im for verzichten.

Die drei Teile der for-Schleife sind alle optional, d. h. for(;;); ist gültiger C-Code und eine Endlosschleife.

/* Beispiel: Gib alle Zahlen von 1 bis 10 aus */
int i = 0;
for (i = 1; i <= 10; i++) {
    printf("%d\n", i);
}
/* Beispiel: Berechne Summe aller Zahlen von 1 bis 10 */
int summe = 0;
int i;

for (i = 1; i <= 10; i++) {
    summe += i;
}

printf("%d\n", summe);

Man kann über den Kommaoperator sogar mehr als eine Variable in der for-Schleife nutzen und Verändern. Die Details werden beim Operator weiter hinten erläutert.

Schleifenabbruch

In manchen Fällen möchte man während der Iteration auf den Ablauf dieser Einfluss nehmen. Hierzu gibt es mit break und continue zwei passende Schlüsselwörter.

Aktueller Schleifendurchlauf kann abgebrochen werden

  • break – Schleife wird ganz verlassen
    (Sprung an die Anweisung nach der Schleife)
  • continue – beginnt sofort einen neuen Durchlauf
    (Sprung in die Prüfung der Bedingung)

Wird häufig als schlechter Programmierstil angesehen. Alternativen

  • Kontrollvariable als Ersatz für break
  • zusätzliches if als Ersatz für continue

Die Verwendung von break und continue wird teilweise als schlechter Programmierstil angesehen, weil der Ablauf der Iteration hierdurch unübersichtlich werden kann. Andererseits gibt es Fälle, in denen ein gut platziertes break oder auch continue das Programm erheblich besser lesbar macht. Es kommt also darauf an, wann und wie man die Schlüsselworte benutzt.

/* Suche kleinste Zahl, die durch 8 und 14  teilbar ist (mit break) */
for (int i = 1; i <= 8*14; i++) {
    if ((i % 8 == 0) && (i % 14 == 0)) {
        printf("%d\n", i);
        break;
    }
}

Das erste Beispiel zeigt, wie man durch ein break nach dem Finden der gesuchten Lösung die Schleife verlässt. Will man dies nicht, muss man – wie im zweiten Beispiel gezeigt – eine zweite Kontrollvariable einführen (gefunden) und diese dann im Erfolgsfall umsetzen.

/* Suche kleinste1 Zahl, die durch 8 und 14 teilbar ist (ohne break) */
int gefunden = 0;
for (int i = 1; i <= 8*14 && !gefunden; i++) {
    if ((i % 8 == 0) && (i % 14 == 0)) {
        printf("%d\n", i);
        gefunden = 1;
    }
}

Die Variante mit dem break ist im vorliegenden Fall übersichtlicher als die zusätzliche Variable und hier deswegen vorzuziehen, weil klarer.

Das goto

C erlaubt es mithilfe von goto unbedingte Sprünge durchzuführen. In Java ist goto zwar als Schlüsselwort reserviert aber nicht in der Sprache implementiert. In C hingegen hat es eine Funktion.

  • Anders als Java besitzt C noch einen goto Befehl
  • goto LABEL springt zum Label LABEL
  • nur innerhalb derselben Funktion
int i = 0;

jump_here:

/* Schleife mit goto. Pfui! */
if (i < 5) {
    printf("i=%d\n", i);
    i++;
    goto jump_here;
}

Das Beispiel zeigt eine falsche Verwendung von goto, weil hier dasselbe Ziel auch mit einer normalen Schleife erreicht werden könnte und daher die unübersichtliche Konstruktion vollkommen unnötig ist.

Man verwendet goto in C hauptsächlich für Fehlerbehandlungsroutinen und Aufräumarbeiten im Falle eines Fehlers. So kann man den Code für die Fehlerbehandlung an einer zentralen Stelle in der Funktion halten und über goto anspringen.

Über Funktionsgrenzen hinweg kann in C mit der Funktion _longjmp gesprungen werden. Wegen der Auswirkungen auf den Stack ist die Anwendung aber nicht trivial und wird deswegen nicht weiter diskutiert.


Copyright © 2025 Thomas Smits