Einführung in die Programmiersprache Pascal Teil 3

Nachdem im letzten Teil die FORNEXT-Schleife behandelt wurde, folgen nun zwei weitere Steuerbefehle. Für diese Schleifenbefehle ist charakteristisch, daß die Anzahl der Durchläufe nicht festgelegt ist, sondern von einer Endbedingung abhängt.

1. REPEAT-Anweisung
Die Anweisung hat die Form:

   REPEAT
       Anweisung(en)
   UNTIL Bedingung

Dabei wird der Teil mit der Anweisung bzw. den Anweisungen so lange durchlaufen, bis die (End-)Bedingung erfüllt ist.
Der Anweisungsteil muß nicht mit BEGIN...END umschlossen sein, weil die äußere Form die Anweisungen klar umschließt.

Dadurch, daß bei der REPEAT-Schleife die Abbruchbedingung am Ende steht, wird die Schleife mindestens einmal durchlaufen. Erst dann wird geprüft, ob die Schleifenbedingung noch zutrifft. Diese Art der Schleifensteuerung nennt man deshalb auch nichtabweisende Schleife. Ihr Struktogramm ist von dem der abweisenden Schleife verschieden (siehe Bild 1).

Diese Eigenheit der REPEAT-Anweisung ist nicht immer erwünscht und muß deshalb besonders beachtet werden.
Das Programm 'Multiplikation' (Listing 1) zeigt eine Anwendung der REPEAT-Schleife. Die Schleife wird so oft durchlaufen, bis die Bedingung a> 1000 erfüllt ist. Danach wird der Endwert der Variablen a und die Anzahl der Schleifendurchläufe (nr) ausgegeben.

program MULTIPLIKATION;
        (* mit Repeat/Until *) 
var a,nr : integer;

begin
  a:=2;
  nr:=1;
  repeat 
     a :=a*2; 
     nr:=nr+1; 
     writeln (a); 
  until a>1000: 
  writeln ('2 ^ ',nr, ' = ',a) 
end.

Das Programm 'Zahl Raten' (Listing 2) ist ein kleines Ratespiel. Dabei wird zuerst vom Programm eine 'Zufallszahl' erzeugt. Dies geschieht mit der Funktion RANDOM bzw. RANDOMI). RANDOM generierte eine Zufallszahl zwischen Null und Eins (ausschließlich!), RANDOM (X) hingegen eine Zahl zwischen Null und X (ausschließlich!).

Mit RANDOM (100) wird also eine Zahl im Bereich von 0 bis 99 erzeugt. Das Programm beinhaltet eine REPEAT-Schleife, die solange durchlaufen wird, bis die eingegebene Zahl (zahl) der Zufallszahl (a) entspricht. Dann wird die Anzahl der benötigten Züge ausgegeben.

program ZAHL_RATEN; 
var a,nr,zahl : integer; 
begin
  writeln ('******* ZAHLENRATEN ********'); 
  writeln ('(Zahlenbereich von 0 bis 99)'); 
  a :=random(100); 
  nr:=0;
  
  repeat 
    write ('Deine Zahl : ');
    read (zahl);
    nr:=nr+1; 
    if zahl>a then writeln (' ... zu gross'); 
    if zahl<a then writeln (' ... zu klein'); 
  until a=zahl;
  
  writeln; 
  writeln ('gratuliere, die Zahl ist gefunden !'); 
  writeln ('--> benoetigte Zuege : ',nr); 
end.

Bei diesem Programm wird am Anfang nr=0 gesetzt. Dies ist bei Pascal, im Gegensatz zu den meisten BasicVersionen, notwendig, weil die Variablen beim Programmstart nicht automatisch auf Null gesetzt werden. Da einige Pascal-Versionen die Funktion RANDOMI) nicht implementiert haben, muß man sie simulieren. Dazu gibt es viele Möglichkeiten. Das Programm 'Zufallszahl' (Listing 3) erzeugt eine Zufallszahl.

program ZUFALLSZAHL;
(* falls RANDOM nicht vorhanden *)
(* Zahlenbereich von 0 bis 99  *)

var       a : integer;
    eingabe : real;

begin 
  readln (eingabe); 
  a:=trunc(abs(99*sin(eingabe))); 
  writeln (a);
end; 

Dabei werden die Funktionen ABS(x) und TRUNC(x) verwendet. Die Funktion ABS gibt den Absolutwert des Arguments (x) aus.

   ABS (-4)    = 4
   ABS (-9.12) = 9.12
   ABS (4)     = 4

Die Funktion TRUNC gibt den Ganzzahlenanteil des Arguments (x) aus, sie 'schneidet' also die Nachkommastellen ab. Sie ist somit dem Befehl ROUND ähnlich, doch wird bei dieser Funktion gerundet.

TRUNC (10.6) = 10 ROUND (10.6) = 11
TRUNC (-5.5) = -5 ROUND (-5.5) = -5
TRUNC (-5.9) = -5 ROUND (-5.9) = -6

