Steuerstrukturen   

Fallunterscheidung(Abfragen) und Wiederholungen(Schleifen)
Eine Besonderheit:  Der Zeitgeber (Timer)


Fallunterscheidung (Abfragen)

Die Fallunterscheidung ist einer grundlegensten Konzepte imperativer Programmiersprachen. 
Neben den auch aus anderen Programmiersprachen bekannten If-THEN-ELSE gibt es noch die eine ELSEIF Klausel. 
In eckigen Klammer Angeführtes ist optional, d.h. kann weggelasssen werden. 
Die mehrzeilige Fallunterscheidung hat folgende Syntax :

IF Boolescher Ausdruck THEN
   Anweisungsfolge...
[ELSEIF Boolescher Ausdruck THEN
   Anweisungsfolge...
[ELSEIF Boolscher Ausdruck THEN 
   Anweisungsfolge...]
....]
[ELSE    
   Anweisungsfolge....]
END IF

Es gibt noch eine einzeilige IF-Anweisung. Die Syntax dazu lautet:

IF Boolescher Ausdruck THEN Anweisungen [ELSE Anweisungen]

In der mehrzeiligen Variante kann es beliebig viele ELSEIF Blöcke geben. Der ELSE Block entfallen kann. 
Die Auswertung der booleschen Terme erfolgt dabei in der angegebenen Reihenfolge. 
D.h. ist ein Ausdruck wahr, so wird sein Zweig ausgeführt und die nachfolgenden Terme 
werden nicht mehr ausgewertet, also auch nicht mehr ausgeführt.
So ist es beispielsweise möglich, in nicht ausgewerteten Bedingungen (möglicherweise) undefinierte Ausdrücke anzugeben.

Beispiel:
IF x = 3 THEN
   ...
ELSEIF x = 4 THEN 
   ...
ELSEIF x = 5 THEN 
   ...
ELSE
   ...
END IF

Beispiel: Nicht strikte Auswertungen
Das folgende Beispiel macht keinerlei Probleme, obwohl eine Division durch eine Variable durchgeführt wird, 
die ja möglicherweise Null ist. Ist dies nämlich der Fall, so wird der ELSEIF-Audruck gar nicht ausgewertet.

IF x = 0 THEN   
   ...
ELSEIF 1/x > 0 THEN
   ...
END IF

Für einfache Fallunterscheidungen bietet sich auch die einzeilige IF-Anweisung an:

Beispiel: Einzeilige IF-Anweisung
Soll der Kehrwert eine Zahl x berechnet werden (also 1/x), man kann aber nicht garantieren, 
dass x ungleich Null ist, so muss man dies vor der Division abfangen. 
Im folgenden Beispiel wird für x = 0 das Ergebnis Null in die Variable result geschrieben, 
ansonsten der Kehrwert von x.

IF NOT (x = 0) THEN result = 1/x ELSE result = 0


Die SELECT CASE-Anweisung

Die SELECT CASE Anweisung bietet die Möglichkeit einen festen Ausdruck auf 
verschiedene Werte zu testen und dem entsprechend zu reagieren.

Syntax:

SELECT CASE testausdruck
CASE ausdruck-1
    [Anweisungen-1]...
[CASE ausdruck-n
    [Anweisungen-n]]
[CASE ELSE
    [Anweisungen des Else-Zweiges]]
END SELECT

Testausdruck ist der Ausdruck, der auf die verschiedenen Werte geprüft werden soll. 
Es können beliebig viele CASE Blöcke und optional ein CASE ELSE Zweig folgen.
Die Ausdrücke ausdruck-1 bis ausdruck-n können dabei durch Komma getrennte Listen, 
Bereich in der Form a TO b oder Vergleiche in der Form IS Vergleichsoperator ausdruck sein.

Beispiel: Signum-Funktion
Das folgende Beispiel liefert je nach Vorzeichen der Variable x die Werte result=-1 bei negativem x, 
result=0 bei x = 0 und result=+1 bei positivem x. Das gleiche leistet die Anweisung result = SGN(x).

SELECT CASE x
CASE is < 0
result = -1
CASE x = 0
result = 0
CASE ELSE
result = 1
END SELECT

Beispiel: Einfacher Primzahl-Test
Wie leistungsfähig die SELECT CASE Anweisung ist, demonstriert das folgende Beispiel, 
das für natürliche Zahlen x, die kleiner 30 sind, feststellt, ob sie Primzahlen sind.

DIM result AS String

