1. Einleitung
Beginnen wir mit der Frage: Wozu sollte man überhaupt eine Schleife in eine andere einbetten? Der Punkt ist, dass unsere Daten oder Aufgaben oft nicht einfach eindimensional organisiert sind, sondern zum Beispiel als Tabelle, Raster oder sogar als mehrdimensionale Struktur. Angenommen, Sie möchten die Multiplikationstabelle auf dem Bildschirm ausgeben, ein zweidimensionales Array durchlaufen oder die Überschneidungen zwischen allen Paarelementen berechnen. Hier reicht eine einzelne Schleife eindeutig nicht – es braucht eine Schleife in der Schleife.
In der Programmierung ist eine verschachtelte Schleife wie zwei Wecker: Der äußere beginnt zu klingeln, und in seinem Inneren startet noch einer, der jedes Mal klingelt, solange der erste aktiv ist. Während also eine „äußere“ Iteration läuft, durchläuft die innere ihren gesamten Weg (und tut das für jede Iteration der äußeren erneut).
Ein gutes Beispiel – Stunden und Minuten. Die Stunden sind die äußere Schleife von 0 bis 23, die Minuten – die innere Schleife von 0 bis 59. Bei jeder Änderung der äußeren Schleife schafft es die innere, alle ihre Werte zu durchlaufen.
2. Syntax verschachtelter Schleifen
In Java unterscheidet sich die Syntax verschachtelter Schleifen nicht von der gewöhnlicher Schleifen – Sie schreiben einfach eine Schleife im Rumpf einer anderen. Schauen wir uns Beispiele mit for und while an:
// Äußere for-Schleife
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++) // Innere for-Schleife
{
System.out.print(i + "," + j + " ");
}
System.out.println(); // Zeilenumbruch nach der inneren Schleife
}
Hier steuert die äußere Schleife die Variable i (von 0 bis 2), und die innere – die Variable j (von 0 bis 3). Für jeden Wert von i läuft die innere Schleife vollständig von j == 0 bis j == 3. Wenn Sie diesen Code ausführen, sehen Sie eine hübsche Koordinatentabelle:
0,0 0,1 0,2 0,3
1,0 1,1 1,2 1,3
2,0 2,1 2,2 2,3
Ein analoges Beispiel mit while:
int i = 0;
while (i < 3)
{
int j = 0;
while (j < 4)
{
System.out.print(i + "," + j + " ");
j++;
}
System.out.println();
i++;
}
Beachten Sie: Innerhalb jedes Durchlaufs der äußeren Schleife muss die Variable der inneren Schleife (j) erneut initialisiert werden, sonst sehen wir nur eine einzige Zeile!
3. Beispiele für verschachtelte Schleifen
Beispiel 1: Ausgabe eines Schachbretts (8x8)
Nehmen wir als erste Aufgabe – geben wir ein klassisches Schachbrett in Form schwarzer und weißer Felder aus (nehmen wir ‚#‘ – schwarz, ‚.‘ – weiß). Implementieren wir das mit verschachtelten for-Schleifen:
for (int row = 0; row < 8; row++)
{
for (int col = 0; col < 8; col++)
{
// Ist die Summe von Zeilen- und Spaltenindex gerade, ist das Feld weiß, sonst schwarz
if ((row + col) % 2 == 0)
System.out.print("_");
else
System.out.print("#");
}
System.out.println(); // Nach jeder Reihe Zeilenumbruch
}
Ergebnis:
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
_#_#_#_#
#_#_#_#_
Wichtiger Punkt: Die Verschachtelung stellt sicher, dass wir für jede Zeile (row) alle Spalten (col) vollständig durchlaufen. Ohne Verschachtelung bekämen wir kein Brettmuster – nur eine einzige Zeile oder eine einzige Spalte.
Beispiel 2: Multiplikationstabelle
Einer der klassischen Kandidaten für verschachtelte Schleifen! Geben wir die Multiplikationstabelle 1–9 aus:
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
System.out.print(i * j + "\t");
}
System.out.println();
}
Die Formatierung i * j + "\t" fügt Tabulatoren hinzu, damit die Tabelle ordentlich aussieht.
Ergebnis:
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
...
9 18 27 36 45 54 63 72 81
4. Verschachtelte Schleifen und ihre Steuerung – Feinheiten
Über die Wirkung von break und continue in verschachtelten Schleifen
Hier tappen viele Einsteiger in die Falle! Wenn Sie break oder continue in der inneren Schleife verwenden, wirken sie nur auf diese Schleife. Die äußere arbeitet unbeeinflusst weiter.
Beispiel: vorzeitiger Ausstieg nur aus der inneren Schleife
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
if (j == 3)
break; // wir springen nur aus der inneren Schleife!
System.out.print(i + "," + j + " ");
}
System.out.println();
}
Ergebnis:
0,0 0,1 0,2
1,0 1,1 1,2
2,0 2,1 2,2
Wenn Sie sofort aus zwei verschachtelten Schleifen aussteigen müssen (zum Beispiel die Suche bei der ersten erfolgreichen Übereinstimmung in einer Tabelle sofort beenden), verwendet man üblicherweise ein Flag oder einen speziellen Kniff (z. B. return – wenn alles innerhalb einer Funktion passiert).
5. Visualisierung verschachtelter Schleifen
Manchmal ist es schwer, die Reihenfolge der Ausführung verschachtelter Schleifen „vor Augen zu haben“. Werfen wir einen Blick auf das folgende Flussdiagramm:
In Tabellenform – wie viele Iterationen gibt es insgesamt bei i von 1 bis 3, j von 1 bis 4?
| i | j (wird für jedes i durchlaufen) | Iterationen der inneren Schleife |
|---|---|---|
| 1 | 1, 2, 3, 4 | 4 |
| 2 | 1, 2, 3, 4 | 4 |
| 3 | 1, 2, 3, 4 | 4 |
| Insgesamt: 3 × 4 = 12 |
6. Fehler und Fallstricke bei der Arbeit mit verschachtelten Schleifen
Ein häufiger Fehler – die Variable der inneren Schleife falsch zu initialisieren. Zum Beispiel sie außerhalb der äußeren Schleife zu deklarieren, aber sie bei jedem Schritt nicht zurückzusetzen. Dadurch kann es passieren, dass die innere Schleife gar nicht oder falsch ausgeführt wird.
int j = 0;
for (int i = 0; i < 3; i++)
{
while (j < 4) // Ups! j könnte nach der ersten Iteration bereits 4 sein.
{
System.out.print(i + "," + j + " ");
j++;
}
System.out.println();
}
Hier läuft die Schleife nur einmal. Vergessen Sie nicht, die Variablen innerer Schleifen innerhalb der äußeren zu initialisieren!
Außerdem: Wenn Sie versehentlich zwei verschachtelte Schleifen mit denselben Variablennamen schreiben (for (int i = 0; ...) { for (int i = 0; ...) { ... } }), wird der Compiler schimpfen: Die Variable ist bereits definiert.
GO TO FULL VERSION