• Keine Ergebnisse gefunden

Eigene Datentypen definieren

Im Dokument Einführung in PASCAL (Seite 31-36)

Eine andere Methode, neue Typen zu definieren, besteht darin, daß man alle Werte aufzählt, die dieser Typ annimmt:

TYPE AMPEL = (ROT, GELB, GRUEN);

FAMILIENSTAND = (LEDIG, VERHEIRATET, GETRENNT, GESCHIEDEN, VERWITWET);

FIGUR = (BAUER,

LAEUFER, SPRINGER, TURM, DAME, KOENIG);

FARBE = (SCHWARZ, WEISS);

Diese Typen nennt man Aufzählungs­

typen. Formal gesehen sind zum Bei­

spiel ROT und KOENIG Konstanten des

jeweiligen Typs. Durch die Reihenfolge bei der Typendeklaration wird eine Ord­

nung auf den Konstanten definiert:

ORD(ROT) = 0 ORD(GELB) = 1 ORD(GRUEN) = 2

Somit sind auch Vergleiche zwischen Variablen eines Aufzählungstyps sinn­

voll:

VAR HAUPTAMPEL : AMPEL;

IF HAUPTAMPEL <£ GELB THEN . . . Um den Nachfolger und Vorgänger im Wertebereich zu erhalten, gibt es die Funktionen PRED (predecessor) und SUCC (successor):

SUCC(ROT) = GELB

SUCC(LAEUFER) = SPRINGER PRED( VERHEIRATET) = LEDIG PRED(WEISS) = SCHWARZ

ORD, SUCC und PRED sind übrigens für jeden skalaren Typ zulässig, da alle skalaren Typen geordnet sind:

0RD(FALSE)=0 SUCC( FALSE) =TRUE SUCC('A') = 'B ' PRED(O) = -1

Viele hoffnungsvolle Programme von Anfängern enthalten direkte Ein- und Ausgabeanweisungen für Werte von Aufzählungstypen:

WRITE (HAUPTAMPEL);

READ (HAUPTAMPEL);

1 2 3 4 5 6 7 8 ! 1 2 3 4 5 6 7 8

1 2 3 4 5 6 7 8 9 ! 1 0 1 2 3 4 5 6 7 2 3 4 5 6 ? 8 9 10! 2 -1 0 1 2 3 4 5 6 3 4 5 6 7 8 9 1 0 1 1! 3 -2 -1 0 1 2 3 4 5 4 5 6 7 8 9 1 0 1 1 1 2! 4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3! 5 -4 -3 -2 -1 0 1 2 3 6 7 8 9 1 0 1 1 1 2 1 3 1 4! 6 -5 -4 -3 -2 -1 0 1 2 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5! 7 -6 -5 -4 -3 -2 -1 0 1 8 9 1 0 1 1 1 2 1 3 1 4 1 5 16! 8 -7 -6 -5 -4 -3 -2 -1 0

Bild 6. Berechnung der Diagonalen im Programm ACHT DAMEN (links: Addition der Zeilen- und Spaltennummern, rechts entsprechend Subtraktion).

am n r,r,yr<

IQ M R J T E l

4 2

PROGRAM ACHT_DAMEN (INPUT,OUTPUT);

CONST N - 8; (* ACHT DAMEN AUF EINEM 0*8 SCHACHBRETT *) N2 »16; ( * * 2 * N *)

"AR DAME : ARRAY I 1 . . N] OF INTEGER; SPALTE.FREI: ARRAY 11 . . N) OF BOOLEAN; DIAG1.PREI : ARRAY I 2. . N2J OF BOOLEAN; DIAG2.FREI : ARRAY l-N. N1 OF BOOLEAN; LOESUNG : INTEGER;

I : INTEGER; PROCEDURE DRUCKELOESUNG;

(* ZEIGE DIE POSITION DER DAMEN AN, ERHÖHE DEN ZÄHLER FÜR DIE LÖSUNGEN *) VAR ZEILE, SPALTE: INTEGER;

BEGIN

LOESUNG:- LOESUNG + 1;

