Inhaltsverzeichnis

2.8.4 While-Anweisung

Möchte man eine Anweisung (einen Block) wiederholt ausführen, so gibt es dafür in Pascal drei verschiedene zusammengesetzte Anweisungen, die jeweils unterschiedliche Kontrollstrukturen bilden. Die Unterschiede bestehen in der Form, in der die Bedingung formuliert wird, unter der die Anweisung wiederholt wird. Zunächst wird die am häufigsten benutzte Wiederholungsanweisung, die While-Anweisung, beschrieben.

Bild 16: Struktur der While-Anweisung

PROGRAM WHILEDEMO (INPUT,OUTPUT);
  VAR VON,BIS,X: INTEGER;
BEGIN
  WRITE('VON BIS :'); READLN(VON,BIS);
  X:= VON;
  WHILE X<=BIS DO
    BEGIN WRITE(X); X:= X+1 END;
END.

Bild 17: Eine einfache While-Schleife

Eine While-Anweisung wird folgendermaßen ausgeführt:

  1. Der boolesche Ausdruck wird ausgewertet. Ist die Bedingung nicht erfüllt (FALSE), so wird die gesamte While-Anweisung beendet.
  2. War die Bedingung erfüllt, das Ergebnis des Ausdruckes also TRUE, so wird die Anweisung nach dem Wortsymbol DO ausgeführt.
  3. Anschließend wird die Programmausführung bei (1) fortgesetzt.

In Bild 17 wird also der Wert der Variablen X solange mit WRITE ausgegeben und um 1 erhöht, bis X größer als die Variable BIS wird. Beispiele für die Ausgaben des Programmes zeigen eine wichtige Eigenschaft der While-Anweisung:

VON BIS: 1   5
1 2 3 4 5
 
VON BIS: 1   2
1 2 
 
VON BIS: 1   1
1 
 
VON BIS: 1   0
Ist also wie bei der letzten Eingabe die Bedingung bereits beim Eintritt in die Schleife nicht erfüllt, wird die Anweisung überhaupt nicht ausgeführt. In diesem Beispiel wurde wieder eine mit BEGIN und END geschachtelte Anweisungsfolge verwendet, um mehr als eine Anweisung nach dem Wortsymbol DO zu wiederholen.

Das nächste Programmbeispiel in Bild 18 berechnet die Anzahl der Stellen einer ganzen Zahl. Die Idee besteht darin, zu zählen, wie oft man die Zahl X nach rechts schieben kann, bis alle Ziffern hinter dem Komma stehen:

PROGRAM STELLEN (INPUT,OUTPUT);
  VAR X,N : INTEGER;
BEGIN
  READLN(X); N:= 0;
  (* N zählt die Divisionen *)
  WHILE X<>0 DO
    BEGIN
      X:= X DIV 10; N:= N+1
    END;
  WRITELN('Anzahl der Stellen:', N);
END.

Bild 18: Dezimalstellen zählen

Wichtig ist dabei die Tatsache, daß die Prüfung des Ausdruckes (X<>0) vor der Ausführung der Anweisungen (X:= X DIV 10; N:= N+1) erfolgt. Deshalb wird für die Eingabe der Zahl X=0 die Schleife überhaupt nicht durchlaufen, weshalb das Programm für diese Eingabe das Ergebnis N=0 liefert. Anzumerken ist noch, daß das Programm auch für negative Zahlen korrekt arbeitet.

Nach der ausführlichen Diskussion im letzten Abschnitt ist Ihnen sicher auch klar, warum im Programm STELLEN nach dem Wortsymbol DO eine Anweisungsfolge (BEGIN ... END) steht. Ist dies nicht der Fall, sollten Sie das Programm probeweise ohne die Klammerung mit BEGIN und END übersetzen und testen. Wenn Sie anschließend die beiden letzten Kapitel noch einmal lesen, werden Sie die Bedeutung der Anweisungsfolge zur Bildung von Anweisungsblöcken erkennen.

