Abschnitt 4 · Lektion 4
Schleifen
Bis hierher hat jede Zeile deines Codes höchstens einmal gearbeitet. Eine Schleife ändert das: Sie führt denselben Block so lange aus, bis eine Bedingung nicht mehr gilt. Damit werden aus drei Zeilen Code hundert Zeilen Ausgabe.
while, solange die Bedingung gilt
<?php
$guthaben = 100;
$preis = 30;
while ($guthaben >= $preis) {
$guthaben = $guthaben - $preis;
echo "Gekauft. Es bleiben $guthaben Euro.\n";
}
echo "Fuer eine weitere Karte reicht es nicht.\n"; while sieht aus wie ein if und verhält sich am Anfang auch so: Bedingung in runden Klammern,
Block in geschweiften. Der Unterschied kommt am Ende des Blocks. Ein if ist dann fertig, ein
while springt zurück nach oben und prüft noch einmal.
Im Beispiel wird gekauft, solange das Guthaben reicht. Bei 100 Euro und 30 Euro Kartenpreis sind das drei Durchgänge, danach stehen 10 Euro da und die Bedingung gilt nicht mehr.
Der Block muss die Bedingung verändern. Das ist die einzige Regel, die wirklich zählt. Ohne die Zeile, die das Guthaben verringert, wäre die Bedingung nach dem ersten Durchgang genauso wahr wie davor, und die Schleife liefe für immer. Dazu weiter unten mehr.
for, wenn du vorher weißt wie oft
<?php
for ($i = 1; $i <= 5; $i++) {
echo "Durchgang $i\n";
}
echo "Nach der Schleife steht $i drin.\n"; Sehr oft ist der Zähler die ganze Bedingung: einmal von 1 bis 10, für jede der fünf Zeilen, dreimal
hintereinander. Für diesen Fall gibt es for, und der Kopf nimmt alle drei Teile auf einmal auf,
getrennt durch Semikolons.
Der erste Teil läuft einmal ganz am Anfang und legt den Zähler an. Der zweite ist die Bedingung, die
vor jedem Durchgang geprüft wird. Der dritte läuft nach jedem Durchgang und zählt hoch, meistens mit
dem ++ aus Lektion 3.1.
Das ist genau dasselbe wie ein while mit einer Zeile davor und einer am Ende. Der Gewinn liegt
darin, dass alle drei Teile beieinanderstehen: Wer die Zeile liest, sieht sofort, wo die Schleife
anfängt, wo sie aufhört und in welchen Schritten sie geht.
Ein Detail für später: Die Zählvariable lebt nach der Schleife weiter. Im Beispiel steht danach eine
6 darin, denn erst bei diesem Wert war die Bedingung nicht mehr wahr. Im Reiter Debug kannst du
ihr dabei zusehen: Nach Aufzeichnen steht die echo-Zeile fünfmal untereinander, mit i=1 bis
i=5 als Chip, und an der Zeile nach der Schleife steht i=6.
Welches von beiden also? Die Faustregel: Weißt du beim Hinschreiben, wie oft es sein wird, nimm
for. Hängt es von etwas ab, das sich erst während der Schleife entscheidet, nimm while.
Der Fehler um genau eins
<?php
echo "Mit kleiner-gleich:\n";
for ($i = 1; $i <= 3; $i++) {
echo " $i\n";
}
echo "Mit kleiner:\n";
for ($i = 1; $i < 3; $i++) {
echo " $i\n";
}
echo "Und ab null gezaehlt:\n";
for ($i = 0; $i < 3; $i++) {
echo " $i\n";
} Diese Sorte Fehler hat einen eigenen Namen, weil sie so häufig ist. Zwischen < und <= liegt genau
ein Durchgang, und dieser eine Durchgang ist der Unterschied zwischen einer vollständigen Liste und
einer, bei der der letzte Eintrag fehlt.
Im Beispiel stehen drei Schleifen untereinander, die sich nur im Kopf unterscheiden: einmal drei
Zeilen, einmal zwei, einmal wieder drei, aber mit anderen Zahlen. Sieh dir die Ausgabe genau an, das
ist die halbe Lektion. Die andere Hälfte steht im Reiter Debug: Nach der ersten Schleife bleibt
i=4 übrig, nach der zweiten i=3. Genau dieser eine Schritt ist der Unterschied zwischen <=
und <.
Die dritte Form, von null bis unter die Grenze, sieht am Anfang ungewohnt aus. Sie ist in der Praxis trotzdem die häufigste, denn Listen fangen in PHP bei null an, und das siehst du in der nächsten Lektion.
do while, für den Fall danach
<?php
$vorrat = 0;
while ($vorrat > 0) {
echo "while: ein Stueck ausgegeben\n";
$vorrat--;
}
echo "Der while-Block ist gar nicht gelaufen.\n";
do {
echo "do while: ein Stueck ausgegeben\n";
$vorrat--;
} while ($vorrat > 0);
echo "Der do-Block ist einmal gelaufen, obwohl der Vorrat leer war.\n"; do while dreht die Reihenfolge um: erst der Block, dann die Prüfung. Damit läuft der Block
mindestens einmal, auch wenn die Bedingung von Anfang an nicht gilt.
Im Beispiel steht beides untereinander, mit einem leeren Vorrat. Das while gibt gar nichts aus, das
do while eine Zeile. Genau das ist der ganze Unterschied.
Gebraucht wird es selten, ungefähr immer dann, wenn man etwas erst tun und danach prüfen muss, ob es
geklappt hat. Erkennen solltest du es trotzdem, denn das kleine while am Ende ist leicht zu
übersehen, und dahinter steht ein Semikolon. Ein Block, dessen schließende Klammer eines braucht,
ist dir bisher nur beim match aus Lektion 4.2 begegnet.
Wenn die Schleife nicht aufhört
Jeder baut sie einmal: eine Bedingung, die immer wahr bleibt, weil im Block die Zeile fehlt, die den Zähler weiterdreht. Auf einem echten Server hängt sich das Programm dann auf, bis jemand eingreift.
In diesem Kurs passiert etwas Freundlicheres. Die Maschine, auf der dein Code läuft, gibt jedem Lauf
nur ein paar Sekunden: zehn beim Prüfen, dreißig bei einem Befehl, den du selbst tippst. Reißt du
diese Grenze, wird der Lauf abgeräumt, und im Terminal steht unter dem, was bis dahin ausgegeben
wurde, eine Zeile von der Plattform: Zeitlimit von 10 s erreicht, Prozess beendet. Wenn du sie
siehst, such nicht nach einem Tippfehler, sondern nach der Zeile, die deine Bedingung verändern
sollte und es nicht tut.
Der Reiter Debug zeigt dir dabei, was schiefgeht. Bau die Schleife oben einmal absichtlich
kaputt, nimm die Zeile mit $guthaben - $preis heraus und klick auf Aufzeichnen: In der Liste
steht dieselbe Zeile zweitausendmal untereinander, und ab der zweiten hängt an keiner mehr ein
Chip. Die Variable, die sich ändern müsste, ändert sich nie, und die Liste hört auf, bevor die Zeit
um ist.
Einen Exit-Code hat so ein Lauf übrigens auch, und zwar 124, das Zeichen von timeout für „die
Zeit war um”. Du bekommst ihn nur zu sehen, wenn du die Grenze selbst setzt:
timeout 5s php index.php > /dev/null; echo $? im Terminal bricht nach fünf Sekunden ab und
schreibt die 124 hin. Das > /dev/null wirft die Ausgabe dabei weg, denn um die geht es hier nicht,
und eine Schleife, die fünf Sekunden lang schreibt, füllt sonst das ganze Transkript. Ohne eigenes
timeout kommt das echo nie an die Reihe, die Plattform beendet die ganze Zeile auf einmal.
Zum Mitnehmen
Zehn Zeilen ausgeben, ohne zehnmal echo zu schreiben. Dafür gibt es while und for, und der Unterschied zwischen beiden ist keine Geschmacksfrage, sondern eine Frage danach, ob du vorher weißt, wie oft.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.