Schleifen
Definition: Schleife
In der Programmierung ist das wiederholte ausführen von Instruktionen eine zentrale Funktion, die man mithilfe von Schleifen realisiert.
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 istUPDATE
: 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ürcontinue
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 LabelLABEL
- 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.