SELFHTML/Quickbar  CGI/Perl  Perl-Sprachelemente


Schleifen und Sprungbefehle

Diese Seite ist ein Dokument mit Informationstext

 Schleifen mit while/until
 Schleifen mit do..while/until
 Schleifen mit for/foreach
 Sprungbefehle in Perl

 

Schleifen mit while/until

Mit Hilfe von while-Schleifen können Sie Programmanweisungen solange wiederholen, wie die Bedingung, die in der Schleife formuliert wird, erfüllt ist. Mit until-Schleifen können Sie Programmanweisungen wiederholen, bis die Bedingung, die in der Schleife formuliert wird, erfüllt ist.

Beispiel 1:

#!/usr/bin/perl

$i = 1;
print "zuerst die Wurzeln von 1 bis 10...\n\n";
while($i <= 10)
 {
  print "Die Wurzel von ", $i, " ist ", sqrt($i), "\n";   
  $i++;
 }
$i = 1;
print "und jetzt die Quadratzahlen von 1 bis 10...\n\n";
until($i > 10)
 {
  print "Das Quadrat von ", $i, " ist ", $i * $i, "\n";   
  $i++;
 }

Beispiel 2:

#!/usr/bin/perl

$AccessDatei = "../../docs/access.log";
$Zugriffe = 0;
$Erfolge = 0;
open(DATEI, "<".$AccessDatei) || die "Datei nicht gefunden!\n";
 {
  while(<DATEI>)
   {
    if(/HTTP\/1.0" 200/)  # nach 'HTTP/1.0" 200' suchen (= erfolgreicher Zugriff)
     {
      $Erfolge++;
     }
    $Zugriffe++;
   }
 }
print "Von ", $Zugriffe, " Zugriffen waren ", $Erfolge, " erfolgreich\n";

Erläuterung:

Eine while-Schleife (wie im obigen Beispiel 1, erster Teil) beginnt mit dem Wort while (while = solange). Dahinter folgt, in Klammern stehend, die Bedingung. Um eine Bedingung zu formulieren, brauchen Sie in der Regel  Vergleichsoperatoren. Der Inhalt der Schleife wird solange wiederholt, wie die Schleifenbedingung wahr ist.

Eine until-Schleife (wie im obigen Beispiel 1, zweiter Teil) beginnt mit dem Wort until (until = bis). Dabei handelt es sich um eine andere logische Formulierung als bei while. Der Inhalt der Schleife wird solange wiederholt, bis die Schleifenbedingung wahr ist. Ansonsten gelten für until-Schleifen die gleichen Regeln wie für while-Schleifen. Achten Sie jedoch auf eine genaue logische Formulierung der Schleifenbedingung! So bedeuten im Beispiel die Schleifenbedingungen while($i <= 10) und until($i > 10) genau das gleiche.

Das obige Beispiel 2 zeigt einen speziellen, Perl-typischen Anwendungsfall der Schleife mit while. In dem Beispiel wird eine Datei zeilenweise eingelesen. Es handelt sich um eine Log-Datei, wie sie ein WWW-Server zum Protokollieren der Zugriffe erzeugt. In diesem speziellen Fall ist für die Schleifenbedingung kein Vergleichsoperator nötig. Die Schleife bricht automatisch ab, wenn alle Zeilen der Datei gelesen wurden (zu diesem Beispiel siehe auch  Dateien lesen und schreiben sowie für das Suchen nach Zeichenketten den Abschnitt  Reguläre Ausdrücke).

Notieren Sie Anweisungen innerhalb der Schleifen immer in geschweiften Klammern { und }, auch wenn es nur eine einzige Anweisung ist.

Beachten Sie:

Achten Sie bei Schleifen mit Vergleichsoperatoren in der Schleifenbedingung immer darauf, daß es mindestens eine Möglichkeit gibt, um die Schleife nach einer angemessenen Zeit zu beenden. Andernfalls erzeugen Sie eine sogenannte "Endlosschleife", die zu Systemabstürzen führen kann!

Um Endlosschleifen zu vermeiden, brauchen Sie irgendetwas, das irgendwann zu einem Ausweg aus der Schleife führt. Meistens werden zu diesem Zweck sogenannte "Zähler" definiert, im Beispiel 1 etwa der  Skalar $i. Dieser Skalar hat im Beispiel einen Anfangswert von 1 und wird innerhalb der Schleife bei jedem Durchgang mit der Anweisung $i++; um 1 erhöht, so daß die Schleifenbedingung irgendwann erreicht wird.

Eine andere Möglichkeit, Schleifen zu kontrollieren und abzubrechen, bieten die  Sprungbefehle.

 

Schleifen mit do..while/until

Bei dieser Art von Schleife wird nicht zuerst die Schleifenbedingung ausgewertet und davon abhängig der Anweisungsblock innerhalb der Schleife ausgeführt, sondern es wird zuerst der Anweisungsblock ausgeführt, und anschließend wird erst die Schleifenbedingung ausgewertet. Die Schleife wird also in jedem Fall mindestens einmal durchlaufen, egal wie die Schleifenbedingung lautet. Das kann sinnvoll sein, wenn Sie in der Schleifenbedingung mit Variablen arbeiten, deren genauen Wert Sie zum Zeitpunkt des Schleifenbeginns nicht kennen.

Beispiel 1:

#!/usr/bin/perl

$Name = "Stefan";
do
 {
  print $Name, "\n";
  $Name = "Virtuella";
 }
while($Name ne "Virtuella")

Beispiel 2:

#!/usr/bin/perl

$Name = "Stefan";
do
 {
  print $Name, "\n";
  $Name = "Virtuella";
 }
until($Name eq "Virtuella")

Erläuterung:

Eine Schleife dieses Typs beginnt mit dem Schlüsselwort do. Anschließend folgt der Anweisungsblock der Schleife, wie üblich markiert durch geschweifte Klammern { bzw. }. Nach der schließenden geschweiften Klammer folgt die Schleifenbedingung. Die Schleifenbedingung können Sie mit while (solange) oder mit until (bis) formulieren. Dabei gelten die gleichen Regeln wie bei  Schleifen mit while/until.

Beachten Sie:

Achten Sie auch bei do..while/until-Schleifen darauf, daß keine Endlosschleifen entstehen. Die beiden obigen Beispiele bewirken jeweils das gleiche, nämlich die einmalige Ausgabe des Namens "Stefan". Beide Beispiele unterscheiden sich nur durch die unterschiedlich formulierte Schleifenbedingung. Wenn Sie in diesen beiden Beispielen die  Vergleichsoperatoren eq und ne umgekehrt einsetzen würden, würde in beiden Fällen eine Endlosschleife entstehen!

 

Schleifen mit for/foreach

Schleifen mit for oder foreach unterscheiden sich von Schleifen mit while oder until dadurch, daß sie bereits in der Schleifenbedingung eine feste Abbruchbedingung vorsehen. Solche Schleifen eignen sich deshalb vor allem für Fälle, in denen "Anfangswert" und "Endwert" von vorneherein feststehen.

Beispiel 1:

#!/usr/bin/perl

for($i=0;$i<=255;$i++)
 {
  printf("%4d = %2X",$i, $i);
  if($i % 8 == 0)
   { print "\n"; }
 }

Beispiel 2:

#!/usr/bin/perl

@Alphabet = (A..Z);
for(@Alphabet)
 {
  print $_, " ist der ", $i+1, ". Buchstabe im Alphabet\n";
  $i++;
 }

Beispiel 3:

#!/usr/bin/perl

foreach $i (1..100)
 {
  next if $i % 2 == 0;
  print $i, "\n" if $i % 3 == 0;
 }

Erläuterung:

Eine for-Schleife beginnt mit dem Wort for. Dahinter wird, in Klammern stehend, die Schleifenbedingung formuliert. Bei der "klassischen", C-konformen for-Schleife werden innerhalb der Schleifenbedingung drei Anweisungen notiert. In der ersten Anweisung wird ein Schleifenzähler definiert und initialisiert. Im obigen Beispiel 1 wird ein Zähler $i definiert und mit dem Wert 0 initialisiert. Die zweite Anweisung enthält die Bedingung, ab der die Schleife beendet wird. Dazu brauchen Sie  Vergleichsoperatoren. In der dritten Anweisung wird der Schleifenzähler so verändert, daß er irgendwann die in der zweiten Anweisung notierte Bedingung erfüllt. Im Beispiel wird $i bei jedem Schleifendurchgang um 1 erhöht, so daß der Wert irgendwann größer 255 ist und damit die Bedingung der zweiten Anweisung erfüllt.
Das Beispiel 1 benutzt den Schleifenzähler, um bei jedem Schleifendurchgang die umgerechnete Hexadezimalzahl zum aktuellen Wert von $i auszugeben. Die Abfrage if($i % 8 == 0) enthält eine Modulodivision und bewirkt, daß nach 8 Ausgaben eine neue Zeile bei der Ausgabe begonnen wird. Die Ausgabe selbst erfolgt mit Hilfe der printf-Funktion (C-konform), die sauber formatierte Ausgaben auf die Standardausgabe erlaubt. Diese Funktion ist allerdings für CGI-Zwecke (also für Ausgaben in HTML-Form) nicht so sehr geeignet.

Das obige Beispiel 2 zeigt einen speziellen, Perl-typischen Anwendungsfall der for-Schleife. Diese Form ist sehr praktisch, um Elemente einer  Liste oder eines  Hashs der Reihe nach abzuarbeiten. Im Beispiel 2 wird eine Liste @Alphabet mit allen Großbuchstaben des Alphabets definiert. Mit der Anweisung for(@Alphabet) wird eine Schleife über diese Liste gelegt. Die Schleife wird automatisch so oft durchlaufen, wie die Liste Elemente hat. Um das jeweils aktuelle Listenelement anzusprechen, wird innerhalb der Schleife die  vordefinierte Variable $_ verwendet. In ihr ist der Inhalt des jeweils aktuellen Listenelements gespeichert.

Eine weitere Perl-typische Konstruktion ist eine Schleife mit foreach. Im obigen Beispiel 3 kommt eine solche Schleife zum Einsatz. Bei diesem Schleifentyp wird als Schleifenbedingung in Klammern ein eindeutiger Bereich definiert, z.B. (von Zahl..bis Zahl) oder Buchstaben (von Buchstabe..bis Buchstabe). Die Schleife wird automatisch so oft durchlaufen, bis alle Elemente innerhalb des definierten Bereichs abgearbeitet sind.
Wenn Sie einen Zähler innerhalb der Schleife für die gewünschte Prozedur einsetzen wollen, können Sie eine Zählervariable zwischen foreach und der Schleifenbedingung definieren, so wie in Beispiel 3 oben der Skalar $i.
Das obige Beispiel 3 gibt alle Zahlen zwischen 1 und 100 aus, die ungerade und durch 3 teilbar sind. Dabei hilft der  Sprungbefehl next.

 

Sprungbefehle in Perl

Perl wird nachgesagt, daß man damit nicht ordentlich strukturiert programmieren kann. Zwar stellt Perl mittlerweile alles zur Verfügung, was zu einem sauber strukturierten und sogar objektorientierten Programmieren gehört, doch Perl ist und bleibt eine Sprache für Scripts, bei denen sich Programmierer oft nicht die Mühe machen, den Programmablauf auf einzelne  Unterprogramme zu verteilen. Eine häufig benutzte Alternative zu strukturierter Programmierung sind Sprungbefehle zu einer beliebigen anderen Stelle im Programm. Auch innerhalb von Schleifen sind Sprungbefehle sehr beliebt, um zum Beispiel den nächsten Schleifendurchlauf vorzeitig zu erzwingen, oder um eine Schleife abzubrechen.

Beispiel 1:

#!/usr/bin/perl

# Raten Sie mal, welche Zahl $i am Ende als Ergebnis ausgibt

$i = 1;
goto Ergebnis;
while($i < 1000)
 {
  ++$i;
  if($i % 3 == 0)
   {
    redo;    
   }
  elsif($i % 7 == 0)
   {
    next;    
   }
  elsif($i % 13 == 0)
   {
    last;    
   }
 }
Ergebnis:
print "Ergebnis: ", $i;

Beispiel 2:

#!/usr/bin/perl

while($i < 10)
 {
  ++$i;
  if($i % 2 != 0)
   {
    redo;
   }
 }
continue
 {
   print $i, "\n";    
 }

Erläuterung:

Folgende Sprungbefehle stehen in Perl zur Verfügung:

goto springt zu einer beliebigen anderen Stelle im Programm. Dazu muß diese Stelle jedoch ein "Label" erhalten (vergleichbar mit einem Verweisanker innerhalb einer HTML-Datei). Ein Label definieren Sie, indem Sie einen Namen notieren und dahinter einen Doppelpunkt. Im obigen Beispiel wird in der vorletzten Zeile ein Label mit dem Namen Ergebnis: definiert. Mit einem goto-Befehl wie am Beginn des Beispiels können Sie zu einem solchen Label springen.

redo ist zur Verwendung innerhalb von Schleifen gedacht. Der aktuelle Schleifendurchgang wird abgebrochen. Der nächste Schleifendurchgang wird gestartet, allerdings ohne daß die Schleifenbedingung neu bewertet wird. Wenn Sie also beispielsweise einen Zähler in einer Schleifenbedingung hochzählen, wird die Schleife bei redo erneut durchlaufen, ohne daß der Zähler weiter hochgezählt wird.

next ist ebenfalls zur Verwendung innerhalb von Schleifen gedacht. Der aktuelle Schleifendurchgang wird abgebrochen. Der nächste Schleifendurchgang wird gestartet, und die Schleifenbedingung wird dabei ebenfalls ausgewertet.

last bricht eine Schleife sofort ab.

continue ist in Perl ein Spezialfall und anders zu behandeln als etwa in C. Das obige Beispiel 2 zeigt eine typische Verwendungsweise. continue leitet einen eigenen Anweisungsblock ein, genauso wie eine Schleife. Innerhalb dieses Anweisungsblocks, der wie üblich mit geschweiften Klammern { und } markiert wird, können Sie beliebige Anweisungen notieren. Wenn ein solcher continue-Block unmittelbar hinter einem Schleifenblock steht, wird er mit jedem Schleifendurchlauf mit durchlaufen. Mit einem Sprungbefehl wie redo innerhalb des Schleifenblocks können Sie verhindern, daß der continue-Block ausgeführt wird. Im obigen Beispiel 2 wird mit dieser Konstruktion erreicht, daß alle geraden Zahlen zwischen 1 und 10 ausgegeben werden.

weiter: Operatoren
zurück: Bedingte Anweisungen
 

SELFHTML/Quickbar  CGI/Perl  Perl-Sprachelemente

© 1998  Stefan Münz, muenz@csi.com