PROGRAM NETZ (INPUT,OUTPUT,GRAPHIC);
  CONST N1 = 8;
        N2 = 8;
  VAR P1,P2: INTEGER;
BEGIN
  GRAPHIC(1,1);
  P1:= 1;
  WHILE P1<=N1 DO
   BEGIN
     P2:= 1;
     WHILE P2<=N2 DO
       BEGIN            (* Zeichne eine Linie: *)
         DRAW(1,        (* Farbe               *)
         P1*40, P1*0,   (* Startpunkt          *)
         P2*0, P2*20);  (* Endpunkt            *)
         P2:= P2+1;
       END;
     P1:= P1+1
   END;
  REPEAT UNTIL KEYPRESSED; (* Warte auf Tastatureingabe *)
  GRAPHIC(0);
END.

Bild 19: Geschachtelte While-Anweisungen

In Bild 19 werden zwei geschachtelte WHILE-Anweisungen verwendet, um ein Netz im Grafikmodus zu zeichnen. In Pascal 2.0 muß bei der Verwendung des Grafikmodus der Name GRAPHIC im Programmkopf aufgeführt werden. Nachdem mit der Anweisung GRAPHIC der Grafikbildschirm eingeschaltet wurde, werden N1 Punkte mit N2 Punkten durch je eine Linie verbunden. Dabei zählt die Variable P1 in der äußeren While-Anweisung von 1 bis N1, während die Variable P2 in der inneren While-Anweisung von 1 bis N2 zählt.

Die Prozedur DRAW (s.a. Kapitel 4.4.4.9) verbindet nun jeweils zwei Punkte (P1 und P2) in der Zeichenfarbe (1). Durch die Wahl der Faktoren (20, 0 ,25, 10) werden zwei Geraden auf dem Bildschirm definiert, auf denen jeweils die Start- und Endpunkte der Linien in gleichem Abstand liegen. Im Programm werden die Punkte nun nach folgendem Schema verbunden:

P1 auf
Gerade 1
mit P2 auf
Gerade 2
1
1, 2, 3, 4, 5, 6, 7, 8
2
1, 2, 3, 4, 5, 6, 7, 8
...
...
8
1, 2, 3, 4, 5, 6, 7, 8

Bild 20: Lage der Linienendpunkte

Insgesamt werden also N1 * N2 = 64 Linien gezeichnet. Durch eine Änderung der Faktoren bei der DRAW-Prozedur und die Variation der Punkteanzahlen (N1 und N2) können Sie verschiedene Effekte erzielen. Probieren Sie doch zum Beispiel

N1 = 10; N2 = 10   
DRAW(1,
     P1 * 32, 100,
     160    , P2 *20)

While-Anweisungen nennt man auch pre check loops oder abweisende Schleifen. Durch die Eigenschaft einer While-Anweisung, die Schleife auch keinmal auszuführen, spart man oft notwendige Sonderbehandlungen. Das letze Beispielprogramm dieses Abschnittes berechnet für zwei natürliche Zahlen N und K den Wert E = N hoch K.

PROGRAM HOCH (INPUT, OUTPUT);
  VAR E,N,I,K : INTEGER;
BEGIN
  READLN(N,K);
  E:= 1; I:=K;
  WHILE I>0 DO
   BEGIN E:= E*N; I:= I-1 END;
  WRITELN(N, '^', K, '=', E);
END.

Dieses Programm berücksichtigt auch die Sonderfälle N=0 und K=0 korrekt. Es gilt nämlich:

N hoch 0 = 1   für alle N
0 hoch K = 0   für alle K<>0

