11.4 For-Next-Anweisung

Es gibt drei Versionen der For-Anweisung: Eine lange, eine kurze und eine generische. Die generische Version der Anweisung kann auch in einer langen und kurzen Version verwendet werden, so dass es insgesamt vier verschiedene Versionen der For-Anweisung sind. Jedoch verbleiben wir aus Gründen der Übersichtlichkeit nur bei drei verschiedenen Versionen in dieser Dokumentation.

1) Lange Version der For-Anweisung:

 
For [Local] <var> = <expr1> To <expr2> [Step <expr3>] <loop-block> Next

Als erstes weist die For-Anweisung der Variable var den Wert im Ausdruck expr1 zu. Nun wird dieser Wert der Step-Anweisung an expr3 übergeben. Dieser Schritt-Wert ist optional. Wenn Sie nichts angeben, ist bei der Step-Anweisung der Schritt-Wert in expr3 standardmäßig auf 1 gesetzt.

Wenn expr3 positiv ist, wird die For-Anweisung überprüfen, ob der Wert der Variable var kleiner oder gleich expr2 ist. Wenn dies der Fall ist, wird in die Schleife eingetreten und wiederholt, bis var größer ist als expr2. Am Ende jeder Schleife wird der Wert expr3 zur Variablen addiert.

Wenn expr3 negativ ist, prüft die For-Anweisung, ob der Wert der Variable var größer oder gleich expr2 ist. Wenn dies der Fall ist, wird in die Schleife eingetreten und so lange wiederholt, bis der Wert in var kleiner ist als der von expr2. Am Ende jeder Schleife wird der Wert expr3 der Variable var abgezogen.

Ist expr3 Null, wird die Schleife für immer wiederholt. Zu beachten ist außerdem, dass die Ausdrücke expr2 und expr3 nur einmal am Anfang der Schleife ausgewertet werden. Somit ist die Schleifengrenze und der Schritt konstant und kann nicht geändert werden, während die Schleife aktiv ist.

Ein Beispiel:

 
For i = 1 To 100
    DebugPrint(i)
Next

Dieser Code gibt die Zahlen von 1 bis 100 aus. DebugPrint() wird hundertmal ausgeführt. Wenn die Schleife beendet wird, hat die Variable i den Wert 101. Sie sehen, dass wir nicht eine Step-Anweisung angegeben haben. Dies bedeutet, dass bei jeder Wiederholung der Schleife 1 zur Variable addiert wird. Wenn wir mit dem Faktor 2 arbeiten möchten, könnten wir den folgenden Code verwenden:

 
For i = 1 To 100 Step 2
    DebugPrint(i)
Next

Das wird "1 3 5 7 9... 95 97 99" ausgeben. Wenn die Schleife verlassen wird, hat die Variable i den Wert 101.

Wenn wir rückwärts von 100-0 zählen wollen, verwenden wir einen negativen Stufenwert wie in dem folgenden Beispiel:

 
For i = 100 To 0 Step -1
    DebugPrint(i)
Next

Dies ruft DebugPrint() hundert und ein Mal auf. Nachdem die Schleife beendet ist, hat die Variable i den Wert -1.

Wenn Sie Local vor der Initialisierung der Variable der For-Anweisung schreiben, wird die Variable lokal in den Schleifen-Block erstellt. Das bedeutet, dass nicht von außerhalb des Schleifenblock auf sie zugegriffen werden kann. Ein Beispiel:

 
For Local i = 1 To 50
    DebugPrint(i)      ; gibt 1, 2, 3 ... 49, 50 aus
Next
DebugPrint(i)          ; gibt 0 aus (i ist nur innerhalb ...
                       ; ... der Schleife existent)

Der Vorteil von einer lokalen Zählervariable in For-Schleifen ist, dass sie schneller laufen als Schleifen, die eine globale Variable verwenden. Wenn Sie auf die Variable von außerhalb der For-Anweisung nicht zugreifen müssen, sollten Sie immer Local verwenden. Eine Einschränkung für Schleifen mit Local ist, dass Sie keinen neuen Wert auf den lokale Zählerwert zuordnen können. Wenn Sie die Schleife beenden müssen, verwenden Sie Break. Ändern der Zählervariable während der Durchführung der Schleife funktioniert nur ohne die Anweisung Local.

Werfen Sie auch einen Blick auf die Break und die Continue-Anweisungen. Diese können verwendet werden, um eine Schleife zu verlassen oder an deren Ende zu springen.

2) Kurze Version der For-Anweisung:

 
For [Local] <var> = <expr1> To <expr2> [Step <expr3>] Do <stat>

Die kurze Version verhält sich genau wie die lange, aber Sie muss nicht die die Next-Anweisung enthalten. Die kurze For-Anweisung hat die Einschränkung, dass der Schleifenblock nur aus einer Anweisung bestehen darf. Wenn Sie mehrere Anweisungen im Schleifenblock ausführen wollen, müssen Sie die lange Version verwenden. Die Anweisung Do signalisiert Hollywood, dass Sie die kurze Version verwenden möchten.