WRITELN; HRITELN; WRITELN( 1 LÖSUNG* , LOESUNG: 2, • : * ) ; FOR ZEILE: »1 TO N DO

BEGIN

FOR SPALTE: »1 TO N DO

IF SPALTE » DAME!ZEILE] THEN HRITE( ' *' ) ELSE WRITE(* •);

WRITELN; END;

END; (* DRUCKELOESUNG *>

PROCEDURE SETZE_ZEILE(I: INTEGER);

(* SUCHE FREIE POSITION FÜR DAME IN ZEILE I. FALLS EIN PLATZ GEFUNDEN *) (* WURDE, WIRD EINE DAME IN ZEILE 1+1 GESETZT ODER DIE VOLLSTAENDIGE *>

<* STELLUNG ANGEZEIGT. SONST ERFOLGT EIN RUECKSPRUNG. *) VAR J: INTEGER;

BEGIN

FOR J: = 1 TO N DO

IF SPALTE.FREII J] AND DIAG1_FREI( I+J] AND DIAG2.FREI ( J-I) THEN BEGIN (* HIER KANN JETZT DIE DAME GESETZT WERDEN: *)

DAMEl I) : - J;

SPALTE_FREI l J) : - FALSE; DIAG1_FREI CI+J1:* FALSE; DIAG2.FREI [J-I):= FALSE;

IF I -N THEN (* ALLE DAMEN GESETZT, LÖSUNG DRUCKEN! *) DRUCKELOESUNG

ELSE <* IN DER NÄCHSTEN ZEILE WEITERSUCHEN *) SETZ E _Z EILE(I+1);

(* JETZT DEN LETZEN ZUG RÜCKGÄNGIG MACHEN: M SPALTE_FREI [ J] : - TRUE;

DIAG1_FREI I I+J): * TRUE; DIAG2 _F REI IJ-Il:« TRUE; END;

END; ( * SETZ E_Z EI LE *) BEGIN

(* SPIELBRETT IST NOCH LEER: *)

POR I * 1 TO8 DOSPALTE.FREI ( I) - TRUE; FOR I = 2 TON2 DODIAG1_PREI ( I) - TRUE; FORI * - NTON DODIAG2 _FREI ( I) - TRUE; LOESUNG:- 0;

SETZ E _Z EILE( 1);

END.

Listing 13. Das Acht-Damen-Problem, ein Beispiel für einen rekursiven Algorithmus.

1 2 3 4 5

Mo 6

nat

7 8 9 1 0 1 1 1 2 1 980 1 .1 2. 1 3. 4 5. 5 6. 6 0. 4 3. 1 0. 0 8. 2 9. 9 0. 0 3. 2 1 981 1 . 2 2. 3 3. 4 4 9 6. 2 1 . 4 3. 2 0. 1 7. 9 9. 5 0. 2 3. 3 1 982 1 . 1 1 . 9 3. 2 4. 5 6. 3 1 . 7 3. 4 0. 2 8. 0 9. 5 0. 0 3. 1 1 983 1 . 4 2. 2 3. 3 4. 3 6. 6 2. 3 3. 5 0. 3 8. 1 9. 5 0. 2 3. 0 1 985 1 . 0 2. 3 3. 4 4. 1 6. 7 2. 4 3. 6 0. 4 8. 3 9. 3 0. 0 3. 5

Bild 7. Darstellung von Jahresumsätzen als Beispiel Diese Anweisungen sind falsch! Nur

während der Übersetzung sind dem Compiler die Namen der Werte des Typs bekannt. Zum Zeitpunkt der Aus­

führung sind alle Aufzählungstypen durch Zahlen ohne Verweise auf irgend­

welche Namen codiert. Man muß also die Umwandlung zwischen dem Auf­

zählungstyp und dem auszugebenden Namen selbst vornehmen:

PROCEDURE DRUCKE_AMPEL(A:AMPEL);

BEGIN

