Schleife (Programmierung)

aus Wikipedia, der freien Enzyklopädie
(Weitergeleitet von While-Schleife)
Wechseln zu: Navigation, Suche

Eine Schleife ist eine Kontrollstruktur in Programmiersprachen. Sie wiederholt einen Anweisungs-Block – den so genannten Schleifenrumpf oder Schleifenkörper – so lange, wie eine Schleifenbedingung als Laufbedingung gültig bleibt bzw. als Abbruchbedingung nicht eintritt. Schleifen, deren Schleifenbedingung immer zur Fortsetzung führt oder die keine Schleifenbedingung haben, sind Endlosschleifen.

Schleifen können beliebig verschachtelt werden: Innerhalb des Schleifenkörpers der äußeren Schleife befindet sich wiederum eine Schleife, sie liegt innen, oder unter der äußeren Schleife. Jede Schleife kann in eine rekursive oder sogar endrekursive Form umgewandelt werden. Zur Beschleunigung des Programmablaufs werden Schleifen oft durch den Compiler entrollt.

Inhaltsverzeichnis

Arten [Bearbeiten]

Prinzipiell werden unterschieden:

  • die kopfgesteuerte oder vorprüfende Schleife, bei der die Schleifenbedingung geprüft wird, bevor der Schleifenrumpf durchlaufen wird (meist mit WHILE = solange eingeleitet).
  • die fußgesteuerte oder nachprüfende Schleife, bei der nach dem Durchlauf des Schleifenrumpfes die Schleifenbedingung überprüft wird (meist als DO...WHILE = „ausführen...solange“ oder REPEAT...UNTIL = „wiederholen...bis“ Konstrukt).
  • die Zählschleife, eine Sonderform der kopfgesteuerten Schleife (meist als FOR = für -Schleife implementiert).
  • die Mengenschleife, eine Sonderform der Zählschleife (meist als FOREACH = „für jedes Element der Menge“ implementiert).

Eine Endlosschleife ohne Schleifenbedingung kann nur von außen unterbrochen werden, etwa durch einen Programmabbruch durch den Benutzer, Reset, Interrupt, Defekt, Abschalten des Gerätes oder ähnliches.

Schleifenabbruch im Sonderfall [Bearbeiten]

In Fällen, die schwierig als Schleifenbedingung zu fassen sind, kann eine Schleife meist abgebrochen werden.

Iterationsabbruch [Bearbeiten]

Es wird lediglich die aktuelle Iteration abgebrochen: Der Rest des aktuellen Schleifenrumpfs wird übersprungen. Mitunter kann in verschachtelten Schleifen auch Bezug genommen werden auf eine weiter außen liegende Schleife - die aktuelle innerste wird dann komplett abgebrochen.

Schleifenabbruch [Bearbeiten]

Meist gibt es auch einen Befehl zum Gesamt-Abbruch der Schleife, das Programm wird dann mit der ersten Anweisung nach der Schleife fortgesetzt. Oft ist in verschachtelten Schleifen auch eine Bezugnahme auf eine weiter außen liegende Schleife möglich, was die inneren dann ebenfalls komplett abbricht.

Beispiele [Bearbeiten]

Die nachfolgenden Beispiele in Pseudocode finden sich in den jeweiligen Programmiersprachen meist sehr ähnlich.

Zählschleife [Bearbeiten]

FOR Iterator:=Anfangszahl TO Endezahl STEP Schrittweite DO Schleifenrumpf.

Bei einer For-Schleife zählt der Computer von einer Anfangszahl bis zu einer Endzahl und wiederholt dabei jedes mal den Codeblock („Schleifenrumpf“). Die aktuelle Zahl wird in eine Variable („Iterator“) gesetzt, damit sie bei Bedarf in dem Codeblock Verwendung finden kann (Details siehe Artikel For-Schleife). Häufig ist die Zählschleife auf Ganzzahlen beschränkt. Ein Ändern der Iterator-Variablen im Schleifenkörper gilt als schlechter Programmierstil, da es oft zu schwer verständlichem Code führt - es läuft der Denkweise zuwider, direkt am Schleifenkopf die Anzahl der Durchläufe ablesen zu können. Das Ändern der Iterator-Variablen im Schleifenkörper ist bei vielen Programmiersprachen verboten.

Kopfgesteuerte Schleife [Bearbeiten]

WHILE Logischer Ausdruck  DO Schleifenrumpf. 

Bei einer While-Schleife wird der Schleifenrumpf solange wiederholt, wie der logische Ausdruck zu wahr auswertet. Eine logische Operation kann beispielsweise sein: (x > 4) Solange diese Bedingung wahr ist, läuft die Schleife. Wird der Inhalt der logischen Operation nicht im wiederholten Teil des Programmcodes verändert, ist diese Kontrollstruktur meist nicht die richtige, weil diese Schleife sonst kein einziges Mal durchlaufen wird oder unendlich lang läuft.

Fußgesteuerte Schleife [Bearbeiten]

DO Schleifenrumpf WHILE Logischer Ausdruck

bzw.

REPEAT Schleifenrumpf UNTIL Logischer Ausdruck

Funktioniert genau so wie die While-Schleife, allerdings wird die Schleifenbedingung erst nach dem Durchlauf des eingeschlossenen Programmcodes überprüft. Auf While (dt: solange) folgt eine Laufbedingung, auf Until (dt: bis) eine Abbruchbedingung.

Mengenschleife [Bearbeiten]

FOREACH Iterator OF Menge DO Schleifenrumpf

Funktioniert wie eine Zählschleife mit dem Schleifenkörper

