s04 – Schleifen

 

Aufbauend auf die oben besprochenen Felder von Variablen werden hier Schleifen eingeführt. Eine Schleife vereinfacht das Programm, wenn eine Reihe von ähnlichen oder gleichen Operationen durchgeführt werden sollen.

Beispiel:

int[] i = new int[5];

i[0] = 2;
i[1] = 4;
i[2] = 6;
i[3] = 8;
i[4] = 10;

Man erkennt sofort das System hinter den Zuweisungen der Werte in das Feld: Es werden aufsteigend die geraden Zahlen gespeichert. Wenn noch mehr als 5 Variablen so zugewiesen werden sollen, wird dies schnell unmöglich (wie viele Zeilen bräuchte man zum Beispiel, um jeder Stadt in Deutschland eine Einwohneranzahl zuzuweisen?)

Eine Schleife tut nun im Prinzip das, was hier im Pseudocode dargestellt wird.

for-Schleife

Für alle Elemente e des Feldes i
Weise dem Element i[e] den Wert (e+1) * 2 zu

In Java wird das wie folgt realisiert:

for(int e = 0; e < 5; ++e)
{
i[e] = (e+1) * 2;
}

Dies ist eine sogenannte for-Schleife. Die Syntax ist:

for ([Initialisierung]; [Bedingung]; [Schritt])
{
Befehle;
}

Initialisierung:
Hier wird eine Schleifenvariable deklariert oder initialisiert. Diese steht dann in der Schleife zur Verfügung und wird nach der Schleife wieder aus dem Arbeitsspeicher gelöscht. Sinnvollerweise wird die Initialisierung so gewählt, dass die Bedingung erfüllt ist.

Bedingung:
Die Schleife läuft so lange, wie die Bedingung erfüllt ist. Daher sollte die Bedingung etwas mit der Schleifenvariable zu tun haben, da diese bei jedem Durchlauf verändert wird. Es kann allerdings auch eine Bedingung wie

4 == 4

benutzt werden. Die Schleife wird dann endlos ausgeführt (Endlosschleife), das Programm reagiert nicht mehr.

Schritt:
Die Schleifenvariable wird in jedem Durchlauf der Schleife verändert.
Sinnvollerweise sollte diese Änderung so gewählt werden, dass irgendwann die Bedingung nicht mehr erfüllt wird und somit die Schleife endet.

Im Beispiel:
In der Initialisierung wird zunächst eine neue Variable vom Typ Integer deklariert, dieser wird in der Wert 0 zugewiesen.
Die Bedingung ist, dass e kleiner als 5 sein soll, sie ist also am Anfang erfüllt (0 < 5).
Der Schritt, der jeden Durchlauf ausgefüht wird, ist ++e. e wird also um 1 erhöht. Wenn dies zum ersten Mal geschieht, ist e = 1, also immernoch kleiner als 5. Beim fünften Durchlauf wird e auf 5 erhöht, daher wird der 6. Durchlauf nicht mehr durchgeführt.

In jedem Schleifendurchlauf werden alle Befehle durchgeführt, die in den geschweiften Klammern der Schleife stehen. Im Beispiel ist das nur der eine Befehl

i[e] = (e+1) * 2;

Da e die Schleifenvariable ist, wird in jedem der 5 Durchläufe ein anderes Element des Feldes i bearbeitet.
Es werden also die folgenden Befehle ausgeführt:

i[0] = (0+1) * 2;
i[1] = (1+1) * 2;
i[2] = (2+1) * 2;
i[3] = (3+1) * 2;
i[4] = (4+1) * 2;

Eine oder mehrere (oder alle) Elemente des Schleifenkopfes können weggelassen werden. So kann das Beispiel oben auch wie folgt programmiert werden:

int e = 0;
for (; e < 5; )
{
i[e] = (e+1) * 2;
++e;
}

Die Schleifenvariable wird hier schon vor der Schleife deklariert und initialisiert. Der Schritt erfolgt in der Schleife selbst und nicht im Kopf.
Die Bedingung kann nicht ohne weiteres weggelassen werden, da die Schleife sonst endlos laufen würde:

int e = 0;
for (; ; )
{
i[e] = (e+1) * 2;
++e;
}

Die Schleife kann allerdings auch manuell beendet werden, indem in der Schleife ein “Abbruchbefehl” eingefügt wird:

int e = 0;
for (; ; )
{
i[e] = (e+1) * 2;
++e;
if (e == 5)
break;
}

Dieses Weglassen von Elementen des Schleifenkopfes führt jedoch dazu, dass das Programm unübersichtlich und schlechter lesbar wird, deshalb sollten sie nur als Notlösung benutzt werden.

Verschachtelte Schleifen

Im folgenden Anwendungsbeispiel wollen wir eine 4×4 Matrix deklarieren und ihr die Einheitsmatrix zuweisen (alle Elemente = 0, Elemente auf der Hauptdiagonalen = 1).

Ohne die Benutzung einer Schleife würde dies so aussehen:

int[][] iMatrixElement = new int[4][4];

iMatrixElement[0][0] = 1;
iMatrixElement[0][1] = 0;
iMatrixElement[0][2] = 0;
iMatrixElement[0][3] = 0;

iMatrixElement[1][0] = 0;
iMatrixElement[1][1] = 1;
iMatrixElement[1][2] = 0;
iMatrixElement[1][3] = 0;

iMatrixElement[2][0] = 0;
iMatrixElement[2][1] = 0;
iMatrixElement[2][2] = 1;
iMatrixElement[2][3] = 0;

iMatrixElement[3][0] = 0;
iMatrixElement[3][1] = 0;
iMatrixElement[3][2] = 0;
iMatrixElement[3][3] = 1;

Mit verschachtelten Schleifen kann dies wie folgt gelöst werden:

int[][] iMatrixElement = new int[4][4];

for (int m = 0; m < 4; ++ m)
{
for (int n = 0; n < 4; ++ n)
{
iMatrixElement[m][n] = 0;
if (m == n)
iMatrixElement[m][n] = 1;
}
}

Die äußere Schleife durchläuft die Zeilen, die innere Schleife durchläuft die Spalten. So wird jedes Element erfasst und es wird jedem Element der Wert 0 zugewiesen. Wenn die Spalte und die Zeile übereinstimmen (bei jedem Element der Hauptdiagonalen), dann wird der Wert 1 zugewiesen.
Es entsteht also die gleiche Matrix wie bei der ersten Ausführung.

While-Schleife

Eine for-Schleife, deren Kopf nur noch die Abbruchbedingung enthält (zum Beispiel weil die Schleifenvariable schon vorher vorhanden ist und der Schritt in der Schleife selbst erfolgt), kann auch als while-Schleife programmiert werden.

Beispiel:

int i = 0;
while (i < 5)
{
// Befehle[...]
++ i;
}

Die Befehle in der Schleife werden fünf Mal ausgeführt.

Bei dieser Version kann es passieren, dass die Befehle in der Schleife niemals ausgeführt werden, weil die Bedingung von Anfang an nicht erfüllt ist. Wenn der Inhalt der Schleife ausgeführt werden soll, bevor die Bedingung geprüft wird, kann man schreiben:

int i = 6;

do
{
// Befehle
++ i;
} while (i < 5)

Obwohl die Schleifenvariable i hier schon vor dem ersten Durchlauf die Bedingung nicht erfüllt, wird der Block ein Mal ausgeführt, da die Bedingung erst hinterher geprüft wird.

Ähnliche Artikel

Kommentar verfassen