Das Programm errechnet nach Eingabe einer Zahl deren Sinuswert. Da dieser im Bereich Null bis Eins liegen kann, wird der Wert mit 99 multipliziert (obere Bereichsgrenze). Dann wird mit ABS ein eventuell auftretendes Minuszeichen beseitigt und mit TRUNC die Nachkommastellen abgeschnitten. Damit kann also problemlos die Zeile mit der RANDOM-Funktion ersetzt werden wenn man vorher noch die Variable 'eingabe' einliest (natürlich kann man die Erzeugung einer Zufallszahl auch mit einer FUNCTION bzw. einer PROCEDURE realisieren, doch dazu später mehr!).

2. WHILE-Schleife
Diese Schleifenfunktion hat die Form:

     WHILE Ausdruck DO
             Anweisung(en)

Falls mehrere Anweisungen innerhalb des Schleifenrumpfes stehen sollen, so müssen diese mit BEGIN...END umschlossen werden. Da bei der WHILESchleife die Bedingung schon am Anfang steht, wird sie, falls die Bedingung schon beim ersten Durchlauf nicht erfüllt ist, auch nicht durchlaufen. Sie ist deshalb, wie auch die FOR-TO-DOAnweisung, eine abweisende Schleife.

Das Programm 'RHOMBUS' (Listing 4) enthält eine WHILE-Schleife und darin verschachtelt noch zwei aufeinanderfolgende Schleifen des gleichen Typs. In jeder dieser Schleifen sind wiederum je zwei FOR-Schleifen enthalten. Das Struktogramm zeigt deutlich diese Anordnung.

Wenn Sie das Programm gestartet haben, entsteht auf dem Bildschirm ein Rhombus. Statt '*' können Sie auch den ASCII-Code dieses Zeichens mit dem Befehl CHR(x) eingeben. Der Wert für x müßte dann 42 lauten.

     CHR(65) = A 
     CHR(66) = B usw.


program RHOMBUS;
        (* mit Hilfe der While-Schleife*)
var a,b,breite : integer;
       eingabe : char; 

begin

   while eingabe<>'n' do begin

      writeln ('wie gross soll der Rhombus sein ?');
      writeln (' ( maximal 39 ) '):
      readln (breite);
      a:=03 
	  while a<breite do begin
         a:=a+1;
         for b:=1 to 40-a do write (' ');
         for b:=1 to 2*a do write ('*');
         writeln 
      end; 
      while a>0 do begin  
         a:=a-1;
         for b:=1 to 40-a do write (' ');
         for b:=1 to 2*a do write ('*');
         writeln 
      end;
      writeln ('noch einmal (j/n) ?');
      readln (eingabe)
   end 

end.

Mit dem Programm PRIMFAKTORZERLEGUNG (Listing 5) kann eine Zahl in ihre Primfaktoren zerlegt werden. Die Bedingung für die äußere WHILE-Schleife heißt: antwort< >'n'. Das Programm läuft also, bis für 'antwort' ein n eingegeben wird. Die nächste Schleife wird ausgeführt, wenn a > 1 ist. Dies bedeutet, daß bei Eingabe einer Zahl, die kleiner als 2(!) ist, keine Reaktion des Programms erfolgt, weil dann die Schleife nicht durchlaufen wird. Die dritte Schleife enthält die Funktion MOD (Modulo). Sie hat die Form:

     x MOD y

Ihr Ergebnis ist der Rest, der bei der Rechenoperation a/b entsteht und ist vom Typ Integer. Dazu einige Beispiele:

   13 MOD 2 = 1
    9 MOD 3 = 0 
   17 MOD 9 = 8

Mit der innersten Schleife wird in unserem Beispiel der Faktor ermittelt, durch den die Variable a teilbar ist. Die Faktoren sind dabei immer Primzahlen. Die Schleifenvariable a wird nun durch den gefundenen Faktor geteilt. Wenn a=b war, dann ist a nun Eins und damit die Primfaktorzerlegung beendet. Um a durch b zu teilen, wurde die DIV-Funktion verwendet. Dies ist hier natürlich nicht notwendig, denn diese Funktion schneidet nach dem Teilen einen eventuell auftretenden Nachkommateil ab. Ein Nachkommateil kann jedoch bei unserem Programm nicht vorkommen, weil b immer ein Teiler von a ist (siehe MOD). Man kann also in diesem Fall statt a div b auch a/b einsetzen.

program PRIMFAKTORZERLEGUNG;
var a,b,zahl : integer; 
     antwort : char; 

begin 

   while antwort<>'n' do begin

      writeln ('********* PRIMFAKTORZERLEGUNG ********'); 
      writeln ('bitte eine natuerliche Zahl eingeben !'); 
      writeln;
      read (zahl);
      write (' = ');

      a:=zahl; 
      while a>1 do begin 
         b:=2; 
         while a mod b <> 0 do
            b:=b+1; 
         if a=b then writeln (b,' <--- primzahl(en)')
            else write (b,' * '); 
         a:=a div b 
      end;

      writeln;
      writeln ('---> Weiter mit < RETURN > 1 (n=ENDE)')
      readln (antwort)
   end;
end.

