Teil X Von Mini Pascal zu Pascal 1
Teil X.1 Pascal Datentypen 2
Begriffe Typ: Menge von Werten Beispiel: integer alle ganzen Zahlen zwischen - MaxInt und MaxInt Variable: Reserviert Speicherplatz für Werte ihres Typs Zuweisung: Weist einer Variablen einen Wert zu. 3
Einfache Datentypen Integer: alle ganzen Zahlen - MaxInt und MaxInt Varianten: byte: 0..255 word: 0..MaxInt LongInt: - MaxInt 2..MaxInt 2 1 ShortInt: -128..127 Boolean: True oder False Char: Meist ASCII-Code 32..127 Real: Exponentendarstellung nach IEEE 754/854 Varianten: single: 32 bit double: 64 bit extended: 80 bit String: Zeichenketten (beliebiger Länge) zwischen 4
Typkonstruktoren (1) Array: Vektor fester Länge, Matrix mit fester Größe Syntax: array [ Bereichstyp ] of Type Beispiele: array[0..10] of Integer array[ a.. z ] of Integer type matrix = array[0..10] of array [0..6] of Real type matrix1 = array[0..10,0..6] of Real Zugriff: var m: matrix; m[3,2] := 7.3; 5
Typkonstruktoren (2) Record: Verbund über Typen T 1... T n Beispiel: type Datum = record Tag : 1..31; Monat : (Jan, Feb, Mar, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez); Jahr : Integer end; Zugriff: var date: Datum; date.monat := Jan; with date do begin Tag := 3; Monat := Jun; Jahr := 2002 end; 6
Typkonstruktoren (3) case Record mit Varianten Beispiel: type Stand = (verh, verw, gesch, ledig); Person = record name : record vorname, nachname : string end; Versnr : integer; Geschlecht : (Mann, Frau); Geburt : Datum; Kinder : integer; case stkomp : Stand of verh, verw : (vd : Datum); gesch : (gd : Datum); ledig : (unabh : boolean); end; 7
Typkonstruktoren (4) Set: Menge von Ordinaltypen Syntax: set of OrdinalerTyp Beispiel: type myset = set of Integer Operationen: + Mengenvereinigung - Komplementbildung * Durchschnitt in ElementOf 8
Zeigertypen (1) Zeiger: Addresse auf Speicher eines gegebenen Typs Beispiel: type Liste = ^Eintrag; Eintrag = record Elem : Integer; Nachfolger : Liste end; var : anfang, neu, p, q : liste; Operationen: new(v) fordert freien Speicher vom Typ T an Zugriff auf Wert: v^ dispose(v) gibt Speicher für v wieder frei. 9
Zeigertypen (2) Erzeugen einer Liste anfang := nil; (* leere Liste erzeugen *) new(anfang); (* Es wird eine Variable anfang^ vom Typ Eintrag erzeugt *) anfang^.elem := 2; anfang^.nachfolger := nil; (* nun hat die Liste ein Element *) (* der Listenanfang ist erzeugt *) 10
Zeigertypen (3) Einfügen eines Elements an den Anfang p := anfang; new(anfang); anfang^.nachfolger := p; anfang^.elem := 5; 11
Zeigertypen (4) Einfügen eines Elements an das Ende p := Anfang; while p^.nachfolger <> nil do p := p^.nachfolger; new(q); q^.nachfolger := nil; q^.elem := y; p^.nachfolger := q; (* Eintrag an alte Liste gehaengt *) 12
Zeigertypen (5) Suchen eines Elements elem = x p := anfang; found := false; leer := false; while not found and not leer do begin if (p <> nil) then begin if p^.elem = x then found := true else p := p^.nachfolger end else leer := true; if found then writeln( gefunden ) else if leer then writeln( nicht vorhanden ); end; (* while *) 13
Zeigertypen (6) Einfügen eines Elements nb nach dem Element nach p := anfang; found := false; leer := false; while not found and not leer do begin if (p <> nil) then begin if p^.elem = nach then found := true else p := p^.nachfolger end else leer := true; if found then writeln( gefunden ) else if leer then writeln( nb nicht vorhanden ); end; (* while *) if found then begin new(q); q^.nachfolger := p^.nachfolger; q^.elem := nb; p^.nachfolger := q end; 14
Zeigertypen (7) Löschen des ersten Elements mit Wert x if (anfang <> nil) then begin if (anfang^.elem = x) then begin p:=anfang^.nachfolger; dispose(anfang); anfang:=p end (* if erstes Element = x *) else begin p := anfang; found := false; leer := false; while not found and not leer do begin if (p^.nachfolger <> nil) then begin if (p^.nachfolger^.elem = x) then found := true else p := p^.nachfolger end else leer := true; end; (* while *) if found then begin q:=p^.nachfolger^.nachfolger; dispose(p^.nachfolger); p^.nachfolger:=q end; end; (* if erstes Element <> x *) end (* if anfang <> nil) 15
Dateien Syntax: file [ of Typ]. Semantik: Folge von Komponenten mit gegebenen Typ. Operationen (in ISO-Pascal): get(f) lese aktuelle Komponente und schalte F auf die nächste Komponente reset(f) öffnen von F zum Lesen put(f) schalte F auf die nächste Komponente zum Beschreiben rewrite(f) öffnen, initialisieren von F für Schreibvorgang eof(f) Abfrage auf Dateiende close(f) Schließen einer Datei. 16
Teil X.2 Kontrollstrukturen, Prozeduren, Funktionen 17
Kontrollstrukturen Repeat-Anweisung = "Repeat" statement {";" statement } "until" expression. For-Anweisung If-Anweisung Case-Anweisung = "for" Laufvariable ":=" expression ("to" "downto") expression "do" statement. = "if" expression "then" statement ["else" statement]. = "case" expression "of" Bereich ":" statement {Bereich ":" statement} ["else" ":" statement] 18
Prozeduren mit Parametern Syntax: procdecl = "procedure" ident [ Interface ]; block; interface = "(" [var] ident ":" Type {; [var] ident ":" Type} ")" Wertparameter: ident : Type Die Variable ident wird bei Aufruf mit dem Wert des aktuellen Parameters (Variable oder Ausdruck) belegt, Änderung von ident innerhalb der Prozedur nach außen nicht sichtbar. Referenzparameter: var ident : Type Die Variable ident wird bei Aufruf mit einer Referenz auf den aktuellen Parameter (nur Variable) belegt, Änderung von ident innerhalb der Prozedur ist nach außen sichtbar. Nützlich für strukturierte Ausgaben. 19
Beispiel: Wert- vs. Referenzparameter Program callbyvaluevscallbyref var i,j,k: integer procedure p(var i1: integer; j1: integer) begin j1:=j1+1; (*? *) i1:=i1+j1; end begin i:=0; j:=1; k:=2; writeln( before: i:, i,, j: j,, k:,k); p(i,j*k); writeln( after: i:, i,, j: j,, k:,k) end. (* Ergebnis: before: i : 0, j:1, k:2 after: i : 3, j:1, k:2 *) 20
Verschränkt rekursive Prozeduren Problem: Verwendung einer Prozedur vor Deklaration Lösung: Trennung von Deklaration und Implementierung mit Hilfe von forward Program abwechselnd; var i, h : integer; procedure q (var k : integer); forward; procedure p (var i, j : integer); begin inc(i); j := i+5; if j < 10 then begin write( q:, j); q(j) end; end; procedure q; begin inc(k); write( p:, k); p(i, k) end; begin i := 0; h := 1; write ( p:, h); p(i, h); writeln( p:, h) end. (* Ergebnis: p:1 q:6 p:7 q:7 p:8 q:8 p:9 q:9 p:10 p:10 *) 21
Ablauf der verschränkten Rekursion i:=0; h:=1; writeln( p:, h); (* p: 1 *) p(i,h); (* i=0, h=1 *) inc(i); j:= i+5; if j < 8 then begin writeln( q:, j); (* q: 6 *) q(j); (* j=6 *) inc(k); writeln( p: k); (* p: 7 *) p(i,k); (* i=1, k=7 *) inc(i); j:= i+5; if j < 8 then begin writeln( q:, j) (* q: 7 *) q(j); (* j=7 *) inc(k); write( p:, k); (* p: 8 *) p(i,k); (* i=2, k=8 *) inc(i); j: = i+5 (* j=8 *) if j < 8 then... writeln( p:, h) (* p: 8 *) 22
Funktionen Wie Prozeduren, jedoch mit explizitem Rückgabeparameter Syntax: Nur einfache Rückgabetypen erlaubt. funcdecl = "function" ident [Interface]: Type; block; Beispiel: Vergleiche: function rfak(n : word) : word; begin if n=0 then rfak := 1 else rfak := rfak(n-1) * n end; procedure rfak(n : word; var ret: word); begin if n=0 then ret := 1 else begin rfak(n-1,ret); ret := ret * n end; end; 23
Beispiel: Minicompiler Aufgabe: Übersetze folgende Syntax in Maschinenprogramm Wertzuweisung = ("a"... "z") ":" "=" Ausdruck ";" Ausdruck = Term = Term {("+" "-") Term} Faktor {("*" "/") Faktor} Faktor = "a"... "z" ("(" Ausdruck ")") 24
Minicompiler: Hauptprogramm program Minicompiler; uses wincrt; var i: Byte; s: String[80]; {80 Zeichen maximal} procedure Fehler(i: byte); begin writeln( Fehler in Position,i:2); end;... begin {Hauptprogramm} write( Wertzuweisung einlesen ); write( - ohne Leertaste - ); writeln( mit Semikolon zum Ende: ); readln(s); i:= 1; while s[i] <> X do begin writeln; Wertzuweisung(s,i); writeln( Press X to stop ); readln(s); i:= 1 end end. 25
Regel für Wertzuweisung (* verschraenkte Rekursion *) procedure Ausdruck(var s: String[80]; var i: Byte); forward; procedure Term(var s: String[80]; var i: Byte); forward; procedure Faktor(var s: String[80]; var i: Byte); forward; (* Wertzuweisung = ("a"... "z") : = Ausdruck ";" *) procedure Wertzuweisung(var s: String[80]; var i: Byte); var ch: Char; begin case s[i] of a.. z : begin ch:= s[i]; inc(i); if s[i] <> : then Fehler(i); inc(i); if s[i] <> = then Fehler(i); inc(i); Ausdruck(s,i); writeln( STORE, ch); if s[i] <> ; then Fehler(i) end else Fehler(i) end end; {Wertzuweisung} 26
Regel für Ausdruck (* Ausdruck = Term {("+" "-") Term} *) procedure Ausdruck(var s: String[80]; var i: Byte); var stop: boolean; begin Term(s,i); stop:=false; repeat case s[i] of + : begin inc(i); Term(s,i); writeln( ADD ) end; - : begin inc(i); Term(s,i); writeln( SUB ) end else stop:=true; end; until stop end; {Ausdruck} 27
Regel für Term (* Term = Faktor {("*" "/") Faktor} *) procedure Term(var s: String[80]; var i: Byte); var stop: boolean; begin stop:=false; Faktor(s,i); repeat case s[i] of * : begin inc(i); Faktor(s,i); writeln( MULT ) end; / : begin inc(i); Faktor(s,i); writeln( DIV ) end else stop:=true; end; until stop; end; {Term} 28
Regel für Faktor (* Faktor = "a".. "z" ("(" Ausdruck ")") *) procedure Faktor(var s: String[80]; var i: Byte); begin case s[i] of a.. z : begin writeln( LOAD,s[i]); inc(i) end; ( : begin inc(i); Ausdruck(s,i); if s[i] <> ) then Fehler(i) else inc(i) end else Fehler(i) end end; {Faktor} 29
Teil X.3 Objektorientierte Programmierung in Pascal 30
Grundbegriffe der Objektorientierten Programmierung Objekttyp: (Klasse) Kombination von Daten (Zustand) mit Programmen (Methoden) Kapselung: Nur öffentliche (public) Methoden und Variablen sind außerhalb einer Klasse sichtbar; auch genannt: Interface einer Klasse. Vererbung: Ableitung neuer Klassen aus einer bereits bestehenden durch Hinzufügen von Methoden und Variablen. Konstruktor: Methode zum Erzeugen eines Objekts Destruktor: Methode zum Löschen eines Objekts 31
Klasse Ellipse implementieren. Beispiel: Geometrische Figuren Eine mögliche Klassenhierarchie für geometrische Figuren zeigt unser Bild: 10.4.3 Implementierung In einem Definitionsmodul werden die Merkmale und Methoden der verschiedenen Klassen exakt definiert und gleichzeitig die Hierarchiebeziehungen zwischen den Klassen festgelegt. 32
GrObjekt Gemeinsame Methoden Gemeinsame Methoden(-interfaces) und Variablen Program Geometrische_Figuren; Type PunktRec = Record x, y : Longint; End; GrObjekt = CLASS (* In Borland Pascal muss das Schluesselwort *) (* CLASS durch OBJECT ersetzt werden *) Bezugspunkt : PunktRec; Sichtbar : Boolean; Constructor Init (x, y : Longint); Destructor Done ; Procedure Verschiebe(dx, dy : Longint); Procedure Zeichne; Virtual; Procedure Anzeigen; Procedure Loesche; End; (* GrObjekt *); 33
Punkt und Strecke Spezifische Implementierung für Konstruktor, Destruktor, Zeichnen Zusätzliche Methode Skaliere Punkt = CLASS(GrObjekt) Constructor Init (x, y : Longint); Destructor Done ; Procedure Zeichne; Virtual; End; (* Punkt *) Strecke = CLASS(GrObjekt) P1 : Punkt; Constructor Init (xa, ya, xb, yb : Longint); Destructor Done ; Procedure Skaliere (F : Real); Procedure Zeichne; Virtual; End; (* Strecke *) 34
Polygon und Dreieck Neue Methode Fläche Const MaxPunkte = 100; Type PktVektor = Array[0..MaxPunkte] Of PunktRec; PolygonS = CLASS(GrObjekt) Constructor Init (PV : PktVektor); Destructor Done ; Procedure Zeichne; Virtual; Procedure Skaliere (F : Real); Function Flaeche : Real; End; (* PolygonS *) Dreieck = CLASS(PolygonS) Constructor Init (xa, ya, xb, yb, xc, yc : Longint); Destructor Done ; Procedure Zeichne; Virtual; Function Flaeche : Real; End; (* Dreieck *) 35
Rechteck und Quadrat Neue Eigenschaften: Winkel, Breite, Höhe Rechteck = CLASS(GrObjekt) Winkel : Real; Breite, Hoehe : Real; Constructor Init (xa, ya : Longint; W, B, H : Real); Destructor Done ; Procedure Skaliere (F : Real); Procedure Zeichne; Virtual; Function Flaeche : Real; End; (* Rechteck *) Quadrat = CLASS(Rechteck) Constructor Init (xa, ya : Longint; W, B: Real); Destructor Done ; Procedure Zeichne; Virtual; End; (* Quadrat *) 36
Implementierung: Konstruktor Getrennt von Interface-Deklaration: Constructor Punkt.Init (x, y : Longint); Begin Bezugspunkt.x := x; Bezugspunkt.y := y; Sichtbar := true End; (* Punkt.Init *) 37
Implementierung: Verschiebe Verwendung von spezifischen Methoden (Zeichne) in einer generischen Methode (Verschiebe) Procedure GrObjekt.Verschiebe (dx, dy: LONGINT); Begin If sichtbar Then Begin Loesche; Bezugspunkt.x := Bezugspunkt.x + dx; Bezugspunkt.y := Bezugspunkt.y + dy; Zeichne End; End; (* Verschiebe *) 38