VOICE Homepage: http://de.os2voice.org |
September 2003
[Inhaltsverzeichnis]
|
Von Thomas Klein © September 2003 |
In der vorherigen Folge haben wir bereits die beiden ersten Arten der
drei bekannten Programmstrukturen kennen gelernt: Sequenz (Batch) und
Verzweigungen. Heute schließen wir dieses Thema ab, indem wir den
dritten Typ besprechen - Iterationen (oder "Schleifen" wenn Sie so
wollen).
Schleifen werden im Prinzip verwendet, um eine bestimmte Verarbeitung
solange zu wiederholen, bis eine bestimmte Bedingung erfüllt ist
wie zum Beispiel das Lesen aller Zeilen (bzw. Datensätze)
einer Datei bis das Dateiende erreicht ist. Schleifen bzw. deren
Bestandteile werden Sie in jeder Programmiersprache finden und immer
bestehen Sie schematisch gesehen aus drei Teilen: Kopf, Rumpf und
Fuß.
Als Rumpf bezeichnen wir die Abfolge der Befehle, die bei
jedem Durchlauf ausgeführt wird. Schleifenkopf und -Fuß
steuern den eigentlichen "Wiederholvorgang", der solange stattfindet,
bis eine bestimmte Bedingung erfüllt ist, die für
gewöhnlich im Schleifenkopf definiert wird.
Hierbei können wir Menschen sprachlich vier Typen von Abbruchsituationen
unterscheiden: Eine Schleife wird jeweils solange wiederholt,...
Eine fußgesteuerte Schleife (bei der die Abbruchbedingung nach Ausführung des Rumpfs geprüft wird) sieht so aus:DO WHILE <Bedingung>
<Befehl-1>
...
<Befehl-n>
END
Ja, das ist ziemlich gemein: In beiden Fällen wird die Bedingung zwar syntaktisch im "Kopf" der Schleife definiert, dennoch arbeiten beide Typen vollkommen verschieden. Um das wie oben bereits genannt einmal zu verdeutlichen, nehmen wir ein Beispiel:DO UNTIL <Bedingung>
<Befehl-1>
...
<Befehl-n>
END
XYZ = 7
DO WHILE XYZ \> 4
SAY XYZ
XYZ = XYZ + 1
END
Unsere Bedingung lautet hier "solange XYZ nicht größer ist als 4".
XYZ = 7
DO UNTIL XYZ > 4
SAY XYZ
XYZ = XYZ + 1
END
Hier
lautet die Bedingung sinngemäß "bis XYZ größer
als 4 ist". Sprachlich also im Prinzip das selbe wie im vorherigen Fall
("solange nicht größer als 4"). Da der Wert von XYZ bereits
zu Beginn 7 ist, dürfte also ebenfalls nichts passieren. Tja -
Pech! Denn wenn man das laufen lässt, wird einmal "7" ausgegeben,
denn: Bei einer fußgesteuerten Schleife wird die Bedingung NACH
Ausführung des Rumpfes geprüft.WobeiDO <anzahl>
<Befehl-1>
...
<Befehl-n>
END
<anzahl>
schlicht eine Zahl ist... Beispiel:Die andere Art der Wiederholungsschleife (die vielseitiger und auch am geläufigsten ist) enthält eine Laufvariable (oder "Zählervariable" wenn Sie so wollen), deren Wert bei jedem Durchlauf des Schleifenrumpfes automatisch um einen bestimmten Faktor erhöht wird. Die vollständige Syntax lautet:DO 3
say "Hallo"
END
DO <variable> = <startwert> TO <endwert> [ BY <erhöhung> ]
<Befehl-1>
...
<Befehl-n>
END
Beispiel:DO durchlauf = 1 TO 10 BY 1
say "Das ist Durchlauf Nummer:" durchlauf
END
Wie
Sie vielleicht noch aus unzähligen vorherigen Syntaxdiagrammen
wissen, kennzeichnen die eckigen Klammern optionale Bestandteile. Somit
handelt es sich bei der Angabe des Erhöhungswerts also um einen
wahlfreien Bestandteil, der auch weggelassen werden kann. In diesem
Fall wird intern der Erhöhungswert 1 verwendet - der Inhalt der
Laufvariable wird also bei jedem Durchlauf (um genau zu sein: nach
Ausführung des Rumpfes) um 1 erhöht. Das gleiche Ergebnis wie
im obigen Beispiel kann man also auch erreichen durch...:DO durchlauf = 1 TO 10
say "Das ist Durchlauf Nummer:" durchlauf
END
Beachten Sie, daß wenn Sie eine "rückwärts" laufende Schleife haben wollen, Sie auch einen negativen
Erhöhungswert angeben müssen. Falls nicht, wird Ihre Schleife
ewig laufen, denn der Endwert (die Abbruchbedingung sozusagen) kann
dann nicht erreicht werden. Wenn Sie also so etwas wie eine
"Countdown"-Schleife basteln wollen, könnten Sie das
beispielsweise so erreichen:DO durchlauf = 10 TO 0 BY -1
say durchlauf
END
Die
Angaben für Start-, End- und Erhöhungswert der Laufvariablen
sind selbstverständlich beliebig wählbar. In diesem
Zusammenhang können Sie übrigens beruhigt an die Sache gehen:
Der Endwert muss nicht genau "getroffen" werden - es genügt, wenn
die Laufvariable dem Endwert entspricht oder "jenseits" davon liegt,
wird die Schleife beendet. Auch hierzu ein Beispiel:DO zähler = 7 TO 94 BY 17
say "wert von 'zähler' ist jetzt:" zähler
END
Das
bewirkt, daß die Laufvariable "zähler" vor dem ersten
Durchlauf auf den Wert 7 gesetzt wird und in den folgenden
Durchläufen um jeweils 17 erhöht wird: 24, 41, 58, 75, 92 und
schließlich 109. Da aber 109 bereits größer als der
angegebene Endwert 94 ist, wird die Schleife davor beendet. SAY
hinter das Ende der Schleife setzen, können Sie erkennen, daß zähler
tatsächlich den Wert 109 enthält, jedoch lediglich die
Schleife vor dem normalerweise folgenden Durchlauf beendet wurde:DO zähler = 7 TO 94 BY 17
say "wert von 'zähler' ist jetzt:" zähler
END
SAY "nach schleifenende:" zähler
...dieser code würde folgende Ausgabe erzeugen:wert von 'zähler' ist jetzt: 7Eine Wiederholungsschleife mit Laufvariable verhält sich also genau wie eine kopfgesteuerte Bedingungsschleife: Die Abbruchbedingung wird VOR Ausführung des Rumpfes geprüft. Es ist wichtig, dieses Verhalten im Hinterkopf zu haben, wenn man beispielsweise nach Beendigung der Schleife den Inhalt der Laufvariablen verwenden möchte, was wir übrigens in einem der folgenden Beispiele tun werden...
wert von 'zähler' ist jetzt: 24
wert von 'zähler' ist jetzt: 41
wert von 'zähler' ist jetzt: 58
wert von 'zähler' ist jetzt: 75
wert von 'zähler' ist jetzt: 92
nach schleifenende: 109
Die Ausgabe dieser Schleife sieht so aus:DO zähler = 99 to 1 BY -15
say "
wert von 'zähler' ist jetzt:" zähler
END
say "nach schleifenende:" zähler
wert von 'zähler' ist jetzt: 99Und das wär's zum Thema Schleifengrundlagen... ich wünsche fröhliches "Schleifen"! ;)
wert von 'zähler' ist jetzt: 84
wert von 'zähler' ist jetzt: 69
wert von 'zähler' ist jetzt: 54
wert von 'zähler' ist jetzt: 39
wert von 'zähler' ist jetzt: 24
wert von 'zähler' ist jetzt: 9
nach schleifenende: -6
name.1 = "Peter"Wir möchten jetzt, daß das Programm zunächst "Bitte Namen eingeben" anzeigt, dann den eingegebenen Namen in der Namenstabelle sucht, falls er gefunden wird die zugehörige Telefonnummer ausgibt und dann endet. Wir gehen auch davon aus, daß die Namen eindeutig sind (es kann also z.B. nur einen "Peter" geben).
name.2 = "Paul"
name.3 = "Karin"
name.4 = "Uwe"
name.5 = "Hugo"
name.6 = "Martin"
name.7 = "Mutti"
name.8 = "Vati"
telnr.1 = "010-99887"
telnr.2 = "020-88776"
telnr.3 = "030-77665"
telnr.4 = "040-66554"
telnr.5 = "050-55443"
telnr.6 = "060-44332"
telnr.7 = "070-33221"
telnr.8 = "080-22110"
Und das wäre schon mal die erste Fassung.SAY "Bitte Namen eingeben..."
PARSE PULL eingabe
DO eintrag = 1 to 8
IF name.eintrag = eingabe then
say name.eintrag ":" telnr.eintrag
END
LEAVE
ins Spiel kommt:Da wir nun innerhalb unseresSAY "Bitte Namen eingeben..."
PARSE PULL eingabe
DO eintrag = 1 to 8
IF name.eintrag = eingabe then
DO
say name.eintrag ":" telnr.eintrag
LEAVE
END
END
IF
mehr als eine Anweisung verwenden, müssen wir die in eine DO...END
-Struktur einbetten (erinnern Sie sich an die letzte Ausgabe?).Jau, das sieht schon viel besser aus... aber was läuft da ab?SAY "Bitte Namen eingeben..."
PARSE PULL eingabe
DO eintrag = 1 to 8
IF name.eintrag = eingabe then
LEAVE
END
if eintrag > 8 then
say "Keine Übereinstimmung gefunden für <"eingabe">"
else
say name.eintrag ":" telnr.eintrag
LEAVE
die
Schleife zwar direkt verlässt, den aktuellen Wert der
Laufvariablen jedoch beibehält. Zweitens befindet sich der Wert
der Laufvariablen (wie Sie bereits wissen) nach einer
vollständigen Schleifenbeendigung "jenseits" des angegebenen
Endwerts. Diese beiden Tatsachen haben wir im obigen code für
unsere Zwecke benutzt:LEAVE
sofort
verlassen. Wenn keine Übereinstimmung gefunden wurde, ist die
Schleife ebenfalls beendet da alle Einträge geprüft wurden
(der Endwert der Laufvariable ist überschritten).PARSE
erreichen,
daß REXX die Benutzereingabe automatisch in Großbuchstaben
umwandelt und Sie haben perfekte Übereinstimmungen, egal ob der
Anwender beispielsweise "Peter", "PeTeR" oder "peter" eingibt./* REXX Schleifenbeispiel 1 */
name.1 = "PETER"
name.2 = "PAUL"
name.3 = "KARIN"
name.4 = "UWE"
name.5 = "HUGO"
name.6 = "MARTIN"
name.7 = "MUTTI"
name.8 = "VATI"
telnr.1 = "010-99887"
telnr.2 = "020-88776"
telnr.3 = "030-77665"
telnr.4 = "040-66554"
telnr.5 = "050-55443"
telnr.6 = "060-44332"
telnr.7 = "070-33221"
telnr.8 = "080-22110"
SAY "Bitte Namen eingeben..."
PULL eingabe
eingabe = strip(eingabe) /* führende und folgende Leerstellen aus eingabe entfernen */
DO eintrag = 1 to 8
IF name.eintrag = eingabe then LEAVE
END
if eintrag > 8 then
say "Keine Übereinstimmung gefunden für <"eingabe">"
else
say name.eintrag ":" telnr.eintrag
/* Beispielcode Ende */
ITERATE
kann die
Ausführung des Schleifenrumpfes direkt abgebrochen werden um mit
dem nächsten Durchlauf zu beginnen - sofern dann natürlich
nicht schon die Abbruchbedingung "zuschlägt". Die Vorteile von ITERATE
steigen mit der Komplexität der dadurch "übersprungenen"
Verarbeitung. Das heißt, wenn der Rumpf Ihrer Schleife nur einen
einzelnen Befehl enthält, gewinnen Sie durch ITERATE
nicht besonders viel. Im Fall einer sehr komplexen und zeitaufwendigen Verarbeitung die damit übersprungen wird, kann ITERATE
den Ablauf um einiges beschleunigen.do jahrzehnt = 40 to 90 by 10
wenn jahrzehnt = 70 then ITERATE
say "Ich erinnere mich immer noch an die" jahrzehnt"'er Jahre"
end
ITERATE
folgen, werden damit übersprungen.ITERATE
durch folgende Codierung erreichen:Diese Variante gibt den Text nur aus, wenn die Laufvariable NICHT 70 ist.do jahrzehnt = 40 to 90 by 10
if jahrzehnt \= 70 then say
"Ich erinnere mich immer noch an die" jahrzehnt"'er Jahre"
end
ITERATE
ist also eigentlich ein expliziter Befehl, um
klar zu machen, daß eine bestimmte Anweisungsfolge innerhalb
einer Schleife übersprungen werden soll - ein sehr gut
selbstdokumentierender Befehl zur besseren Lesbarkeit, wenn Sie so
wollen.ITERATE
gibt und was dahinter steckt. Damit sind Sie etwas flexibler, wenn Sie
Ihre Programm- bzw. Schleifenabläufe konstruieren (müssen).
Daten und Quellen:
|
[Artikelverzeichnis]
editor@os2voice.org
[Vorherige Seite] [Inhaltsverzeichnis] [Nächste Seite]
VOICE Homepage: http://de.os2voice.org