Auch für die Repeat-Anweisung, die erst im nächsten Abschnitt vorgestellt wird, gelten die folgenden Regeln, die man bei der Programmierung von Wiederholungsanweisungen beachten sollte:

  1. Bei der Wiederholung muß die Schleife irgendwann beendet werden. Deshalb muß man sich während der Berechnung dem Ziel nähern. Folgendes Programmstück ist also auf jeden Fall sinnlos, da der Wert des Booleschen Ausdruckes (I<>0) innerhalb der Schleife überhaupt nicht verändert wird:

    WHILE I<>0 DO K:= K+1
  2. Während jeder Ausführung der Wiederholung müssen gewisse Bedingungen erhalten bleiben. Diese Bedingungen bezeichnet man auch als Schleifen-Invarianten. Es ist keine schlechte Idee, diese Invarianten durch Kommentare zu verdeutliche.

    E:=1; I:= K;
    WHILE I>0 DO
      (* E = X hoch (K-I) *)
      BEGIN E:= E*N; I:= I-1 END
    

    Am Ende der Schleife ist also I=0, und damit besitzt E den gewünschten Wert.

  3. Grundsätzlich sollte man beim Entwurf einer Wiederholung den Sonderfällen besondere Aufmerksamkeit schenken, um logische Fehler nicht erst im fertigen Programm bei seltenen Eingaben zu finden.

2.8.5 Repeat-Anweisung

Seltener als die While-Anweisung wird die Repeat-Anweisung benutzt. Sie hat die in Bild 21 angegebene Struktur:

Bild 21: Repeat-Anweisung

Der wesentliche Unterschied zur While-Anweisung ist die Tatsache, daß die Anweisungsfolge mindestens einmal ausgeführt wird, da eine Repeat-Anweisung folgendermaßen ausgeführt wird:

  1. Die Anweisungen zwischen den Wortsymbolen REPEAT und UNTIL werden in der angegebenen Reihenfolge ausgeführt.
  2. Anschließend wird die Bedingung nach dem Symbol UNTIL ausgewertet. Ist die Bedingung erfüllt (TRUE), so wird die Ausführung der Repeat-Anweisung beendet. Ist das Ergebnis des booleschen Ausdruckes FALSE, so wird die Ausführung bei (1) fortgesetzt.

Im Gegensatz zur While-Anweisung kann damit der boolesche Ausdruck Variablen enthalten, die erst innerhalb der Anweisungsfolge berechnet werden.

PROGRAM SIMPLEREPEAT(INPUT,OUTPUT);
  VAR CH: CHAR;
BEGIN
  REPEAT
    WRITE('Allles klar? (J,N) ');
    READLN(CH)
  UNTIL (CH='J') OR (CH='N');
  IF CH ='J' THEN
    WRITELN('Na prima!')
  ELSE
    WRITELN('Ist doch gar nicht schwer!');
END.

Eine beliebte Anwendung der Repeat-Anweisung besteht nur aus einer Abbruchbedingung ohne Anweisungen zwischen REPEAT und UNTIL:

REPEAT UNTIL KEYPRESSED;

Die in Pascal 2.0 vordefinierte Funktion KEYPRESSED liefert den Wert TRUE, falls der Benutzer eine Taste betätigt hat. Somit wird die (leere) Repeat-Schleife bis zur Betätigung einer Taste durchlaufen. In Bild 19 wurde diese Schleife zum Beispiel verwendet, um vor dem Löschen des Grafikbildschirms auf einen Tastendruck des Benutzers zu warten.

Im nächsten Beispiel wird die Repeat-Anweisung zum Zeichnen einer Funktion benutzt.

PROGRAM PLOT (INPUT,OUTPUT,GRAPHIC);
  CONST BILDSCHIRMBREITE = 319;
        PIXELSCHRITT     = 3;
  VAR XPIXEL, YPIXEL : INTEGER;
      X, VON, BIS,Y  : REAL;
      FAKTOR         : REAL;