SELECT CASE x
CASE 2,3,5,7,11,13,17,19,23,29
result = "x ist Primzahl"
CASE 0 TO 1
result = "x zwischen Null und Eins"
CASE is < 0
result = "x ist negativ"
CASE is > 30
result = "x ist größer als 30"
CASE 
END SELECT

Die SELECT CASE Anweisung kann natürlich auch als IF-THEN-ELSE Anweisung implementiert werden, 
wie gleich an diesem Beispiel vorgeführt wird. Diese Lösung ist allerdings äußerst unelegant, 
was natürlich für SELECT CASE spricht.

DIM result AS String

IF x=2 OR x=3 OR x=5 OR x=7 OR x=11 OR x=11 OR x=13 _
   OR x=17 OR x=19 OR x=23 OR x=29 THEN
   result = "x ist Primzahl"
ELSEIF 0 =< x AND x =< 1 THEN
   result = "x zwischen Null und Eins"
ELSEIF x < 0 THEN
   result = "x ist negativ"
ELSEIF x > 30 THEN
   result = "x ist größer als 30"
ENDIF

SCHLEIFEN

FOR - Schleife

Die FOR-Schleife (gezählte Schleife) hat folgende Syntax :

FOR Variable = Startwert TO Endwert [STEP Schrittweite]
   Anweisungsfolge
   ...
   [EXIT FOR]
   ...
NEXT [Variable]

Bei der gezählten Schleife wird eine Zählvariable von einem Startwert zu einem Endwert hochgezählt (heruntergezählt). 
Das Vorzeichen der Schrittweite gibt an, ob hoch- oder heruntergezählt wird. 
Vor jedem Schleifendurchlauf wird überprüft, ob der Zähler schon echt größer (echt kleiner) als der Endwert ist. 
In diesem Fall wird die Schleife nicht mehr ausgeführt.
Das EXIT FOR verlässt die Schleife ohne Auswertung des Zählers und kann entfallen.
Es ist zu beachten, dass der Zähler und auch Start- und Endwert, falls diese als Variablen vorliegen, 
innerhalb der Schleife nicht geändert werden sollten (das ist das kein besonders guter Stil, 
da das Programm dadurch nicht lesbarer wird!). 
Ferner sollte der Zähler nach Bendigung der Schleife auch nicht weiter verwendet werden 
(in manchen Programmiersprachen ist der Zähler nach einer FOR-Schleife die obere Grenze der Schleife oder auch obere Grenze plus Eins).
Manche Compiler-Hersteller treffen zwar Aussagen über diese Grenzfälle, aber ob die auf anderen Plattformen oder anderen Programmiersprachen gelten, ist mehr als fraglich. Damit wird eine Portierung erheblich erschwert.

Beispiel: FOR-Schleife
Das folgende (nicht sonderlich sinnvolle) Beispiel summiert die ersten tausend Zahlen auf.

DIM summe AS INTEGER
DIM i as INTEGER
FOR i = 1 TO 1000 
   summe = summe + i
NEXT i 

Beispiel: Rückwärts gezählte Schleife

Die folgende Schleife macht genau dasselbe nur in umgekehrter Reihenfolge.
DIM summe AS INTEGER
DIM i as INTEGER
FOR i = 1000 TO 1 STEP -1
   summe = summe + i
NEXT i 

WHILE - Schleife

Die WHILE-Schleife ist eine Schleife mit Anfangsbedingung. Vor jedem Schleifendurchlauf wird die Bedingnung ausgewertet und bei dem Ergebnis FALSE wird die Schleife verlassen.

Die WHILE-Schleife hat folgende Syntax :

WHILE Boolescher Ausdruck
   Anweisungsfolge....
WEND

Beispiel: Wurzel von a

Das folgende Beispiel berechnet die Quadratwurzel von a = 2 mit einer Genauigkeit von epsilon = 0.001. Das Ergebnis wird in der Variablen result abgelegt. Um einzusehen, dass result wirklich gegen Wurzel a geht, muss man sich erstmal vor Augen führen, dass das Ganze gegen eine Zahl z konvergiert (was nicht so einfach ist). Für ein solches z muss gelten: z = 0.5*(z+a/z). Multipliziert man diese Gleichung mit z, so ergibt sich: z2 = 0.5*z + 0.5*a. Und daraus ergibt sich z2 = a. (Einen ausführlichen Beweis findet man beispielsweise im Buch Analysis I von Otto Forster, Vieweg Verlag.)

DIM epsilon AS DOUBLE
DIM result AS DOUBLE
DIM a AS DOUBLE

a = 2
result = a / 2
epsilon = 0.001

