Schleifen - Oder die Kunst, sich selbst zu wiederholen!

Was werden wir behandeln?
Wie Schleifen benutzt werden um Mehrfacheingaben zu vermeiden. Unterschiedliche Schleifentypen und wann sie benutzt werden.

In der letzten Übung haben wir einen Teil der 12er Reihe ausgedruckt. Aber es erforderte eine Menge Tipperei und wenn wir sie erweitern müssten, würde dies sehr zeitraubend sein. Glücklicherweise gibt es einen besseren Weg und hier beginnen wir die wahre Leistungsfähigkeit zu erkennen, die Programmiersprachen uns anbieten.

FOR - Schleifen

Was wir jetzt machen, ist, dass wir die Programmiersprache für Wiederholungen heranziehen werden, um eine Variable zu ersetzen, wobei bei jeder Wiederholung ihr Wert anwächst. In Python sieht das folgendermaßen aus:

>>>for i in range(1,13):
...    print "%d x 12 = %d" % (i, i*12)

Anmerkung 1: Wir benutzen range(1,13) um 13 zu spezifizieren, weil range() von der ersten bis zur, aber nicht einschließlich, letzten Zahl wirkt. Mag dies auch auf den ersten Blick irgendwie bizarr aussehen, aber das hat Gründe und du wirst in ihren Gebrauch kommen.

Anmerkung 2: Der for-Operator in Python ist tatsächlich ein foreach-Operator, wobei er die sich anschließenden Code-Sequenz auf jedes Bestandteil einer Sammlung anwendet. Im vorliegenden Fall ist die Sammlung eine Liste von Zahlen, die durch range() generiert wurde. Du kannst das ausprobieren, indem du nach dem Python-Prompt print range(1,13) eintippst und schaust, was gedruckt wird.

Anmerkung 3: Die print-Zeile ist weiter eingezogen, als die for-Zeile darüber. Das ist ein sehr wichtiger Punkt, denn so weiß Python, dass das print das zu wiederholende Stück ist. Es spielt keine Rolle, wie groß der Einzug ist, solange er übereinstimmt.

Wie arbeitet denn nun das Programm? Laß es uns durchgehen.
Zuallerest verwendet Python die range-Funktion um eine Liste von Zahlen von 1 bis 12 zu erzeugen.

Als Nächstes macht Python i zum ersten Wert in der Liste, in diesem Falle 1. Dann führt es das Stück eingezogenen Code unter Verwendung des Wertes i = 1 aus:

   print "%d x 12 = %d" % (1, 1*12)

Python geht dann zurück zur for Zeile und setzt i auf den nächsten Wert in der Liste, diesmal 2. Wieder wird der eingezogene Code ausgeführt, diesmal mit i = 2:

   print "%d x 12 = %d" % (2, 2*12)

Diese Abfolge wird sooft wiederholt, bis i auf alle Werte in der Liste gesetzt ist. An diesem Punkt bewegt sich das Programm zu der nächsten Zeile, die nicht eingezogen ist - in diesem Falle gibt es keine weiteren Kommandos, so dass das Programm anhält.

Hier folgt die gleiche Schleife in BASIC:

FOR I = 1 to 12
    PRINT I, " x 12 = ", I*12
NEXT I

Dies ist viel expliziter und viel einfacher zu erkennen, was geschehen wird. Dennoch ist die Pythonversion viel flexibler, da die Schleife über einen ganzen Satz von Zahlen, die Gegenstände einer Liste oder andere Sammlungen (z. B. ein String) laufen kann.

Und in Tcl

Tcl verwendet ein for-Konstrukt, das in vielen Programmiersprachen gängig ist und ursprünglich in C modelliert wurde. Es sieht so aus:

for {set i 1} {$i <= 12} {incr i} {
    puts [format "%d x 12 = %d" $i [expr $i*12]]
    }

Note: Dieses Konstrukt hat 3 Teile:

Der Schleifenrumpf wird nur dann ausgeführt, wenn der Test-Teil wahr ist. Jedes von diesen Teilen kann einen beliebigen Code enthalten, lediglich der Test-Teil muß einen Boole'schen Wert untersuchen (was in Tcl Null oder Nicht-Null bedeutet). Beachte, dass, obwohl ich den Schleifenrumpf als eingezogen dargestellt habe, dies rein zur Verständnishilfe dient. Tcl verlangt von mir keinen Einzug des Blocks, lediglich die geschweiften Klammern weren zur Markierung von Beginn und Ende benutzt.

Tcl hat ebenfalls ein foreach-Konstrukt, das auf Listen angewendet werden kann.