WRITE('Die Ampel z e i g t ) ; CASE A OF

ROT : WRITELN( ' r o t ' ) ; GELB : W RITELN ('gelb');

GRUEN: WRITELN(' g r ü n ') ; END;

END; (* DRUCKE_AMPEL *)

Natürlich können auch Auschnittsty- pen von Aufzählungstypen gebildet werden:

TYPE ENDSPIELFIGUR = LAEUFER..KOENIG;

Mit den Aufzählungstypen lernen Sie den letzten skalaren Typen in Pascal kennen. Alle weiteren Typen, die den Rest des Artikels einnehmen, sind zusammengesetzte Typen wie das Array. Mengen von Zahlen sind Ihnen sicher bekannt. Um einen Mengentyp zu deklarieren, verwendet man die Wortsymbole SET und OF, denen ein skalarer Typ folgen muß:

TYPE FIGUREN = SET OF FIGUR;

VAR MEINE, DEINE: FIGUREN;

Mit den Mengen-Variablen MEINE und DEINE kann man beispielsweise über die geschlagenen Figuren führen.

Am Spielbeginn gilt:

MEINE:= [BAUER...KOENIG];

DEINE:= MEINE;

IF [TURM,DAME,KOENIG]<

=MEINE THEN...

Mit dieser Abfrage wird also getestet, ob ein Spieler noch Turm, Dame und König besitzt. Da eine Menge jedes Ele­

ment nur einmal oder keinmal enthält, werden Mengen überall dort verwen­

det, wo das Vorhandensein einer gewissen Eigenschaft signalisiert wer­

den soll.

Arrays und Mengen fassen mehrere Werte eines Typs zu einem zusammen- gesetzen Typ zusammen. Besonders in großen Programmen ist es jedoch auch sinnvoll, Werte verschiedener Typen zu einer Einheit zu verbinden. Zur Kon­

struktion solcher Typen verwendet man in Pascal Recordtypen (Verbundtypen):

TYPE POSITION = RECORD X ,Y : REAL;

END;

ADRESSE = RECORD

NAME, VORNAME: STRING;

ORT, STRASSE : STRING;

HAUSNUMMER : INTEGER;

PLZ : INTEGER;

END;

VAR P1,P2 : POSITION;

ADR : ADRESSE;

Nach einer solchen Deklaration bezeichnet man P1, P2 und ADR als Records. Ein Record besitzt einzelne Felder, auf die man durch Angabe ihres Namens nach einem Punkt zugreift:

P 1 .X := 3 0 ;

P 1 .Y := 4 0 ;

ADR.ORT := 'MONOPOLY';

ADR. STRASSE:= ' S c h lo ß a lle e ' ; ADR. HAUSNR := 4 ;

Andererseits kann man aber auch den Record als Ganzes ansprechen:

P l := P2

Durch diese Zuweisung werden alle

PROGRAM UMSAETZE (INPUT, OUTPUT);

Listing 14. Bearbeitung zweidimensionaler Tabellen

BEGIN

Felder im Record übertragen. Wichtig und charakteristisch für das Typkon­

zept in Pascal ist die Tatsache, daß zusammengesetzte Typen auch mehr­

stufig aufzubauen sind:

VAR POSITIONEN: ARRAY [ 1 . . . 9 9 ] OF POSITION;

Den umgekehrten Fall, daß ein Record aus Arrays besteht, finden Sie bereits im Beispiel des Typs ADRESSE.

Dort sind die Felder NAME und VOR­

NAME vom Typ STRING, den wir ja als TYPE STRING = ARRAY [ 1 .. 1 1 ]

OF CHAR;

vereinbart hatten. Sollen viele Operatio­

nen mit den Feldern eines Records durchgeführt werden, so ist die stän­

dige Wiederholung des Variablenna­

mens lästig. Für diesen Fall existiert die WITH-Anweisung:

WITH R ecordvariable DO Anweisung So kann man folgende Zuweisungen ADR. NAME : = ' Hugendubel' ; ADR. VORNAME: = ' Kunigunde' ; ADR.ORT : = '7 B e rg e ';

ADR. STRASSE: = 17 Zw erge';

schreiben als:

WITH ADR DO BEGIN

NAME := ’Hugendubel1;

VORNAME:= ’ Kunigunde';

ORT := '7 B e r g e ';

STRASSE:= '7 Zw erge';

END;

Wie alles in Pascal können auch WITH-Anweisungen geschachtelt wer­

den. Nach der geschachtelten Record- Deklaration

BANKAUSZUG = RECORD DATUM: DATUM;

KONTOSTAND: REAL

END;

VAR MEINBANKAUSZUG: BANKAUSZUG;

prüft man folgendermaßen das Datum auf dem Bankauszug:

WITH MEINBANKAUSZUG DO BEGIN der äußeren WITH-Anweisung bezie­

hen. Hier ist dies also das Feld MEIN BANKAUSZUG.DATUM. Bemerkens­

wert sind noch die Sichtbarkeitsregeln für Feldnamen. Man kann ohne Na­

menskonflikte Variablen mit dem Feld­

namen aus der Record-Deklaration definieren. Der Feldname ist durch einen Punkt oder die WITH-Anweisung an den Variablennamen des Records gebunden.

Am besten verdeutlicht wiederum ein Beispiel die Arbeit mit Records. In Listing 15 wird der Typ

TYPE BRUCH = RECORD

ZAEHLER, NENNER: INTEGER;

END;

definiert. Man möchte also auch gebro­

chene Zahlen »exakt« darstellen. Nun lernt man aber In der Schule, daß

1 2 1 2 3 4 5 6

- und - und

---2 4 2 4 5 9 1 2

dieselbe Zahl darstellen. Deshalb wer­

den bei allen Operationen Zähler und Nenner gekürzt dargestellt. Zum Kür­

zen muß man den größten gemeinsa­

men Teiler (ggT) von Zähler und Nenner kennen. Beim Addieren werden die bei­

den Brüche auf einen Hauptnenner gebracht, der natürlich möglichst klein bleiben soll. Daher ist im Programm auch eine Funktion zur Berechnung

des kleinsten gemeinsamen Vielfachen (kgV) enthalten. Nach der Erweiterung der beiden Zähler ergibt sich durch Addieren der Zähler des Summenbru­

ches. Wegen der teilerfremden Aus­

gangsbrüche und der Wahl des Haupt­

nenners spart man es sich, den Zähler gegen den Nenner zu kürzen.

Die Multiplikation verläuft wie in der Schule nach der Regel Zähler mal Zäh­

ler und Nenner mal Nenner. Jedoch werden zuvor die Brüche kreuzweise gekürzt, um die Produkte möglichst klein zu halten. Vielleicht ist es eine gute Denksportaufgabe, zu überlegen, warum nach der Multiplikation Zähler und Nenner teilerfremd sind.

Die Subtraktion ist einfach auf die Addition zurückzuführen, ebenso wie die Division durch Kehrwertbildung auf die Multiplikation zurückführt. Bei der Berechnung des Kehrwertes ist jedoch auf eine korrekte Behandlung des Vor­

zeichens zu achten.

Normalerweise eignen sich zur Erläu­

terung von Records Beispiele aus der kaufmännischen Datenverarbeitung, da man einen Record am einfachsten als ein Formblatt beschreiben kann, das verschiedene Felder enthält, die nur Werte gewisser Typen beinhalten dür­

fen.

TYPE KRAFTFAHRZEUGSCHEIN = RECORD

WAGEN: KENNZEICHEN;

WOHNORT, STANDORT: ADRESSE;

LEISTUNG: INTEGER;

END;

Diese Deklaration setzt natürlich vor­

aus, daß zuvor die Typen KENNZEI­

CHEN und ADRESSE (zum Beispiel selbst als Records) definiert wurden.

Es gibt jedoch auch Felder, die nur dann gültig sind, falls in einem anderen Feld ein bestimmter Wert steht.

4 4

»>1 n r < r < y n

;QryiRJTEi£

TYPE PERSONALAKTE = RECORD

NAME : STRING;

VORNAME: STRING;

CASE STAND: FAMILIENSTAND OF LEDIG: ( ) ;

VERHEIRATET, GETRENNT:

(HEIRAT: DATUM);

GESCHIEDEN:

(SCHEIDUNG: DATUM;

ALIMENTE : BOOLEAN);

END;

VAR AKTEI: PERSONALAKTE;

Dieses Beispiel zeigt einen Varianten (veränderlichen) Record. Er besteht aus einem festen Teil (den Feldern NAME und VORNAME), dem ein verän­

derbarer Teil folgt. Dieser Teil wird durch das Schlüsselwort CASE eingeleitet.

Ihm folgt ein Feldname mit Typangabe.

In Abhängigkeit der Werte dieses skala­

ren Typs besitzen die nachfolgenden Feldlisten in runden Klammern Gültig­

keit.

Nach der Zuweisung »AKTE 1.STAND:

= LEDIG« sind nur die Felder NAME

und VO RNAM E gültig. Ist jedoch

»AKTE1.STAND = VERHEIRATET«, so wird zusätzlich das Feld HEIRAT vom Typ DATUM relevant. Ihm darf man jetzt Werte des korrekten Typs zuweisen:

AKTEI. HEIRAT.TAG := 7 ; AKTEI. HEIRAT.MONAT:=6;

AKTEI. HEIRAT.JAHR := 1 9 7 3 ;

Dieselben Felder gelten auch für

»STAND = GETRENNT«. Sollte im Laufe der Ehegeschichte eine Scheidung eintreten, so werden sich auch in der Personalakte gravierende Änderungen

PROGRAM BRUECHE (INPUT, OUTPUT);

(* RECHNUNG MIT BRUECHEN IN DER DARSTELLUNG ZAEHLER, NENNER *) TYPE BRUCH = RECORD

ZA EHLER: IN TE G E R ; NENNER : IN TE G E R ;

< * ZAEHLER UND NENNER IMMER * ) ( * T E IL E R F R E M D , NENNER P O S I T I V * ) END;