WHILE ABS(result^2 - a) >= epsilon
    result = 0.5*(result+a/result)
WEND

DO LOOP - Schleife

Die DO LOOP-Schleife ist die flexibelste Schleife. Mit ihr kann man sowohl unbedingte Schleifen, 
als auch Schleifen mit Anfangs-, End- und Abbruchbedingung realisieren.
Die unbedingte Schleife (Syntax 1) wird durch die Abbruchanweisung EXIT DO im Schleifenrumpf verlassen. 
Die Schleife mit Anfangsbedingung (Syntax 2) entspricht der WHILE Schleife. 
Bei der Schleife mit Endbedingung (Syntax 3) wird nach jedem Schleifendurchlauf überprüft, 
ob der Ausdruck noch wahr ist, im Gegensatz zur Schleife mit Abbruchbedingung (Syntax 4), 
in der nach jedem Schleifendurchlauf geprüft wird, ob die Abbruchbedingung schon erfüllt ist. 

Die Syntax lautet:
Syntax 1 - unbedingte Schleife Syntax 2 - Schleife mit Anfangsbedingung

  DO
     Anweisungsfolge
     ....
     EXIT DO
     ....
     Anweisungsfolge
     ....
  LOOP

  

  DO WHILE Boolescher Ausdruck
     Anweisungsfolge
     ....
     [EXIT DO]
     ....
  LOOP

  

 
Syntax 3 - Schleife mit Endbedingung Syntax 4 - Schleife mit Abbruchbedingung

  DO
     Anweisungsfolge
     ....
     [EXIT DO]
     ....
  LOOP WHILE Boolescher Ausdruck  
 
  

  DO
     Anweisungsfolge
     ....
     [EXIT DO]
     ....
  LOOP UNTIL Boolescher Ausdruck
  


Bei den letzten beiden Schleifentypen wird der Rumpf mindestens einmal ausgeführt. Schleifen der ersten Art haben sinnvollerweise mindestens ein EXIT DO und werden unmittelbar bei der Ausführung dieses Befehls verlassen. Die EXIT DO's können in der zweiten, dritten und vierten Syntax-Form entfallen.

Beispiel 1: Arithmetisches Mittel
Beispiel (1) berechnet das arithmetische Mittel (engl. mean) von echt positiven Zahlen in einem Array, die letzte Zahl ist dabei von einer Null gefolgt.

DIM x (1 TO 10) AS BYTE
DIM mean AS SINGLE, sum AS INTEGER
DIM i AS INTEGER
x(1) = 1
x(2) = 4
x(3) = 3
x(4) = 0

i = 0

DO 
   i = i + 1
      IF x(i) = 0 THEN EXIT DO
   sum = sum + x(i)
LOOP
durchschnitt = sum / (i-1)

Beispiel 2: Quotient und Rest

Beispiel (2) führt eine Ganzzahldivision mit Rest durch. Dabei enthählt quotient = x \ y und remainder = x MOD y. 
(Dies ist zugegebenermaßen nicht sehr effizient.)

DIM x AS INTEGER, y AS INTEGER
DIM quotient AS INTEGER
DIM remainder AS INTEGER

x = 77
y = 13
quotient = 0

DO WHILE x >= y 
  x = x - y
  quotient = quotient + 1
LOOP

remainder = x

Beispiel 3: Wurzel von a mit Endbedinung
Beispiel (3) berechnet die Wurzel einer Zahl a mit Hilfe einer Schleife mit Endbedingung. Dabei legt epsilon die Genauigkeit fest. 

DIM epsilon AS DOUBLE
DIM result AS DOUBLE
DIM a AS DOUBLE

a = 2
result = a / 2
epsilon = 0.001

DO 
result = 0.5*(result+a/result)
LOOP WHILE ABS(result^2 - a) >= epsilon

Beispiel 4: Wurzel von a mit Abbruchbedinung
Beispiel (4) berechnet ebenso die Wurzel einer Zahl a, diesmal aber mit Hilfe einer Schleife mit Abbruchbedingung.

DIM epsilon AS DOUBLE
DIM result AS DOUBLE
DIM a AS DOUBLE

a = 2
result = a / 2
epsilon = 0.001

DO
result = 0.5*(result+a/result)
LOOP UNTIL ABS(result^2 - a) < epsilon

Das Zeitgeber-Objekt (Timer, Uhr)

Das Zeitgeberobjekt löst ein Ereignis in regelmäßigen Intervallen (Zeiteingabe in Millisekunden) aus.
Dadurch kann ebenfalls eine zeitgesteuerte Wiederholung realisiert werden.