FOR Iterator2 := 1 TO Mächtigkeit(Menge) DO
  BEGIN
    Iterator := Iterator2-tes Element von Menge ;
    Schleifenrumpf
  END

Iterationsabbruch [Bearbeiten]

CONTINUE

bzw.

CONTINUE Schleifenbezeichner

Die erste Variante bricht die aktuelle Iteration ab, es geht weiter mit der Prüfung der Laufbedingung für die nächste Iteration. Die zweite Variante beendet in verschachtelten Schleifen alle inneren komplett und wirkt wie die erste Variante für diejenige äußere Schleife, welche durch Schleifenbezeichner angesprochen wird. Oft kommt hier entweder ein Name ähnlich einer Sprungmarke zum Einsatz; in Zählschleifen erfolgt die Identifizierung mitunter über den Namen des Iterators.

Schleifenabbruch [Bearbeiten]

BREAK

bzw.

BREAK Schleifenbezeichner

Die erste Variante bricht die aktuelle Schleife ab, es geht weiter mit der ersten Anweisung nach der Schleife. Die zweite Variante beendet in verschachtelten Schleifen alle inneren komplett und sowie diejenige äußere Schleife, welche durch Schleifenbezeichner angesprochen wird. Oft kommt hier entweder ein Name ähnlich einer Sprungmarke zum Einsatz; in Zählschleifen erfolgt die Identifizierung mitunter über den Namen des Iterators.

Implementierung mit Sprungbefehlen [Bearbeiten]

Früher wurden auch in Hochsprachen-Programmen häufig unbedingte Sprünge (Goto-Befehle) verwendet. Sprachen, die Sprunganweisungen verwenden, ermöglichen das Einfügen einer Marke (engl. Label). Eine solche Marke kann dann als Ziel einer Goto-Anweisung dienen.

Nach heutigen Programmierparadigmen, namentlich der strukturierten Programmierung, wird von der Verwendung von Goto-Sprüngen abgeraten, da durch diese der berüchtigte "Spaghetticode" entsteht. Prinzipiell lässt sich jedoch jede Schleifenform mit Sprungbefehlen abbilden.

For-Schleife [Bearbeiten]

Es gibt mehrere Alternativen, For-Schleifen mit Hilfe einfacherer Befehle zu implementieren. Im Normalfall verhalten sich diese Alternativen gleich, aber in einigen speziellen Situationen gibt es Unterschiede. Beispiele für spezielle Situationen sind:

  • Die Schrittweite ist 0 (nicht in allen Varianten der For-Schleife möglich).
  • Der Startwert oder der Endwert sind die kleinst- oder größtmögliche darstellbare Zahl.

Eine ausführlichere Darstellung der Varianten befindet sich im Artikel For-Schleife.

While-Do-Schleife [Bearbeiten]

WHILE Logischer Ausdruck  DO Befehlssequenz. 

entspricht:

Marke1:
IF NOT Logischer Ausdruck GOTO Marke2 (bedingter Vorwärtssprung)
Befehlssequenz
GOTO Marke1 (Rückwärtssprung)
Marke2:

Die Befehlssequenz wird keinmal durchlaufen, wenn der logische Ausdruck schon zu Beginn falsch ist.

Do-While-Schleife [Bearbeiten]

DO Befehlssequenz WHILE Logischer Ausdruck

entspricht:

Marke1:
Befehlssequenz
IF Logischer Ausdruck GOTO Marke1 

Hier wird die Schleife in jedem Fall einmal durchlaufen. Die Do-While-Schleife ist damit nachprüfend.

Repeat-Until-Schleife [Bearbeiten]

REPEAT Befehlssequenz UNTIL Logischer Ausdruck

entspricht:

Marke1:
Befehlssequenz
IF NOT Logischer Ausdruck GOTO Marke1 (bedingter Rückwärtssprung)

Befehle in Assemblersprache [Bearbeiten]

Assemblercode verfügt normalerweise nicht über die aus höheren Programmiersprachen bekannten for/while/repeat Konstrukte. Da aber auch hier Schleifen eingesetzt werden müssen (Verzögerung durch aktives Warten (s.u.), serielles adressiertes Verarbeiten von Daten), stehen einfache Sprungbefehle für unbedingte und bedingte Sprünge zur Verfügung.

Letztere entscheiden anhand eines Statusflags der CPU (z.B. Zero-Flag), ob gesprungen werden muss. Trifft die Voraussetzung nicht zu, so wird der Programmcounter (PC) einfach um eins erhöht. Es wird dann also als Nächstes der Befehl nach dem bedingten Sprungbefehl ausgeführt.

Beispiel für Code für einen AVR-Mikrocontroller, der unter Verwendung einer Schleife um insgesamt 5000 Takte durch aktives Warten verzögert:

 ; delaying 4998 clocks
            ldi R0, $07
 Label0:    ldi R1, $ed
 Label1:    dec R1       ; Vermindert Inhalt in R1 um 1
            brne Label1  ; Sprung nur, wenn R1 nun nicht 0 ist.
            dec R0       ; alternativ gehts hier weiter
            brne Label0
 ; delaying 2 clocks
            nop
            nop

Häufig gibt es angepasste Assemblerbefehle, die mehrere Aktionen kombinieren („Prüfe Iterator auf Ist-Gleich-..., wenn ungleich springe nach ...“, „Zähle Iterator 1 herunter, wenn er noch immer größer 0 ist, springe nach ...“). Oft setzen diese voraus, dass ein Zähl-Iterator sich z. B. in einem bestimmten Register befindet.