While-Schleifen in Rust
Eine while-Schleife läuft so lange, wie eine Bedingung true bleibt. Sie ist das richtige Werkzeug, wenn du weißt, worauf du wartest – auch wenn du nicht genau weißt, wie viele Durchläufe es dauern wird.
Eine einfache while-Schleife
Abschnitt betitelt „Eine einfache while-Schleife“fn main() { let mut count = 1;
while count <= 5 { println!("{count}"); count += 1; }}Ausgabe:
12345Die Bedingung (count <= 5) wird vor jedem Durchlauf geprüft. Sobald sie false ist, endet die Schleife – hier, nachdem count den Wert 6 erreicht hat.
while oder loop?
Abschnitt betitelt „while oder loop?“Du könntest dasselbe auch mit loop und einem eigenen if/break schreiben. while drückt aber direkter aus, was du meinst: „Mach weiter, solange das hier wahr ist.“ Heb dir loop für Fälle auf, in denen die Abbruchbedingung nicht natürlich an den Anfang der Schleife passt.
// mit while – klar und auf den Punktlet mut n = 0;while n < 3 { println!("{n}"); n += 1;}
// dasselbe mit loop – funktioniert, aber mehr zu lesenlet mut n = 0;loop { if n >= 3 { break; } println!("{n}"); n += 1;}Ein realistischeres Beispiel
Abschnitt betitelt „Ein realistischeres Beispiel“while siehst du oft, wenn ein Wert ein bestimmtes Ziel erreichen soll:
fn main() { let mut balance = 100;
while balance < 200 { balance += 25; println!("Kontostand ist jetzt {balance}"); }
println!("Ziel erreicht!");}Ausgabe:
Kontostand ist jetzt 125Kontostand ist jetzt 150Kontostand ist jetzt 175Kontostand ist jetzt 200Ziel erreicht!Die Bedingung kann jeder Ausdruck sein, der ein bool ergibt. Du kannst also Prüfungen mit && und || von der Seite Operatoren kombinieren, etwa while balance < 200 && months < 12.
Rust hat kein do-while
Abschnitt betitelt „Rust hat kein do-while“Manche Sprachen haben eine do { ... } while (bedingung)-Schleife. Sie führt den Rumpf zuerst aus und prüft die Bedingung erst danach. Der Rumpf läuft also immer mindestens einmal. Rust hat diese Schleife nicht. Stattdessen nimmst du loop und setzt die Prüfung ans Ende.
Hier ein Fall, in dem das wichtig ist: Um die Ziffern einer Zahl zu zählen, kannst du so lange durch 10 teilen, bis nichts mehr übrig ist. Die Zahl 0 hat aber trotzdem eine Ziffer – und eine normale while-Schleife läuft für sie kein einziges Mal:
fn main() { let number = 0;
// Eine while-Schleife prüft zuerst, also läuft sie für 0 nie. let mut n = number; let mut digits = 0; while n > 0 { digits += 1; n /= 10; } println!("while sagt: {number} hat {digits} Ziffern");
// loop + Prüfung am Ende führt den Rumpf mindestens einmal aus. let mut n = number; let mut digits = 0; loop { digits += 1; n /= 10; if n == 0 { break; } } println!("loop sagt: {number} hat {digits} Ziffer");}Ausgabe:
while sagt: 0 hat 0 Ziffernloop sagt: 0 hat 1 ZifferSetz number auf 4096, und beide Versionen sind sich einig: 4 Ziffern. Der Unterschied zeigt sich nur, wenn die Bedingung schon ganz am Anfang false ist. Als Faustregel gilt also: Muss der Rumpf mindestens einmal laufen, schreib loop mit dem if ... { break; } am Ende.
Es gibt noch eine weitere Art von while-Schleife: while let. Sie läuft weiter, solange ein Wert auf ein Muster passt. Mehr dazu findest du auf der Seite if let und while let.
Übungen
Abschnitt betitelt „Übungen“1. Addieren, bis du über 100 bist
Abschnitt betitelt „1. Addieren, bis du über 100 bist“Addiere 1 + 2 + 3 + … und hör auf, sobald die Summe größer als 100 ist. Gib aus, wie viele Zahlen du addiert hast, und die Summe. Tipp: Du brauchst zwei mut-Variablen: eine für die nächste Zahl und eine für die Summe.
Lösung anzeigen
fn main() { let mut next = 1; let mut total = 0;
while total <= 100 { total += next; next += 1; }
println!("{} Zahlen addiert, die Summe ist {total}", next - 1);}Ausgabe:
14 Zahlen addiert, die Summe ist 105Nach dem letzten Durchlauf ist next schon einen Schritt weiter – deshalb geben wir next - 1 aus. Solche „Um eins daneben“-Details (Off-by-one-Fehler) prüfst du am besten kurz mit einem kleinen Beispiel im Kopf.
2. Halbieren, bis du bei 1 bist
Abschnitt betitelt „2. Halbieren, bis du bei 1 bist“Beginne mit 1000. Solange die Zahl größer als 1 ist, teilst du sie durch 2 (ganzzahlige Division) und gibst sie aus. Gib am Ende aus, wie viele Halbierungen es gebraucht hat. Tipp: n /= 2 teilt n durch 2 und lässt den Rest weg.
Lösung anzeigen
fn main() { let mut n = 1000; let mut steps = 0;
while n > 1 { n /= 2; steps += 1; println!("{n}"); }
println!("Es hat {steps} Halbierungen bis 1 gebraucht");}Ausgabe:
500250125623115731Es hat 9 Halbierungen bis 1 gebraucht125 / 2 ergibt 62, nicht 62.5, weil beide Zahlen Ganzzahlen sind. Genau deshalb endet die Schleife exakt bei 1.
Zusammenfassung
Abschnitt betitelt „Zusammenfassung“while bedingung { ... }wiederholt den Block, solange die Bedingungtrueist. Geprüft wird vor jedem Durchlauf.- Sorg dafür, dass irgendetwas in der Schleife die Bedingung irgendwann
falsemacht – sonst läuft sie ewig. - Nimm lieber
whilealsloop, wenn sich die Abbruchbedingung natürlich als „solange X gilt“ formulieren lässt. - Rust hat kein do-while. Muss der Rumpf mindestens einmal laufen, nimm
loopmit derbreak-Prüfung am Ende.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Welcher klassische Fehler führt zu einer endlosen while-Schleife?
2. Wann solltest du laut dieser Seite while statt loop verwenden?
3. Wie schreibst du eine Schleife, deren Rumpf immer mindestens einmal läuft?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- Bedingte Schleifen mit while – Das Rust-Buch: die offizielle Einführung, die
whilemitloopvergleicht. - while – Rust by Example (auf Englisch): ein ausführbares FizzBuzz, geschrieben mit einer
while-Schleife. - Predicate loops – The Rust Reference (auf Englisch): die genauen Regeln dafür, wie eine
while-Schleife abläuft. - Das Schlüsselwort
while– Doku der Standardbibliothek (auf Englisch): eine kurze Übersicht überwhileundwhile let, mit Beispielen.