Schleifen
Wozu brauchen wir Schleifen in der Programmierung?
Schleifen: Wiederholung mit System
Stell dir vor, du möchtest einer Gruppe von 100 Personen eine persönliche Begrüßungs-E-Mail schicken. Anstatt 100-mal den Text "Hallo [Name]," zu kopieren und den Namen manuell einzusetzen, kannst du eine Schleife verwenden. Eine Schleife ist eine Kontrollstruktur, die es ermöglicht, einen Codeblock mehrmals hintereinander auszuführen. Sie nimmt sich jeden Namen aus einer Liste und führt die Anweisung "Sende E-Mail an [Name]" automatisch für jeden Namen aus. Gesteuert wird eine Schleife meist durch eine Abbruchbedingung – sie läuft so lange, bis diese Bedingung erfüllt ist (z. B. alle Namen in der Liste abgearbeitet wurden).
Die for-Schleife: Wenn die Anzahl der Runden feststeht
Die for
-Schleife (auch Zählschleife genannt) ist ideal, wenn du genau weißt, wie oft ein Codeblock wiederholt werden soll oder wenn du jedes Element einer Sammlung (wie einer Liste/Array) einmal durchlaufen möchtest. Sie eignet sich perfekt, um über alle Elemente eines Arrays zu iterieren.
Ein Beispiel in Javascript, das alle Teilnehmenden begrüßt:
const teilnehmer = ["Julia", "Max", "Sophie"];
// Die for...of-Schleife geht jedes Element im Array 'teilnehmer' durch
for (const name of teilnehmer) {
// Für jedes Element (hier 'name') wird dieser Code ausgeführt
console.log(`Herzlich willkommen, ${name}!`);
}
// Ausgabe:
// Herzlich willkommen, Julia!
// Herzlich willkommen, Max!
// Herzlich willkommen, Sophie!
Welche weiteren Arten von Schleifen gibt es?
Die while-Schleife: Solange die Bedingung stimmt
Die while
-Schleife (auch kopfgesteuerte Schleife genannt) wiederholt einen Codeblock, solange eine bestimmte Bedingung wahr (true
) ist. Die Bedingung wird vor jedem Schleifendurchlauf geprüft. Ist die Bedingung von Anfang an falsch (false
), wird der Codeblock gar nicht erst ausgeführt. Sie ist besonders nützlich, wenn die Anzahl der Wiederholungen nicht im Voraus bekannt ist, sondern von einem Ereignis oder Zustand abhängt.
Ein Beispiel in Javascript, das würfelt, bis eine 6 kommt:
let wurf = 0; // Variable für das Würfelergebnis
let anzahlWuerfe = 0;
console.log("Würfeln, bis eine 6 kommt...");
while (wurf !== 6) { // Solange der Wurf keine 6 ist...
// Math.random() gibt eine Zahl zwischen 0 und <1 aus
// Multiplikation mit 6 erlaubt Werte von 0 bis <6, +1 -> 1 bis <7
// Math.floor rundet ab
wurf = Math.floor(Math.random() * 6) + 1;
anzahlWuerfe++;
console.log(`Wurf ${anzahlWuerfe}: ${wurf}`);
}
console.log(`Geschafft! Eine 6 nach ${anzahlWuerfe} Würfen.`);
Die Schleife läuft, bis die Bedingung wurf !== 6
falsch wird. Die Anzahl der Durchläufe ist zufällig.
Die do-while-Schleife: Mindestens einmal dabei
Die do-while
-Schleife (oder fußgesteuerte Schleife) ist eine Variante der while
-Schleife. Der entscheidende Unterschied: Der Codeblock innerhalb der Schleife wird mindestens einmal ausgeführt, bevor die Bedingung zum ersten Mal geprüft wird. Wenn die Bedingung dann wahr ist, wird die Schleife wiederholt.
Ein Beispiel in Javascript für ein einfaches Auswahlmenü, welches auf eine passende Eingabe wartet:
let userChoice;
do {
console.log("\n--- MENU ---");
console.log("1: Spiel starten");
console.log("2: Spiel laden");
console.log("3: Verlassen");
userChoice = prompt("Bitte wählen (1, 2 oder 3):");
console.log(`Ausgewählt: ${userChoice}`);
} while (userChoice !== '1' && userChoice !== '2' && userChoice !== '3');
console.log("Gültige Auswahl getroffen. Menü wird verlassen...");
Typische Stolpersteine: Endlosschleifen und Off-by-One-Fehler
Beim Arbeiten mit Schleifen können leicht logische Fehler entstehen:
- Endlosschleifen: Eine Schleife, deren Abbruchbedingung niemals erreicht wird, läuft unendlich weiter. Das Programm "hängt".
// Vorsicht: Beispiel für eine Endlosschleife!
// let counter = 0;
// while (counter < 5) {
// console.log("Ich laufe und laufe...");
// // Fehler: counter wird nicht erhöht, die Bedingung counter < 5 bleibt immer wahr.
// }
- Off-by-One-Fehler: Die Schleife wird genau einmal zu oft oder einmal zu wenig ausgeführt. Dies passiert oft durch eine falsche Initialisierung des Zählers oder eine ungenaue Abbruchbedingung (z. B.
<
statt<=
).
// Ziel: Zahlen von 1 bis 3 ausgeben.
// Fehlerhaftes Beispiel (Off-by-One):
// for (let i = 1; i < 3; i++) { // Läuft nur für i=1 und i=2 (Bedingung i < 3)
// console.log(i); // Gibt nur 1, 2 aus. Die 3 fehlt.
// }
// Korrekt:
for (let i = 1; i <= 3; i++) { // Bedingung i <= 3 schließt die 3 mit ein
console.log(i);
}
// Ausgabe:
// 1
// 2
// 3
Sorgfältiges Überprüfen der Startwerte, Bedingungen und der Veränderung der Zählvariablen hilft, diese Fehler zu vermeiden.
Wie kann man den Ablauf einer Schleife gezielt beeinflussen?
break: Der Notausstieg aus der Schleife
Die Anweisung break
beendet die aktuelle Schleife (for
, while
oder do-while
) sofort und vollständig, unabhängig davon, ob die eigentliche Schleifenbedingung noch erfüllt wäre. Die Programmausführung wird dann mit der ersten Anweisung nach der Schleife fortgesetzt. Stell dir vor, du durchsuchst eine lange Liste von Kund:innendaten nach einer bestimmten Kund:innummer. Sobald die Nummer gefunden wurde, ist die weitere Durchsuchung der Liste unnötig, und die Schleife kann abgebrochen werden.
const zahlen = [10, 23, 45, 67, 88, 102];
const gesuchteZahl = 67;
let gefunden = false;
for (const zahl of zahlen) {
console.log(`Prüfe ${zahl}...`);
if (zahl === gesuchteZahl) { // Strikter Vergleich '===' ist oft besser in JS
gefunden = true;
console.log(`${gesuchteZahl} wurde gefunden!`);
break; // Schleife sofort verlassen
}
}
if (!gefunden) {
console.log(`${gesuchteZahl} nicht in der Liste.`);
}
continue: Die aktuelle Runde überspringen
Die Anweisung continue
beendet nur die aktuelle Iteration (Runde) der Schleife und springt sofort zum Anfang der nächsten Iteration (zur Überprüfung der Schleifenbedingung bei while
/do-while
oder zum nächsten Element bei for
). Der restliche Code innerhalb des Schleifenkörpers für die aktuelle Runde wird übersprungen. Stell dir vor, du möchtest alle positiven Zahlen in einer Liste addieren und negative Zahlen oder Nullen ignorieren.
const werte = [10, -5, 20, 0, 30, -2];
let summePositiv = 0;
for (const wert of werte) {
if (wert <= 0) {
console.log(`Wert ${wert} wird übersprungen.`);
continue; // Aktuelle Runde überspringen, wenn Wert nicht positiv ist
}
summePositiv += wert;
console.log(`${wert} wurde addiert.`);
}
console.log(`Summe der positiven Werte: ${summePositiv}`);
// Ausgabe:
// 10 wurde addiert.
// Wert -5 wird übersprungen.
// 20 wurde addiert.
// Wert 0 wird übersprungen.
// 30 wurde addiert.
// Wert -2 wird übersprungen.
// Summe der positiven Werte: 60
Lernziele
- die grundlegende Funktionsweise und den Zweck von Schleifen als Mittel zur Wiederholung von Anweisungen erklären, indem anhand von Codebeispielen erläutert wird, wie diese durch eine Abbruchbedingung gesteuert werden und welche Vorteile sie gegenüber mehrfacher manueller Wiederholung von Codeblöcken bieten.
- die Ursachen für häufige logische Fehler (z.B. Endlosschleifen oder "Off-by-One"-Fehler) in Schleifenkonstruktionen zuzuordnen, indem anhand von Codebeispielen analysiert wird, wie fehlerhafte Initialisierungen, Bedingungen oder Inkrementierungs-/Dekrementierungsschritte zu unerwünschtem Schleifenverhalten führen und wie diese Fehler unter Berücksichtigung der Schleifensemantik identifiziert und korrigiert werden können.
- die Unterschiede und Anwendungsfälle der grundlegenden Schleifenstrukturen differenzieren, indem für gegebene Szenarien, die eine wiederholte Ausführung von Codeblöcken erfordern, die jeweils adäquate Schleifenkonstruktion (z.B. for für eine bekannte Anzahl von Iterationen, while für eine bedingungsabhängige Wiederholung vor der Ausführung, do-while für eine mindestens einmalige Ausführung) ausgewählt und die Entscheidung anhand der Anzahl der Iterationen und der bekannten oder unbekannten Abbruchbedingung begründet wird.
- die Funktionsweise und den Einsatz von Schleifensteueranweisungen (break, continue) zur Modifikation des Standard-Schleifenablaufs erklären, indem beschrieben wird, wie break eine Schleife vorzeitig beendet und continue zum nächsten Iterationsschritt springt, und für gegebene Szenarien erläutert wird, wie diese Anweisungen den Programmfluss innerhalb einer Schleife gezielt beeinflussen, um spezifische Anforderungen zu erfüllen.