BEGIN
  WRITELN('Intervallgrenzen');
  WRITE('von :'); READLN(VON);
  WRITE('bis :'); READLN(BIS);
  FAKTOR:= (BIS-VON) / BILDSCHIRMBREITE;
  GRAPHIC(1,1); COLOR(1,1);            (* schwarze Farbe *)
 
  XPIXEL:= 0;
  REPEAT
    (* Berechne X-Wert aus XPIXEL: *)
    X:= VON + XPIXEL * FAKTOR;
    Y:= SIN(X) + 2 * COS(3*X);
    YPIXEL:= ROUND( Y*40) + 100;       (* Y Werte skalieren *)
    IF XPIXEL = 0 THEN                 (* 1. Punkt *)
      LOCATE(XPIXEL,YPIXEL)
    ELSE
      DRAW(1,,XPIXEL,YPIXEL);          (* ziehe Linie *)
    XPIXEL:= XPIXEL + PIXELSCHRITT;
  UNTIL XPIXEL>BILDSCHIRMBREITE;
 
  REPEAT UNTIL KEYPRESSED;
  GRAPHIC(0);
END.

Das Programm läßt sich dreiteilen: Zunächst werden die Grenzen des darzustellenden Koordinatenbereichs der Funktion eingegeben. In der nachfolgenden Repeat-Schleife wird die Funktion von links nach rechts in voller Bildschirmbreite ausgegeben. Abschließend wird vor dem Löschen des Bildschirms auf eine Tastatureingabe des Benutzers gewartet. Wählen Sie z.B. folgende Eingabewerte

VON : -10
BIS :  10

wird die Funktion

Y = SIN(X) + 2 * COS(3*X)

im Intervall [-10, 10] dargestellt. Innerhalb der Repeat-Schleife wird mit den Prozeduren LOCATE und DRAW (s. 4.4.4.9) eine zusammenhängende Linie gezogen. Dabei wird in jedem Durchlauf der Schleife ein Bildschirmkoordinatenpaar XPIXEL / YPIXEL berechnet. Mit der bedingten Anweisung IF XPIXEL=0 wird folgende Zeichenstrategie gewählt:

Der 1. Bildschirmpunkt wird mit LOCATE als Anfangspunkt eines Linienzuges definiert. In jedem folgenden Durchlauf wird der neu berechnete Punkt mit dem zuletzt gemalten Punkt verbunden.

Während XPIXEL mit der Schrittweite PIXELSCHRITT von 0 bis BILDSCHIRMBREITE hochgezählt wird, muß YPIXEL gemäß der Funktion in jedem Durchlauf neu berechnet werden. Mit der Zuweisung

X:= VON + XPIXEL * FAKTOR

wird der Bereich der ganzzahligen Bildschirmkoordinaten von 0 bis BILDSCHIRMBREITE auf den Bereich der X-Koordinaten der Funktion (z.B. [-10,10]) abgebildet. Dabei nimmt der Compiler automatisch eine Umwandlung vom Typ INTEGER zum Typ REAL vor. Nachdem so die Koordinate X berechnet wurde, kann diese in die Funktion eingesetzt werden, um die Y-Koordinate Y zu berechnen. Schließlich muß diese reelle Zahl Y wieder auf den Bereich der darstellbaren ganzzahligen Y-Bildschirmkoordinaten (von 0 bis 199) umgeformt werden.

Dies geschieht mit der Rundungsfunktion ROUND:

YPIXEL:= ROUND (40*Y) + 100

Zur Abwechselung können Sie auch die folgende Funktion im Bereich von -20 bis 20 darstellen:

Y:= 2 * SIN(X) / X

2.8.6 For-Anweisung

In BASIC bietet die For-Anweisung die beste Möglichkeit zur Strukturierung von Wiederholungen. In Pascal wird die For-Anweisung nur dann verwendet, wenn die Anzahl der Wiederholungen bereits vor dem Eintritt in die Schleife bekannt ist. Die Struktur der Anweisung ist wieder in einem Bild dargestellt:

Bild 22: Struktur der For-Anweisung

