For-Schleifen in Rust
for durchläuft einen Bereich oder eine Collection, ein Element nach dem anderen. Von den drei Schleifenarten in Rust ist das die, zu der du am häufigsten greifen wirst.
Einen Bereich durchlaufen
Abschnitt betitelt „Einen Bereich durchlaufen“fn main() { for i in 1..=5 { println!("{i}"); }}Ausgabe:
123451..=5 ist ein Bereich (Range), der beide Enden einschließt (1 bis 5). Lässt du das = weg – also 1..5 –, hört er eins vorher auf, und du bekommst 1 bis 4. Über diesen „Um-eins-daneben“-Fehler stolpert man leicht. Prüf also lieber zweimal, welche Variante du meinst.
Eine Collection durchlaufen
Abschnitt betitelt „Eine Collection durchlaufen“Hier spielt for seine Stärke richtig aus: Du durchläufst ein Array oder einen Vektor, ohne selbst einen Index mitzuführen:
fn main() { let fruits = ["Apfel", "Banane", "Kirsche"];
for fruit in fruits { println!("{fruit}"); }}Ausgabe:
ApfelBananeKirscheStell dir zum Vergleich vor, du zählst mit einer while-Schleife von Hand mit und greifst per Index (fruits[i]) zu. Die for-Variante ist kürzer, und es gibt keinen Index, den du falsch setzen kannst. Mehr über Arrays und Vektoren erfährst du auf den Seiten Arrays und Vektoren.
Auch den Index bekommen, mit .enumerate()
Abschnitt betitelt „Auch den Index bekommen, mit .enumerate()“Brauchst du sowohl die Position als auch den Wert, nimm .enumerate():
fn main() { let fruits = ["Apfel", "Banane", "Kirsche"];
for (index, fruit) in fruits.iter().enumerate() { println!("{index}: {fruit}"); }}Ausgabe:
0: Apfel1: Banane2: KirscheDer Teil (index, fruit) ist ein Tupel-Muster: Jeder Durchlauf liefert dir ein Paar, und die Schleife zerlegt es für dich in zwei Variablen.
Rückwärts und in Schritten zählen
Abschnitt betitelt „Rückwärts und in Schritten zählen“Was, wenn du von 3 herunterzählen oder nur jede zweite Zahl besuchen willst? Naheliegend wäre ein Bereich, der rückwärts läuft, etwa 3..=1. Das kompiliert zwar, aber die Schleife läuft kein einziges Mal. Ein Bereich zählt nur aufwärts. Ist der Anfang größer als das Ende, ist der Bereich einfach leer.
Nimm stattdessen einen normalen Bereich und ändere, wie du ihn durchläufst:
.rev()geht den Bereich rückwärts durch..step_by(n)nimmt jedenn-ten Wert, beginnend mit dem ersten.
fn main() { for i in (1..=3).rev() { println!("{i}..."); } println!("Los!");
for even in (0..=10).step_by(2) { print!("{even} "); } println!();
for i in 3..=1 { println!("das wird nie ausgegeben: {i}"); }}Ausgabe:
3...2...1...Los!0 2 4 6 8 10Achte auf die Klammern: (1..=3).rev(). Ohne sie würde Rust 1..=3.rev() als „1 bis 3.rev()“ lesen – und das willst du nicht. Du kannst beides auch kombinieren: (0..=10).rev().step_by(5) ergibt 10, 5, 0.
Warum for beim Zählen besser ist als while
Abschnitt betitelt „Warum for beim Zählen besser ist als while“Du könntest eine Zählschleife auch mit while schreiben. Aber for mit einem Bereich räumt eine ganze Kategorie von Fehlern aus dem Weg: Es gibt keinen Zähler, den du zu erhöhen vergessen kannst, und du läufst nicht aus Versehen einen Schritt über das Ende eines Arrays hinaus. Rust-Entwickler nehmen standardmäßig for und greifen nur dann zu while, wenn es keinen natürlichen Bereich und keine Collection zum Durchlaufen gibt.
Übungen
Abschnitt betitelt „Übungen“1. Eine Einmaleins-Reihe
Abschnitt betitelt „1. Eine Einmaleins-Reihe“Gib die 7er-Reihe aus, von 7 x 1 = 7 bis 7 x 10 = 70. Tipp: Eine einzige for-Schleife über 1..=10 reicht. Die Multiplikation kannst du direkt in println! erledigen.
Lösung anzeigen
fn main() { for i in 1..=10 { println!("7 x {i} = {}", 7 * i); }}Ausgabe:
7 x 1 = 77 x 2 = 147 x 3 = 217 x 4 = 287 x 5 = 357 x 6 = 427 x 7 = 497 x 8 = 567 x 9 = 637 x 10 = 70Benannte Variablen wie {i} dürfen direkt in die geschweiften Klammern. Eine Rechnung wie 7 * i darf das nicht. Deshalb steht dort ein leeres {}, und der Wert folgt nach dem Komma.
2. Die ungeraden Zahlen addieren
Abschnitt betitelt „2. Die ungeraden Zahlen addieren“Addiere alle ungeraden Zahlen von 1 bis 99 und gib die Summe aus. Tipp: (1..100).step_by(2) liefert dir 1, 3, 5, … 99. Halte eine mut-Summe außerhalb der Schleife.
Lösung anzeigen
fn main() { let mut total = 0;
for n in (1..100).step_by(2) { total += n; }
println!("Die ungeraden Zahlen von 1 bis 99 ergeben zusammen {total}");}Ausgabe:
Die ungeraden Zahlen von 1 bis 99 ergeben zusammen 2500Alternativ kannst du 1..100 durchlaufen und n nur dann addieren, wenn n % 2 == 1 ist. Beides funktioniert. step_by überspringt die geraden Zahlen einfach, statt jede einzeln zu prüfen.
Zusammenfassung
Abschnitt betitelt „Zusammenfassung“for element in bereich_oder_collection { ... }ist die Alltagsschleife in Rust.1..=5schließt beide Enden ein;1..5hört eins vor der 5 auf.- Durchlauf Arrays und Vektoren direkt, um jeden Wert ohne eigenen Index zu bekommen.
- Nimm
.enumerate(), wenn du neben dem Wert auch den Index brauchst. - Ein Rückwärts-Bereich wie
3..=1ist leer. Zähl mit(1..=3).rev()herunter und überspring mit.step_by(n)Werte.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Was ist in einer for-Schleife der Unterschied zwischen 1..=5 und 1..5?
2. Wie bekommst du beim Durchlaufen einer Collection sowohl den Index als auch den Wert?
3. Warum ist for zum Durchzählen einer Collection meist besser als while?
4. Was macht for i in 5..=1 { ... }?
Punkte: 0 / 4
Weiterlesen
Abschnitt betitelt „Weiterlesen“- Durchlaufen einer Kollektion mit for – Das Rust-Buch: die offizielle Einführung, samt Countdown mit
.rev(). - for and range – Rust by Example (auf Englisch): ausführbare Beispiele für Bereiche, dazu
iter,iter_mutundinto_iterfür Collections. - Iterator loops – The Rust Reference (auf Englisch): die genauen Regeln dafür, was eine
for-Schleife hinter den Kulissen tut. Iterator::step_by– Doku der Standardbibliothek (auf Englisch): wiestep_byfunktioniert, mit Beispielen.revist auf derselben Seite beschrieben.