VAR A, B, SUMME, DIFFERENZ, PRODUKT, QUOTIENT; BRUCH; PROCEDURE KUERZ E( VAR A, B: INTEGER);

<* KUERZE A UND B DURCH IHREN GROESSTEN GEMEINSAMEN TEILER *) VAR X: INTEGER;

( * ZAEHLER MAL ZAEHLER UND NENNER MAL NENNER. VOR DER * )

< * M U L T IP L IK A T IO N WERDEN ZAEHLER UND NENNER G EKUERZT. * ) BE G IN

( * KUERZE ZUNAECHST K R E U Z W E IS E , D A M IT PRODUKT N IC H T *>

< * ZU GROSS W IRD #>

KUERZE (A .Z A E H L E R , B .N E N N E R );

KUERZE (B .Z A E H L E R , A .N E N N E R );

C. ZAEHLER: - A. ZAEHLER * B. ZAEHLER; C. NENNER : = A. NENNER * B. NENNER;

(* ZÄHLER UND NENNER VON C SIND HIER NOCH TEILERFREMD *>

END; (* MULTIPLIZIERE *) FUNCTION GGT ( X, Y; INTEGER): INTEGER;

<* BERECHNE DEN GRÖSSTEN GEMEINSAMEN TEILER VON X UND Y *) VAR H: INTEGER;

BEGIN IF Y> X THEN

BEGIN H: *X; X: = Y; Y: =H END; REPEAT

H: - X MOD Y; X: - Y; Y: * H UNTIL H = 0; GGT: = X; END; (* GGT *) BEGIN ( * KÜRZE *)

X: * GGT( ABS( A) , B) ; IF X01 THEN

BEGIN

A: * A DI V X; B: - B DI V X; END;

END; ( * KÜRZE *)

FUNCTION KGV( X, Y: INTEGER): INTEGER;

<* BERECHNE DAS KLEINSTE GEMEINSAME VIELFACHE VON X UND Y *) VAR U, V: INTEGER;