Die Ausführung erfolgt nach dem folgenden Schema. Es sichert, daß der Endwert der Schleife nicht in der Schleife verändert werden kann. Außerdem kann die For-Schleife wie die While-Schleife auch keinmal durchlaufen werden, falls nämlich der Wert von Ausdruck 1 bereits größer als der Wert von Ausdruck 2 ist:

  1. Ausdruck 1 wird ausgewertet und als Startwert der Schleife gespeichert. Anschließend wird das Ergebnis von Ausdruck 2 als Endwert der Schleife gespeichert.
  2. Ist der Schleifenzählerwert größer als der Endwert wird die For-Anweisung beendet. Ansonsten wird er in der Laufvariablen gespeichert.
  3. Die Anweisung nach dem Wortsymbol DO wird ausgeführt.
  4. Der Schleifenzählerwert wird um 1 erhöht und die Ausführung der Schleife bei (2) fortgesetzt.

Das folgende kleine Programm bestimmt die Summe der Kehrwerte der Zahlen von 1 bis 100:

PROGRAM FORLOOP(OUTPUT);
  VAR S: REAL;
      I: INTEGER;
BEGIN
  S:= 0.0;
  FOR I:= 1 TO 100 DO
    S:= S + 1 / I;
  WRITELN(S);
END.

Als Typ der Laufvariablen sind alle skalaren Typen (z.B. INTEGER, CHAR, BOOLEAN, nicht aber REAL) zulässig. Dementsprechend wird in Schritt (4) allgemein der Nachfolger im Wertebereich bestimmt:

PROGRAM FORCHAR (OUTPUT);
  VAR CH: CHAR;
BEGIN
  FOR CH:= ' ' TO 'Z' DO
    WRITELN('Der Code von ', CH,' ist', ORD(CH):4);
END.

Die einzige Möglichkeit zur Änderung der Schrittweite einer FOR- Anweisung besteht darin, abwärts zu zählen:

FOR Variable:= Ausdruck 1 DOWNTO Ausdruck 2 DO
  Anweisung

Die Variable durchläuft also ihren Wertebereich zwischen Ausdruck 1 und Ausdruck 2 rückwärts:

PROGRAM BACKANDFOR(OUTPUT);
  VAR CH: CHAR;
BEGIN
  FOR CH:= 'Z' TO 'A' DO WRITE(CH);
  WRITELN('Schleife 1 beendet');
  FOR CH:= 'Z' DOWNTO 'A' DO WRITE(CH);
  WRITELN;
  WRITELN('Schleife 2 beendet')
END.

Die erste Schleife wird keinmal durchlaufen, da 'Z' größer als 'A' ist, wohingegen in der zweiten Schleife die Buchstaben von 'Z' bis 'A' rückwärts gedruckt werden.

PROGRAM SEHTRA (INPUT,OUTPUT);
(* Berechnung eines bestimmten Integrals nach der *)
(* summierten Sehnentrapezformel:                 *)
(* (Es gibt wesentlich bessere Methoden!)         *)
  VAR SIGMA             : REAL;
      VON, BIS ,X ,F ,H : REAL;
      I,N               : INTEGER;
BEGIN
  WRITE('Integrationsgrenzen:');
  READLN(VON, BIS);
  WRITE('Stützstellen:');
  READLN(N);
  H:= (BIS-VON) / N;
  SIGMA:= 0;
  FOR I:= 0 TO N DO
    BEGIN
      X:= VON + I * H;
      F:= SIN(X);
      IF (I=0) OR (I=N) THEN 
        SIGMA:= SIGMA + F / 2
      ELSE
        SIGMA:= SIGMA + F
    END;
  WRITELN('Näherung:', SIGMA * H);
END.

Bild 23: Numerische Integration

In diesem Beispielprogramm wird das bestimmte Integral der Funktion F = SIN(X) in einem frei wählbaren Intervall mit der einfachen Sehnentrapezregel (s. Mathematik-Schulbücher) angenähert. Dazu berechnet man (N+1) Funktionswerte an äquidistanten Stützstellen, die jeweils den Abstand H voneinander besitzen. Bildet man nun die Summe über diese Funktionswerte, wobei die Werte am Intervallrand (I=0) oder (I=N) nur halb gewichtet werden, so ist das Produkt SIGMA * H eine Näherung für das Integral der Funktion zwischen VON und BIS.

