Wenn du keinen Zähler hast
Die for-Schleife ist um einen Zähler herum aufgebaut, den du im Voraus festlegst. Doch viele Schleifen haben keine saubere Anzahl: weiter Zahlen lesen, bis die Eingabe ausgeht, weiter nach einem Passwort fragen, bis es korrekt ist, einen Wert immer wieder halbieren, bis er 1 erreicht. Dafür passt die while-Schleife ganz natürlich - sie wiederholt einfach, solange eine Bedingung wahr bleibt.
Eine while-Schleife prüft ihre Bedingung vor jedem Durchlauf, auch dem allerersten. Ist die Bedingung von vornherein falsch, läuft der Rumpf gar nicht erst.
Die Bedingung count > 0 wird zuerst geprüft; ist sie wahr, läuft der Rumpf, dann springen wir zurück und prüfen erneut. Die Zeile count-- ist das, was die Bedingung schließlich falsch macht - lässt du sie weg, läuft die Schleife für immer.
Die Anatomie einer while-Schleife
Vergleiche sie mit der dreiteiligen for-Schleife, die du bereits kennst. Eine while-Schleife trennt diese drei Aufgaben: Die Initialisierung erledigst du vor der Schleife, die Bedingung steht in den Klammern, und die Aktualisierung lebt innerhalb des Rumpfs.
int i = 0; // Initialisierung - vor der Schleife
while (i < 5) { // Bedingung - bei jedem Durchlauf geprüft
cout << i << "\n";
i++; // Aktualisierung - daran musst du selbst denken
}
Genau dieser letzte Teil ist der Haken. In einer for-Schleife steht die Aktualisierung direkt neben der Bedingung, sodass man sie kaum vergisst. In einer while-Schleife ist sie nur eine weitere Anweisung im Rumpf - der häufigste Fehler ist, sie wegzulassen und das Programm aufzuhängen.
Ein C++-Fallstrick, der Anfänger erwischt: Ein verirrtes Semikolon direkt hinter der Bedingung macht den Rumpf zu einer leeren Anweisung.
int i = 0;
while (i < 5); // <-- dieses Semikolon ist der gesamte Schleifenrumpf
{
cout << i << "\n";
i++;
}
Das läuft für immer und tut nichts, denn das ; ist der Rumpf, und i ändert sich nie. Der Block in geschweiften Klammern läuft dann genau einmal. Der Compiler hält dich nicht auf - das ist völlig legaler Code, nur nicht das, was du gemeint hast.
do-while: den Rumpf mindestens einmal ausführen
Manchmal muss der Rumpf einmal laufen, bevor du überhaupt entscheiden kannst, ob du wiederholst. Die do-while-Schleife prüft ihre Bedingung am Ende, sodass der Rumpf immer mindestens einmal ausgeführt wird:
Du musst mindestens einmal fragen und lesen, bevor du wissen kannst, ob die Eingabe gültig ist - und genau das gibt dir do-while. Beachte das Semikolon nach while (...) - in C++ ist es für do-while erforderlich, und es zu vergessen ist ein häufiger Kompilierfehler.
Der Unterschied zu einem schlichten while zeigt sich klar, wenn die Bedingung von Anfang an falsch ist:
Nur do-while body wird ausgegeben. Die while-Schleife überspringt ihren Rumpf vollständig, weil x < 5 schon vor der ersten Prüfung falsch war.
Schleifen, bis cin fehlschlägt
Eine klassische while-Anwendung ist das Lesen, bis die Eingabe stoppt - es gibt keinen Zähler, du machst einfach weiter, bis der Stream dir signalisiert, aufzuhören. In C++ wird cin >> value zum Stream selbst ausgewertet, der wahr ist, solange das Lesen gelingt, und falsch, sobald er das Eingabeende oder eine Typabweichung erreicht. Das macht es zu einer sauberen Schleifenbedingung:
Die Bedingung erfüllt eine Doppelrolle: Sie liest und prüft in einem Schritt. Vergleiche das mit einem Sentinel-Wert - etwa beim Stopp bei 0. Dort musst du einmal vor der Schleife und erneut am Ende jedes Durchlaufs lesen, damit die Bedingung stets frische Eingaben prüft:
Wenn du die zweite Leseanweisung im Rumpf vergisst, ändert sich value nie und du hast eine Endlosschleife. Die Form while (cin >> value) umgeht das, indem sie das Lesen in die Bedingung faltet.
break und continue in while-Schleifen
break und continue funktionieren hier genauso wie in einer for-Schleife. break verlässt die Schleife sofort; continue springt direkt zurück zur Bedingungsprüfung und überspringt den Rest des aktuellen Durchlaufs:
Das gibt 1 3 5 7 9 aus. Das while (true) hört absichtlich nie von selbst auf - das break ist der einzige Ausgang. Sei vorsichtig mit continue in einer while-Schleife: Da die Aktualisierung Teil des Rumpfs ist, ist ein Rücksprung an den Anfang mit continue bevor du deinen Zähler weitergeschoben hast, ein stiller Weg, die Schleife hängen zu lassen. Im obigen Beispiel läuft n++ zuerst, also ist es sicher.
Vorsicht vor Endlosschleifen
Die Bedingung muss irgendwann falsch werden, und das hängt vollständig davon ab, dass sich etwas im Rumpf ändert. Die zwei üblichen Übeltäter sind: die Aktualisierung zu vergessen und so zu aktualisieren, dass der Ausstiegswert übersprungen wird:
int i = 0;
while (i < 5) {
cout << i << "\n"; // i ändert sich nie -> läuft für immer
}
int i = 0;
while (i != 10) {
i += 3; // 0, 3, 6, 9, 12... springt genau über 10 hinweg -> läuft für immer
}
Die erste hängt, weil i nie aktualisiert wird. Die zweite hängt, weil der Zähler über den exakten Wert hinwegspringt, den die Bedingung sucht - bevorzuge < oder <= gegenüber !=, wenn der Schritt nicht genau landen könnte. Ein while (true) ist in Ordnung, sofern es ein garantiertes break hat; ein versehentliches ist einfach ein Bug. Und denk an die Falle des leeren Rumpfs while (...); von vorhin - ein falsch platziertes Semikolon erzeugt eine Endlosschleife, die auf den ersten Blick korrekt aussieht.
Als Nächstes: die bereichsbasierte for-Schleife
Eine while-Schleife ist das richtige Werkzeug, wenn du schleifst, bis sich eine Bedingung ändert, und es keine saubere Anzahl gibt. Doch wenn du einfach jedes Element eines Containers besuchen willst - einen vector, ein Array, einen string - ohne Index und ohne zu verwaltende Bedingung, bietet modernes C++ etwas Saubereres: die bereichsbasierte for-Schleife (for (auto x : container)). Das ist die nächste Seite.
Häufig gestellte Fragen
Was ist der Unterschied zwischen while und do-while in C++?
Eine while-Schleife prüft ihre Bedingung vor dem ersten Durchlauf, sodass der Rumpf null Mal laufen kann. Eine do-while-Schleife führt den Rumpf zuerst einmal aus und prüft dann die Bedingung am Ende - sie läuft also immer mindestens einmal. Verwende do-while, wenn die Arbeit erfolgen muss, bevor du entscheiden kannst, ob du wiederholst, etwa eine Eingabe abfragen und sie anschließend validieren. Beachte, dass do-while nach dem abschließenden while (...) ein Semikolon braucht.
Wann sollte ich in C++ eine while-Schleife statt einer for-Schleife verwenden?
Verwende eine while-Schleife, wenn du keinen sauberen Zähler hast und einfach wiederholen willst, bis sich eine Bedingung ändert - Eingaben lesen, bis cin fehlschlägt, abfragen, bis ein Wert bereit ist, oder eine Warteschlange verarbeiten, bis sie leer ist. Greife zur for-Schleife, wenn du die Anzahl der Iterationen kennst oder einen offensichtlichen Index zum Zählen hast.
Wie stoppt man in C++ eine endlose while-Schleife?
Stelle sicher, dass etwas im Rumpf die Bedingung irgendwann falsch macht (einen Zähler verringern, einen Zeiger weiterschieben, ein Flag setzen). Für eine absichtliche while (true)-Schleife setze ein break hinein, das durch ein if abgesichert ist. Wenn eine Schleife hängt, ist die übliche Ursache, dass man vergessen hat, die Variable zu aktualisieren, von der die Bedingung abhängt.