BEGIN

U: « X;. V: - Y; WHILE XOY DO

IF X> Y THEN

BEGINX: « X-Y; U: - U+VEND ELSE

BEGINY: » Y-X; V: - V + UEND; KGV: - ( U*V) DI V 2

<* ÜBRIGENS IST GGT( X, Y) = X *) END; (* KGV *)

PROCEDURE ADDIERE ( A, B: BRUCH; VAR C: BRUCH);

(* ADDIERE DIE BRÜCHE A UND B ZUM BRUCH C *) VAR HN: INTEGER; (* HAUPTNENNER *) BE G IN

W ITH C DO B E G IN

( * HAUPTNENNER BERECHNEN * ) HN K G V < A .N E N N E R , B .N E N N E R );

NENNER HN;

< * AUF HAUPTNENNER BR IN GEN * )

ZAEHLER : = A .Z A E H L E R * (HN D IV A .N E N N E R ) + B .Z A E H L E R * (HN D I V B .N E N N E R );

END; ( * W ITH * ) END; <* A D D IE R E *>

PROCEDURE SUBTRAHIEREt A, B: BRUCH; VAR C: BRUCH) ; (* SUBTRAHIERE B VON A. ERGEBNIS IN C *) BEGIN

B. ZAEHLER: - - B. ZAEHLER; ADDIERE(A,B,C)