Neben den drei in Standard-Pascal vorhandenen Kontrollstrukturen zur Schleifensteuerung gibt es in manchen Pascal-Versionen (z. B. ST-Pascal von ATARI) noch die LOOP-Anweisung. Sie hat die Form:

   LOOP
     Anweisung(en)
   EXIT IF Ausdruck ;
     Anweisung(en)
   END

Die Bedingung für den Abbruch (EXIT IF) steht dabei an einer beliebigen Stelle innerhalb der Anweisung der Schleife. Sie kann aber auch am Anfang oder am Ende des Anweisungsblocks stehen, je nachdem, wo die Abbruchbedingung abgefragt werden soll (!).

Das folgende Beispiel zeigt den Vorteil der LOOP-Anweisung gegenüber der WHILE-Anweisung. Bei der letzteren muß die Abbruchbedingung zweimal abgefragt werden.

LOOP 
   writeln ('a/b='); 
   readln (a,b) 
EXIT IF b = 0; 
   x: = a/b; 
   writeln ('a/b=',x) 
END

LOOP-Anweisung

WHILE b < > 0 do begin 
   writeln ('a/b='); 
   readln (a,b); 
   if b < > 0 then begin 
      x:=a/b; 
      writeln ('a/b=',x) 
   end;
end

WHILE-Anweisung

program HORNER; {Berechnung von Funktionswert und Ableitung } {an der Stelle x} var a : array [0..20] of integer: c : array [0..20] of real; n,k,i,x,f : integer; begin writeln ('HORNER-SCHEMA') writeln ('Funktionswert und Ableitung an der Stelle x'); writeln ('Funktionsgrad und x eingeben'); readln (n,x); for k:=n downto 0 do begin {Werte einlesen} write ('a,[',k,']= '); readln (a(k]); c[k] := a[k] end; for i:=1 to n do {HORNER-Algorithmus} for k:=n-1 downto i-1 do c[k] := c[k+1]x+c[k]; writeln; write ('f(x) = '); for k:=n downto 0 do begin {Funktion ausgeben} if a[k]<>0 then begin if (a[k]>0) and (k<>n) then write('+'); if k=0 then write (a[0]) else if k=1 then write (a[1],'x') else write (a[k],'x^',k); write (' ') end end; writeln; for i:=0 to n do begin {Funktion & Ableitung} if i=0 then f:=l else f:=fi: c[i]:=c[i]*f; writeln ('f',i,'(',x,') -',c[i]:8:2) end end.

Das letzte Programm (Listing 6) behandelt ein Problem aus der Mathematik. Es handelt sich um die Berechnung des Funktionswerts und der Ableitung an einem bestimmten Punkt x. Dazu wird das - sicherlich bekannte HORNER-Schema verwendet

Wie auch schon bei den letzten Programmen sind hier Kommentarzeilen enthalten. Der Text kann an einer beliebigen Stelle im Text stehen. Er wird entweder mit (* ... *) oder mit {...} umschlossen und benötigt kein Semikolon am Ende.

Die Faktoren werden in ein Feld (ARRAY) eingelesen. Dieses Feld muß bei der Variablenvereinbarung definiert werden. Die Form der Vereinbarung ist:

ARRAY Indexbereich OF Elementtyp

Beispiel:
a: array [0..20] of integer

Damit wird für die Variable a ein Feld von 21 Elementen vom Typ INTEGER bereitgestellt. Der Datentyp ARRAY wird später noch ausführlich besprochen.

Im ersten Teil des Programms werden die Werte eingelesen. Die Werte werden dabei gleich in ein zweites Feld c[] kopiert, um sie für die Funktionsausgabe zu erhalten. Der zweite Teil berechnet die Werte nach dem HORNER-Algorithmus. Die Endwerte stehen dann im Feld c[].

Im anschließenden Teil wird die Funktion in einer übersichtlichen Form ausgegeben (siehe Bild2). Dabei werden die Nullterme gestrichen, und bei Bedarf wird ein Additionszeichen eingesetzt.

Der letzte Teil gibt die Werte der Ableitungen an der Stelle x aus. Dazu müssen die im Feld c[] befindlichen Werte noch mit der entsprechenden Fakultät multipliziert werden. Die Ausgabe der Werte erfolgt formatiert.
Hinweis: Sie sollten unbedingt alle Beispiele dieses Kurses eingeben und dann 'damit experimentieren. Probieren Sie alle Werte aus, die Ihnen einfallen, und suchen Sie Schwächen des Programms. Außerdem können Sie das Programm nach Ihren Wünschen ändern und erweitern. Wenn Sie Kritik oder Anregungen zu diesem Kurs haben, dann schreiben Sie mir.

Im nächsten Teil geht es weiter mit Prozeduren und Funktionen. Diese Strukturen unterstützen die übersichtliche Gestaltung von Programmen. Sie ermöglichen außerdem das Programmieren von Modulen und somit eine schrittweise Verfeinerung des zu lösenden Problems.



Aus: ST-Computer 04 / 1986, Seite 33

Links

Copyright-Bestimmungen: siehe Über diese Seite