Die Genauigkeit der Näherung hängt unter anderem von der Anzahl der Stützstellen ab. Solange nicht Rundungsfehler das Ergebnis beeinflussen, steigt die Genauigkeit mit dem Quadrat der Anzahl der Stützstellen.

Da als Laufvariable keine reellen Zahlen zulässig sind, ist folgende Schleife nicht in Pascal möglich:

FOR X:= VON TO BIS STEP H DO ...     FALSCH !

Solche Schleifen bieten nämlich eine ideale Grundlage für undurchsichtige Fehler, falls bei der sukzessiven Addition der Schrittweite H Rundungsfehler auftreten. Als abschreckendes Beispiel sollten Sie in BASIC folgendes Programm probieren:

FOR I=-1 TO 1 STEP 0.1: PRINT I: NEXT

Durch Rundungsfehler werden nur 20 (statt 21) Zahlen gedruckt! Die in Programm 23 gewählte Methode benötigt zwar bei jedem Schleifendurchlauf eine zusätzliche Multiplikation, jedoch können sich dort Rundungsfehler nicht kumulieren.

Die Ausgabe einer Multiplikationstabelle ist ein anschauliches Beispiel für geschachtelte For-Schleifen:

PROGRAM MULTIPLIKATION (OUTPUT);
  CONST N=13;
  VAR I,J: INTEGER;
BEGIN
  FOR I:= 1 TO N DO
    BEGIN
      FOR J:= 1 TO N DO
        WRITE(I * J : 3);
      WRITELN;
    END;
END.

Dabei durchläuft die Variable J in der inneren Schleife die Werte 1 bis 13, während die Variable I in der äußeren Schleife die momentan gedruckte Zeile zählt. In jeder Zeile werden die Produkte I*J gedruckt.

2.8.7 Sprunganweisung

In diesem Abschnitt werden enzyklopädisch alle Regeln zusammengestellt, die die Sprunganweisung betreffen. Deshalb werden einige Begriffe auftreten, die erst in späteren Abschnitten erklärt werden.

Sprunganweisungen sollten nur zur Behandlung selten auftretender Ausnahmefälle in einem Programm benutzt werden. Außerdem ist es sinnvoll, bei einer Sprunganweisung Kommentare einzufügen, die erläutern, wohin und warum gesprungen wird.

Eine Sprunganweisung hat die folgende Syntax:

GOTO Label

Die Programmausführung wird beim Erreichen der Sprunganweisung an der Anweisung fortgesetzt, die durch das Label markiert wird. Ein Label ist eine positive ganze Zahl. Jede Anweisung kann durch ein Label markiert werden:

Label: Anweisung

Alle Labels müssen außerdem in dem Block, in dem sich die markierte Anweisung befindet, im Labeldeklarationsteil aufgeführt werden. Im report wird definiert, daß der Labeldeklaratonsteil die erste Deklaration eines Blockes bilden muß. In Pascal 2.0 ist wie bereits erwähnt die Reihenfolge der Deklarationsteile frei wählbar. Eine Labeldeklaration hat folgende Syntax:

LABEL Label, Label, ... , Label;

Sinnvolle Beispiele für Sprünge findet man nur in komplexen Programmen, bei denen eine Ausnahmebehandlung erforderlich wird. In kleinen Programmen läßt sich die Sprunganweisung ohne Mehraufwand problemlos vermeiden. Daher ist das folgende Programmstück nur als ein künstliches Beispiel zu betrachten (BASIC läßt grüßen):

PROGRAM SPRUNG(OUTPUT);
  LABEL 1,7,8; 
  VAR X: INTEGER;