END; ( * SUBTRAHIERE *)

PROCEDURE MULTI PLI Z IERE( A, B: BRUCH; VAR C: BRUCH);

PROCEDURE KEHRWERTtVAR A: BRUCH);

(* BERECHNE DEN KEHRWERT VON A. BEACHTE DIVISION DURCH 0 UND VORZEICHEN *)

VAR T: INTEGER; BEGI N

T: = A. ZAEHLER;

IF T = 0 THEN WRITELN( * DIVISION DURCH NULL!’) ELSE

IF T> 0 THEN BEGIN

A. ZAEHLER: * A. NENNER; A. NENNER : » T END

ELSE BEGIN

A. ZAEHLER: * -A. NENNER; A. NENNER : * -T; END;

END; ( * KEHRWERT *>

PROCEDURE LESEN (VAR A : B R U C H );

<« L IE S T E IN E N rB R U C H VON DER TA S TA T U R . WIRD NACH * ) ( * DEM ZAEHLER7 DAS ZE ILE N E N D E E R R E IC H T , SO W IRD * )

< * DER NENNER G L E IC H E IN S G ESETZT * )

BEGIN WITH A DO

BEGIN

READ( A. ZAEHLER) ;

IF EOLN THEN A. NENNER: = 1 ELSE READLN( A. NENNER) ; END;

KUERZ E( A. ZAEHLER, A. NENNER) ; END; ( * LESEN *)

PROCEDURE DRUCKEN ( A: BRUCH) ; BEGI N

WITH A DO

IF NENNER * 1 THEN WRITELN(ZAEHLER) ELSE

WRITELNi ZAEHLER, • /’, NENNER) END; (* DRUCKEN *)

BEGIN

WRITELNt * RECHNEN MIT BRUECHEN: (EMDE MIT A = 0) * );

REPEAT

WRITEi 'A - • ) ; LESEN( A) ; WRI TE( ' B - * ) ; LESEN( B) ; ADDIERE« A, B, SUMME) ;

WRITE(' A B » ’); DRUCKEN«SUMME);

SUBTRAHIERE« A, B, DIFFERENZ) ;

WRITE( ' A - B - *); DRUCKEN( DIFFERENZ);' MULTIPLIZIERE«A,B,PRODUKT);

WRITEt-A * B » •); DRUCKEN«PRODUKT);

KEHRWERT« B) ; MULTIPLIZIERE« A, B, QUOTIENT) ; WRITEi‘A / B • ’); DRUCKEN«QUOTIENT);

UNTIL A. ZAEHLER - 0; END.

Listing 15. Bruchrechnung mit Records in Pascal

oM P Îm

45

vollziehen. Mit »AKTE1.STAND := GE­

SCHIEDEN* wird das Feld HEIRAT un­