WHILE - Schleifen

FOR - Schleifen sind nicht der einzige zugängliche Typ zur Konstruktion von Schleifen. Diese sind eigentlich ganz gut, aber FOR-Schleifen verlangen von uns, dass wir wissen oder berechnen können, wie groß die Anzahl der Iterationen ist, die wir duchführen wollen. Was geschieht nun, wenn wir eine bestimmte Aufgabe solange durchführen lassen wollen, bis etwas geschieht, wir aber nicht wissen, wann dieses Etwas geschieht? Zum Beispiel wollen wir Daten aus einer Datei lesen und bearbeiten, aber wir wissen nicht im Voraus wie groß die Menge der Daten ist, die die Datei enthält. Wir wollen also solange die Daten bearbeiten, bis wir das Dateiende erreicht haben. Das ist möglich, aber schwierig mit einer FOR-Schleife.

Zur Lösung des Problems haben wir einen anderen Schleifentyp: die WHILE-Schleife. Sie sieht in BASIC so aus:

J = 1
WHILE J <= 12 
    PRINT J, " x 12 = ", J*12
    J = J + 1
WEND

Dies produziert das gleiche Ergebnis wie vorher, verwendet aber eine while-anstatt einer for-Schleife. Beachte, dass die Struktur ein while ist, gefolgt von einem Ausdruck, der als Boole'scher Wert ausgewertet wird (wahr oder falsch, du erinnerst dich?). Wenn der Ausdruck wahr ist, so wird der Code innerhalb der Schleife ausgeführt.

Als eine Alternative betrachten wir die Tcl-Version:

set j  1
while {$j <= 12} {
   puts [format "%d x 12 = %s"  $j [expr $j*12]]
   set j [expr $j + 1]
}

Wie du siehst ist die Struktur ziemlich ähnlich, außer ein Paar geschwungenen Klammern anstelle des WEND in BASIC. Aber was ist dieses Ducheinander innerhalb der Schleife? Erinnerst du dich an Format-Strings in in Python? format ist Tcl's Äquivalent. Das $j bedeutet lediglich den Wert von j (im Gegensatz zum Buchstaben 'j'!) und das expr sagt nur: 'berechne das folgende Stück als sei es ein Ausdruck'. Die eckigen Klammern sagen Tcl welches Stück zuerst durchzunehmen ist. Tcl ist eine unübliche Sprache darin, dass es versucht, seinen Code in einem Durchlauf zu interpretieren; so würde es ohne die Klammern versuchen, das Wort 'expr'auszudrucken, dann nach weiteren Werten Ausschau halten und mit einer Fehlermeldung aufgeben. Wir müssen ihm mitteilen, dass es die Summe bilden, dann den String formatieren und dann das Ergebnis ausdrucken soll. Verwirrt? Mach dir darüber keine Sorgen. Wie ich sagte, ist Tcl eine unübliche Sprache mit einigen wenigen einzigartigen guten Bestandteilen und vielen Merkwürdigkeiten.

Jetzt betrachte Python:

>>> j = 1
>>> while j <= 12:
...    print "%d x 12 = %d" % (j, j*12)
...    j = j + 1

Bis jetzt sieht das recht unkompliziert aus. Nur eine Sache bedarf der Erläuteung - siehst du den Doppelpunkt (:) am Ende der while-Zeilen und for-Zeilen ganz oben im Text? Dies erzählt Python, daß ein Code-Klumpen (ein Block) nachfolgt. Die meisten Sprachen verwenden eine Marke für das Blockende (wie BASIC's WEND oder Tcl's geshwungene Klammern), aber Python benutzt den Einzug um die Struktur zu zeigen. Das bedeutet, dass es sehr wichtig ist, innerhalb der Schleife alle Zeilen um den gleichen Einzug zu versetzen; das ist eine gute Eigenart, da dies insbesondere das Lesen erleichtert.

Flexiblere Schleifen

Kommen wir zu unserer 12er Tabelle am Anfang dieses Abschnittes zurück. Die von uns erzeugte Schleife ist zum Ausdrucken der 12er Tabelle ganz gut. Aber was ist mit anderen Werten? Kannst du die Schleife so verändern, dass man zu ihr sagen kann, sie soll die 7er-Reihe machen? Das würde so aussehen:

>>> for j in range(1,13):
...    print "%d x 7 = %d" % (j,j*7)

Das hat jetzt bedeutet, dass wir zweimal die 12 in eine 7 verändert haben. Und wenn wir einen anderen Wert möchten, müssen wir wiederum diese Änderungen durchführen. Wäre es nicht besser, wir könnten den Multiplikator eingeben, den wir möchten?