BEGIN
  WRITELN('Punkt 1');
  GOTO 7;
  1: IF X=0 THEN GOTO 8;
  WRITELN('Punkt 2', X);
  X:= X-1; GOTO 1;
  7: X:=5; GOTO 1;
  8: WRITELN('Punkt 3');
END.

Das Programm erzeugt folgende Ausgabe:

Punkt 1
Punkt 2 5
Punkt 2 4
Punkt 2 3
Punkt 2 2
Punkt 2 1
Punkt 3

Bei Sprüngen muß die durch Prozeduren, Funktionen und zusammengesetzte Anweisungen gebildete Blockstruktur eines Pascal- Programmes beachtet werden:

  1. Es ist nicht erlaubt, von außen in eine Prozedur (Funktion) zu springen.
  2. Es ist nicht erlaubt, von außen in eine For-, With- oder Case-Anweisung zu springen.

Andererseits ist es erlaubt, aus einer geschachtelten Prozedur zu einer Marke in einem umfassenden Block zu springen. Beispiele für diese Regeln bei blockübergreifenden Sprüngen finden Sie in Abschnitt 4.4.2 unter dem Stichwort »Sprunganweisung«.

Aufgaben

1. Schreiben Sie ein Programm zur Umwandlung arabischer Zahlen in römische Zahlen. Vielleicht haben Sie auch eine Idee, wie man die Umwandlung in umgekehrter Richtung realisieren kann.

2. Schreiben Sie ein Programm, das Zahlenfolgen einliest und bei der Eingabe der Zahl 999 die Summe über die Folge (natürlich ohne 999) druckt. Welche Wiederholungsanweisung ist hier angebracht?

3. Erweitern Sie das Programm 2, so daß die größte und kleinste Zahl der eingelesenen Zahlen bestimmt wird:

1 3 44 33 -20 12 999
 
SUMME:    73
MAXIMUM:  44
MINIMUM: -20

4. Erweitern Sie das Programm aus Abschnitt 2.8.5, indem Sie vor dem Zeichen der Funktion zunächst den Bereich der auftretenden Y-Werte bestimmen. Nachdem der maximale und minimale Y-Wert bekannt sind, können Sie die Y-Koordinaten wie die X-Koordinaten skalieren, um die Funktion auch in Y-Richtung immer bildschirmfüllend darzustellen.

5. Erstellen Sie ein Programm, das die Nullstellen einer Funktion F nach dem Intervallschachtelungsverfahren bestimmt: Der Benuter gibt als Startwerte die Intervallgrenzen L und R an, zwischen denen eine Nullstelle liegt. Dabei soll gelten:

F(L) * F(R) <= 0

d.h. zwischen L und R liegt ein Vorzeichenwechsel. Die Nullstelle wird durch sukzessive Intervallhalbierung gefunden. In Abhängigkeit vom Vorzeichen des Funktionswertes in der Intervallmitte M=(L+R)/2 wird M als rechte oder linke Intervallgrenze des folgenden Schleifendurchlaufs benutzt. Die Approximation beende man, falls die Intervallgröße kleiner als eine vom Benutzer vorgegebene Genauigkeit ist. Prüfen Sie das Programm mit der Funktion

F:= 2 * SIN(X) - COS (2 * X)

im Intervall L=0 und R=1!

6. Schreiben Sie ein Programm, das alle Primzahlen in einem vom Benutzer vorgegebenen Intervall druckt. (Eine Zahl X heißt prim, wenn sie nur durch 1 und sich selbst geteilt werden kann. 1 ist keine Primzahl). Die Geradeaus-Methode zur Programmierung besteht darin, den Divisionsrest (Operation MOD!) bei der Division der Zahl X durch alle kleineren Zahlen Y zu untersuchen. Um die Laufzeit des Programmes nicht sinnlos anwachsen zu lassen, sollten Sie sich vor der Programmierung überlegen, welche Zahlen von Anfang an als Primzahlen ausscheiden und bis zu welcher Zahl Y die Teilbarkeit geprüft werden muß.