Das erste Beispiel von oben könnte auf folgende Weise geschrieben werden, um eine kurze For-Anweisung zu erhalten:

 
For i = 1 To 100 Do DebugPrint(i)

3) Generische Version der For-Anweisung:

 
For <var1> [, <var2>, ...] In <expr> [Do <stat>] or [<loop-block> Next]

Die generische Version der For-Anweisung unterscheidet sich von den beiden anderen Varianten durch die Tatsache, dass sie eine benutzerdefinierte Funktion aufruft, um die Werte für jede Zählervariablen zu erhalten. Diese Tatsache macht die generische For-Anweisung für eine Vielzahl von Zwecken nützlich. Sie können Ihre eigenen Zählerfunktionen schreiben, aber für die meisten Fälle werden Sie wahrscheinlich die eingebauten Zählerfunktionen verwenden, die von Befehlen wie Pairs(), IPairs() oder PatternFindStr() zur Verfügung gestellt werden.

Der in expr angegebener Ausdruck wird nur einmal ausgewertet. Er gibt drei Werte zurück: Eine Zählerfunktion, einen Zustands- und einen Anfangswert für var1. Die Zählerfunktion und der Zustandswert sind private Werte und sie sind während der Laufzeit der For-Schleife als Variablen weder sichtbar noch zugänglich. Sobald die generische For-Schleife diese drei Werte abgerufen hat, startet sie die Zählerfunktion mit dem Zustands- und dem aktuellen Wert in var1. Die Schleife wird beendet werden, sobald der aktuelle Wert in var1 Nil ist.

Die meisten Zählerfunktionen geben mehrere Werte für den Zähler zurück. Deshalb können Sie auch mehrere Variablen in der allgemeinen For-Anweisung angeben. Die Fähigkeit, mehrere Variablen auf verschiedene Zählerzustände initialisiert zu haben, macht die allgemeine For-Anweisung sehr flexibel.

Lassen Sie uns nun ein Beispiel anschauen und betrachten Sie die folgende Tabelle:

 
months = {"January", "February", "March", "April", "May", "June",
     "July", "August", "September", "October", "November", "December"}

Wir wollen nun herauszufinden, welchen Index (1 bis 12) jeder Monat hat. Dafür verwenden wir die Namen als Referenz. Natürlich könnten wir die Tabelle durchlaufen und den Namen mit dem entsprechenden Index zu vergleichen. Aber wenn es sich um größere Datenmengen handelt, ist es häufig schneller, eine Umkehr-Tabelle zu erstellen, um die gewünschten Informationen zu erhalten. In unserem Fall wollen wir eine Tabelle, die den Namen der Monate als Indizes verwendet, so dass die Tabelle ["Januar"] 1, Tabelle ["Februar"] liefert 2, und so weiter. Wir können diese Umkehr-Tabelle mit der generischen Zählerfunktion IPairs() und der For-Schleife zusammen erstellen. Die IPairs()-Zählerfunktion gibt zwei Werte zurück: Den Index- sowie den Schlüsselwert für jedes Tabellenelement, welche an sie übergeben werden. Wir können diese IPairs()-Zählerfunktion verwenden, um die Tabelle sehr leicht durchzugehen:

 
revmonths = {}
For i,v In IPairs(months)
   revmonths[v] = i + 1
Next

Alternativ könnten wir auch für diesen Code die kurze Version der generischen For-Schleife verwenden, da sich nur eine Anweisung in der For-Schleife befindet. Mit Hilfe der Kurzversion würde der Code wie folgt aussehen:

 
revmonths = {}
For i,v In IPairs(months) Do revmonths[v] = i + 1

Die IPairs()-Zählerfunktion zählt nur alle Ganzzahlen-Indizes in einer Tabelle. Wenn Sie alle Felder einer Tabelle durchgehen wollen, können Sie stattdessen die Zählerfunktion Pairs() verwenden.

Ein weiterer Befehl, der oft in Verbindung mit der generischen For-Schleife verwendet wird, ist PatternFindStr(). Er wird eine Zählerfunktion zurückgeben, die verwendet werden kann, um eine Zeichenfolge zu analysieren. Zum Beispiel wird der folgende Code alle Wörter in einer Zeichenkette durchgehen:

 
s$ = "Hello World This is a test"
For w$ In PatternFindStr(s, "%a+") Do Print(w$)

Natürlich ist es auch möglich, eigene Zählerfunktionen zu schreiben. Dies kann jedoch ziemlich kompliziert werden. Deshalb wird das hier nicht erläutert. Bitte konsultieren Sie das Buch "Programming in Lua (zweite Auflage)" von Roberto Ierusalimschy für weitere Informationen, wie eigene Zählerfunktionen (Iterator-Function) zu schreiben sind.


Navigation zeigen