Wir erreichen das dadurch, dass wir die Werte im Print-String durch einen anderen Variablennamen ersetzen. Dann setzen wir die Variable, bevor wir die Schleife durchlaufen:

>>> multiplikator = 12
>>> for j in range(1,13):
...    print "%d x %d = %d" % (j, multiplikator, j*multiplikator)

Das ist unser alte Freundin, die 12er-Tabelle. Um jetzt auf die 7er umzustellen, brauchen wir einfach nur den Wert von 'multiplikator' zu ändern.

Beachte, dass wir hier Befehlfolge und Schleife kombiniert haben. Wir haben zuerst einen Einzelbefehl, multiplikator = 12 gefolgt, in Befehlsfolge also, von einer for Schleife.

Die Schleife in der Schleife

Lass uns das vorangegangene Beispiel um eine Stufe erweitern. Angenommen, wir möchten die Tabellen von allen Vielfachen von 2 bis 12 ausdrucken (1 ist zu trivial, um sich damit zu beschäftigen). Das einzige was wir jetzt eigentlich nur benötigen, ist, den Variablenwert als den Teil einer Schleife zu setzen, nämlich so:

>>> for multiplikator in range(2,13):
...    for j in range(1,13):
...       print "%d x %d = %d" % (j,multiplikator,j*multiplikator)

Beachte, dass der eingezogene Teil innerhalb der ersten for Schleife genau dieselbe Schleife ist, von der wir ausgegangen sind. Dies arbeitet wie folgt:
Wir setzen den Multiplikator auf den ersten Wert (2) und durchlaufen die zweite Schleife.
Dann setzen wir den Multiplikator auf den nächsten Wert (3) und durchlaufen wiederum die innere Schleife und so fort. Diese Technik ist bekannt als verschachtelte Schleifen.

Ein Haken ist, dass alle Tabellen zusammenhängen; wir können das ausbügeln, indem wir einfach eine Trennungslinie am Ende der ersten Schleife mit ausdrucken, etwa so:

>>> for multiplikator in range(2,13):
...    for j in range(1,13):
...       print "%d x %d = %d" % (j,multiplikator,j*multiplikator)
...    print "------------------- "

Beachte, dass die zweite Print-Anweisung in einer Linie mit dem zweiten 'for' steht, es ist die zweite Anweisung in der Schleifen-Befehlsfolge. Erinnere dich daran, dass die Einzugsebene in Python sehr wichtig ist.

Experimentiere solange herum, bis du eine Trennlinie erhälts, die anzeigt, welche Tabelle jetzt folgt, mit der Absicht, eine Beschriftung zu erhalten. Hinweis: Du benötigst wahrscheinlich die Multiplikator-Variable und ein Format-String.

Andere Schleifen

Einige Sprachen unterstützen weitere Schleifen-Konstruktionen, aber eine Art von for und while ist gewöhnlich immer vorhanden. (Modula 2 und Oberon unterstützen nur while-Schleifen , aber sie können for-Schleifen - wie wir sie oben sahen - simulieren). Andere Schleifen, denen du begegnest, sind:

do-while
Dasselbe wie ein 'while', jedoch findet der Test am Ende statt, so dass die Schleife immer noch ein zusätzliches Mal durchlaufen wird.
repeat-until
Ähnlich wie die obere, aber die Logik des Tests ist umgekehrt.
GOTO, JUMP, LOOP etc
Diese sind hauptsächlich in älteren Sprachen zu sehen; sie setzen eine Marke in den Code und springen dann explizit zu dieser.
Zur Erinnerung
  • FOR-Schleifen wiederholen einen Befehlssatz für eine festgelegte Anzahl an Iterationen.
  • WHILE-Schleifen wiederholen einen Befehlssatz, bis eine Abbruchbedingung erfüllt ist. Sie führen den Schleifenrumpf niemals aus, wenn die Abbruchbedingung falsch ist oder damit gestartet wird.
  • Andere Schleifentypen existieren, aber FOR und WHILE werden fast immer unterstützt.
  • Python's for-Schleifen sind in Wirklichkeit foreach-Schleifen - sie operieren mit einer Liste von Gegenständen.
  • Schleifen können ineinander verschachtelt sein.

zurück  weiter  Inhalt


Im Falle von Fragen oder Hinweisen sende bitte eine Nachricht auf Englisch an alan.gauld@yahoo.co.uk oder auf Deutsch an bup.schaefer@freenet.de