7. Schreiben Sie ein Programm, das eine Wahrheitstabelle in der folgenden Form druckt:

  A     |   B     | A AND B
--------+---------+----------
 FALSE  |  FALSE  | FALSE
 FALSE  |  TRUE   | FALSE
 TRUE   |  FALSE  | FALSE
 TRUE   |  TRUE   | TRUE
Geben Sie sich ruhig etwas Mühe bei der Formatierung. Benutzen Sie (String-)Konstanten! Besonders schön wäre es, wenn Sie zwei geschachtelte Schleifen mit booleschen Variablen A und B verwenden würden:

FOR A:= FALSE TO TRUE DO
  ...
  FOR B:= FALSE TO TRUE DO
    ...
  ...

Prüfen Sie mit dem Programm die Ergebnisse von A<B, A>B, A<=B und A>=B statt A AND B!

8. Überlegen Sie sich, wie man die Operation I MOD 7 verwenden kann, um die Ausgabe von Ergebnissen so zu steuern, daß jeweils sieben Werte in einer Zeile erscheinen:

 2  4  6  8 10 12 14
16 18 20 22 24 26 28
30 32 34 36 38 40 42
...

9. Besonders schöne Bildschirmgrafiken erhält man durch die Darstellung mathematischer Kurven, die als Zykloiden bezeich- net werden. Sie entstehen mechanisch als Bahn eines Punktes P, der mit einem Kreis vom Radius R im Abstand A vom Mittelpunkt M des Kreises fest verbunden ist, wenn dieser Kreis um einen anderen Kreis mit dem Radius R1 rollt. Ein Spielzeug zum Zeichnen dieser Bilder heißt Spirograph.

Bild 24: Parameter einer Zykloide

Natürlich lassen sich die Linien auch punktweise mathematisch berechnen: Dreht sich der Kreis um einen Winkel PHI, so befindet sich der Punkt an folgenden relativen Koordinaten zum Mittelpunkt des feststehenden Kreises M1:

X = (R + R1) * COS(PHI) - A * COS((R + R1) * PHI / R)
Y = (R + R1) * SIN(PHI) - A * SIN((R + R1) * PHI / R)

Programmieren Sie diese Kurven! Für die Eingabe von R, R1, A und einer Schrittweite DELTAPHI wird eine Folge von X/Y-Koordinatenpaaren berechnet, die wie in Abschnitt 2.8.5 beim Zeichnen der Funktion mit LOCATE und DRAW zu einer zusammenhängenden Kurve verbunden werden.

Da es ein nichttriviales Problem ist, aus dem rationalen Verhältnis von R und R1 den Winkel ENDPHI zu bestimmen, bei dem sich die Koordinaten zyklisch wiederholen, und die Kurve sich schließt, sollten Sie die Berechnung einfach bei einer Tastenbetätigung des Betrachters beenden.

Beispielparameter:
R        = 40    20
R1       = 35    50
A        = 75    75
DELTAPHI = 0.2   1

10. Etwas aufwendig ist die Beschriftung von Grafiken: Erweitern Sie das Programm zum Zeichenen einer Funktion, indem Sie z.B. die X-Achse im Bild einzeichnen und in einem festen Abstand mit den X-Werten beschriften. Am schwierigsten ist dabei die Ausrichtung der Grafik am Text, da Text im Grafikmodus nur in 8-Pixel-Schritten ausgegeben werden kann.

Um z.B. die Zahlen von 0 bis 10 jeweils 16 Pixel in Y-Richtung auseinanderstehend zu drucken kann man folgendes Programm verwenden:

PROGRAM GRAPHICTEXT(INPUT,OUTPUT,GRAPHIC);
  VAR I: INTEGER;
BEGIN
  GRAPHIC(1,1);
  FOR I:= 0 TO 10 DO
    DISPLAY(1,5,24-2*I, STR(I:5:1));
  REPEAT UNTIL KEYPRESSED;
  GRAPHIC(0);
END.

Inhaltsverzeichnis