gültig und statt dessen das Feld SCHEI­

DUNG (ebenfalls ein Datum) mit dem booleschen Feld ALIMENTE wirksam.

Offensichtlich kann man mit Varianten Records sehr gut die Tatsache wieder­

geben, daß gewisse Attribute eines Objektes nur unter gewissen Randbe­

dingungen relevant sind. Dies wird dadurch erreicht, daß zu jedem Zeit­

punkt immer nur eine der Feldlisten in Klammern hinter den Konstanten gültig ist. Diese zusätzlichen Informationen nutzt der Pascal-Compiler, um wie­

derum Speicherplatz zu sparen. Er legt alle Varianten (also alle Feldlisten, die zu verschiedenen Werten des Auswahlfel­

des gehören) an dieselbe Speicherpo­

sition. Zur Laufzeit bestimmt dann das Auswahlfeld nach CASE (engl, tagfield), wie der Inhalt des Speichers zu inter­

pretieren ist. Alle gemeinsamen Felder aus dem festen Teil sind eindeutig, wäh­

rend die Felder im Varianten Teil sich gegenseitig überlappen.

Diese Überschneidung muß beach­

tetwerden, wenn ein Wechsel des Aus­

wahlfeldes anfällt. Eine Anwendung varianter Records zeigt Listing 16.

Bekanntermaßen kann man einen Punkt in der Ebene auf zwei verschie­

dene Methoden darstellen:

In rechtwinkligen X- und Y-Koordina- ten oder mit Polarkoordinaten, durch Angabe der Entfernung des Punktes zum Koordinatensprung (L) und des Winkels zur X-Achse (PHI).

Da sich eine Darstellungsform für gewisse Anwendungen jeweils besser eignet, wird in diesem Programm mit Varianten Records ein Wechsel zwi­

schen beiden Darstellungen zugelas­

sen:

TYPE KOORDINATE = RECORD

CASE TYP:KOORDINATENTYP OP RECHTWINKLIG: KOORDINATENTYP) durch einen Typ­

namen erfolgen muß. Je nach dem Wert von Typ ist also die Koordinate durch X und Y oder L und PHI bestimmt. Im übri­

gen Programm können Sie neben dem Nutzen der WITH-Anweisung bei der Arbeit mit Records auch den Vorteil der Case-Anweisung bei Varianten Records erkennen. Indem man vor dem Zugriff auf eine Variante eine CASE-Anweisung setzt, die die Konstanten aus der

Record-Deklaration wiederholt, ist man vor unerlaubten Zuweisungen wie P . TYP:= POLAR;

P.X := 3 9 .4 ;

geschützt. Erwähnenswert ist noch die Ende-Bedingung der Repeat-Schleife UNTIL BETRAG(P) < = EPSILON;

Das Programm soll beendet werden, wenn die Entfernung des Punktes vom Ursprung Null ist. Da jedoch alle reellen Zahlen nur mit Rundungsfehlern berechnet werden können, verwendet man zwischen reellen Zahlen nie den Test auf Gleichheit (A = B ), sondern nur eine Prüfung der Form ABS(A-B) < = EPSILON mit einer Konstanten EPSI­

LON, die eine Schranke für die Run­

dungsfehler auf dem jeweiligen Rech­

ner angibt. Die Berücksichtigung dieser Regel hilft eine Reihe häufiger Fehler zu vermeiden.

Nun sind wir am Ende unserer Einfüh­

rung in das Programmieren mit Funktio­

nen, Prozeduren und Datentypen ange­

langt. Zur Vertiefung der gewonnenen Erkenntnisse sei es dringend angera­

ten, ein wenig mit den abgedruckten Beispielen herumzuexperimentieren, sie zu erweitern und abzuändern. Denn auch in Pascal gilt der altbekannte Spruch vom Meister, den man nur durch Ü b u n g ...

Listing 16. Koordinatenumrechnung mit Varianten Records

4 6

Sp'M'RJTEI

Dateiverwaltung mit

Im Dokument Einführung in PASCAL (Seite 31-36)