Beiträge durchsuchen

Schleifen

Was sind Schleifen?

In einem Programmablauf kommt es mitunter vor, dass eine bestimmte Befehlsfolge mehrmals hintereinander ausgeführt werden soll. So etwas nennt man „Schleife“.
Von ihnen gibt es unterschiedliche Arten: Sie unterscheiden sich darin, ob die Abbruchbedingung vor dem ersten Durchlauf geprüft werden soll oder erst danach und ob bereits feststeht, wie viele Male eine Schleife durchlaufen wird.

for-Schleife

Die for-Schleife hat folgenden Aufbau:

for i := 1 to 10 do begin
 ... // Befehlsfolge, die mehrfach ausgeführt werden soll
end;

Die Beispielschleife wird von 1 bis 10, also zehnmal durchlaufen. Nach jeder „Runde“ wird die sog. Schleifenvariable automatisch um 1 erhöht. Die Schleifenvariable heißt im Beispiel i, das muss nicht so sein. Auf jeden Fall ist es aber ein Ordinalwert. Die Grenzen (1 bis 10) sind hier direkt als Zahlen vorgegeben, es können jedoch auch Integer-Variablen, Aufzählungen oder Chars sein. Es sind alle Typen erlaubt, bei denen es eine feste Reihenfolge gibt.

Schleifenvariablen dürfen grundsätzlich innerhalb der Schleife nicht verändert werden. Ist die Obergrenze kleiner als die Untergrenze, wird die Schleife nicht durchlaufen (z. B. for i:=1 to 0); sind die Grenzen identisch, wird sie einmal durchlaufen.
Alternativ zum Hochzählen der Schleifenvariable ist auch Folgendes möglich:

 for i:=10 downto 1 do ...

while-Schleife

Im Gegensatz zur for-Schleife verwendet die while-Schleife keine Schleifenvariable, die automatisch hochgezählt wird. Hier wird vor jedem Durchlauf geprüft, ob eine bestimmte Bedingung erfüllt ist. Trifft diese nicht mehr zu, wird die Schleife nicht mehr durchlaufen und der Programmablauf danach fortgesetzt. Trifft die Bedingung bereits am Anfang nicht zu, wird die Schleife überhaupt nicht betreten. Man spricht hier von einer kopfgesteuerten Schleife.

Die while-Schleife hat folgende Struktur:

while x<>y do begin
 ... // Befehlsfolge, die mehrfach ausgeführt werden soll
end;

Solange also x ungleich y ist, wird die Schleife durchlaufen. Es ist also ratsam, x und/oder y innerhalb der Schleife zu verändern; andernfalls wäre das Durchlaufkriterium immer erfüllt, die Schleife würde nie zu einem Ende kommen. Der erfahrene Programmierer spricht hier von einer Endlosschleife, die ältere Betriebssysteme komplett in die Knie zwingen kann. Ist x bereits zu Beginn gleich y wird die Schleife überhaupt nicht durchlaufen.

Die Bedingung hinter while kann ein beliebiger Ausdruck sein, der einen Wahrheitswert (Boolean) ergibt.

repeat-until-Schleife

War bei der while-Schleife das Durchlaufkriterium anzugeben, ist es bei der repeat-until-Schleife das Abbruchkriterium. Außerdem wird dieses erst am Ende eines Schleifendurchlaufs geprüft. Ein Durchlauf findet also auf jeden Fall statt. Man spricht hier von einer fußgesteuerten Schleife.

repeat
 ...  // Befehlsfolge, die wiederholt ausgeführt werden soll
until x=y;

Die Beispielschleife wird solange durchlaufen, bis x gleich y ist. Auch hier ist wieder darauf zu achten, dass keine Endlosschleife entsteht. Auch wenn x schon zu Beginn gleich y ist, wird die Schleife dennoch einmal durchlaufen.

for-in-Schleife

Delphi Ab 2005

In Delphi 2005 neu hinzugekommen ist die for-in-Schleife. Dies erleichtert besonders Schleifen über Arrays, wenn kein Indexwert benötigt wird. Die allgemeine Syntax lautet:

for element in collection do statement;

Beispiel:

var stringarr: array of String;
 s: String;
begin
 for s in stringarr do begin
 ShowMessage(s);
end;

Bedingungen

Bei den Abbruch- und Durchlaufbedingungen handelt es sich um logische Ausdrücke . Wie diese in Delphi notiert werden und wann hierbei Klammern benötigt werden, ist in einem folgenden Kapitel beschrieben.

Schleifen abbrechen

Schleifen lassen sich natürlich auch vor dem regulären Ende verlassen. Dazu gibt es die Prozedur break. break kann nur innerhalb von Schleifen verwendet werden und setzt den Programmablauf mit der ersten Anweisung nach der Schleife fort.

Außerdem gibt es Situationen, in denen man schon zu Beginn eines Schleifendurchlaufs weiß, dass man gleich mit der nächsten „Runde“ fortfahren kann. Hier kann man continue verwenden. Dadurch wird die Durchführung eines Schleifendurchlaufs abgebrochen und mit dem nächsten Durchlauf begonnen. Bei for-Schleifen wird der Index erhöht.

Warum läuft die Zählvariable einer for-Schleife falsch herum?

Es mag zwar für manche unvorstellbar klingen, aber das ist kein Fehler im Compiler, sondern eine sehr effektive Optimierungsmaßnahme. Für den Computer ist es leichter auf den Wert Null zu prüfen als auf einen beliebigen Wert. Und genau diesen Zustand nutzt der Delphi-Compiler aus. Der Compiler prüft, ob er die Schleife so umstellen kann, dass die Programmlogik dabei nicht verändert wird. Um wieder auf die Ausgangsfrage zurückzukommen: Ja, die Zählvariable läuft rückwärts. Jedoch läuft etwas anderes vorwärts, nämlich die zu verändernden Daten. Ein sehr gutes Beispiel ist das Setzen aller Elemente eines Arrays auf Null. Hierbei spielt es keine Rolle, wie rum die Schleife läuft. Was ist aber, wenn in dem Array Objekt-Referenzen gespeichert sind, bei denen eine Methode aufgerufen werde soll und das auch noch in der richtigen Reihenfolge? Nun geht der Compiler mit einem Trick an die Sache heran. Anstatt dass die Zählvariable hoch gezählt wird, verschiebt er einen temporären Zeiger nach jedem Schleifendurchlauf auf das nächste Array-Element. Somit wandert zwar die Zählvariable rückwärts, das Array aber vorwärts und alles passt wieder.
Der integrierte Debugger wiederum kommt mit dieser Optimierung nicht zurecht und liefert einfach den Wert, der in der Zählvariable steht, anstatt dass er die Differenz der Speicheradresse des ersten Elements mit der des temporären Zeigers vergleicht. Das kann man aber auch nicht von einem Debugger verlangen, da es unendlich viele Konstellationen geben kann, die nicht alle berücksichtigt werden können.