Michael Neuhold Homepage
Startseite >
Informatikunterricht >
Turbo Pascal für Fortgeschrittene
Das folgende ist nie ganz fertig geworden. Vor allem mangelt es an praktischen Beispielen, da man im Unterricht selten alle diese Themen abhandeln kann. Das Thema Objekte und objektorientierte Programmierung füllt Bücher; hier kann nur ein minimaler Hinweis auf die Syntax gegeben werden.
CONST name: Typ = Wert;Obwohl mit dem Schlüsselwort CONST vereinbart, handelt es sich eigentlich um Variablen mit einem definierten Startwert. Der Wert kann zur Laufzeit geändert werden.
TYPE Faecher = (D, E, L, M, GW, GS, Ph, BU); PersDaten = RECORD name, vorname: String[30]; titel: String[10]; UFach: Faecher; END; CONST direktor: PersDaten = (name: 'Löwenzahn'; vorname: 'Hans'; titel: 'Hofrat'; UFach: M);
TYPE DreiLottoTips = ARRAY [1..3, 1..6] OF Byte; CONST Tip17: DreiLottoTips = ((2,13,21,37,41,44), (8,12,27,31,38, 42), (15,19,21,23,29,31));
TYPE Person = RECORD name: String[20]; GebDatum: String[10]; geschlecht: Char; CASE stand: String[12] OF 'ledig': (); 'verwitwet', 'verheiratet', 'geschieden': (GebName: String[12]); END;Wenn die Komponente stand den Wert 'verwitwet', 'verheiratet' oder 'geschieden' hat, besitzt der Record noch ein weiteres Feld GebName.
IF (stand='verheiratet') OR (stand='geschieden') OR (stand='verwitwet') THEN BEGIN write ('Bitte den Ledigennamen eingeben: '); ReadLn (GebName); END;
TYPE MitgliederStatus = (Aktiver, Wettkaempfer, Foerderer); Sportart = (Karate, Judo, Aikido); Mitglied = RECORD name: String[25]; CASE status OF Aktiver: (Disziplin: Sportart; BeitrErmaess: Boolean); Wettkaempfer: (Disziplin: Sportart; Punkte: Word); Foerderer: (Seit, GebDatum: String[10]); END;
TYPE change = RECORD CASE Boolean OF TRUE: (ch: Char); FALSE: (n: Byte); END; VAR trick: change; trick.ch:= 'A'; WriteLn ('Zeichen: ', trick.ch); WriteLn ('Wert : ', trick.n); trick.n:= 66; WriteLn ('Zeichen: ', trick.ch); WriteLn ('Wert : ', trick.n);Dies wird z. B. vom Datentyp Registers (Unit dos) verwendet, seine Definition lautet:
TYPE Registers = RECORD CASE Integer OF 0: (ax, bx, cx, dx, bp, si, di, ds, es, flags: Word); 1: (al, ah, bl, bh, cl, ch, dl, dh: Byte); END;
TYPE SetTyp = SET OF ElementTyp; VAR MySet: SetTyp;z.B.
TYPE CharSet = SET OF Char;
CharSet:= [ ]; CharSet:= CharSet + ['D'];
ErlaubteTasten:= [#13, #27, 'j', 'n']; IF taste IN ErlaubteTasten THEN...
PROCEDURE Dies; BEGIN ...; Das; END; PROCEDURE Das; BEGIN Dies; ...; END;
PROCEDURE Flip (n: Byte); FORWARD; PROCEDURE Flop (n: Byte); BEGIN WriteLn ('Flop', n); IF n>0 THEN Flip (n-1); END; PROCEDURE Flip; BEGIN WriteLn ('Flip', n); IF n>0 THEN Flop (n-1); END;
Ist ein Datentyp, der die Anfangsadresse eines Datums (Einzahl von Daten) enthält, und zwar in der Segment-Offset-Schreibweise, ein Pointer benötigt 4 Byte Speicher (2 Byte Offset, 2 Byte Segment).
TYPE ZeigerTyp = ^DatenTyp; {vorangestelltes ^ bedeutet: Zeiger auf DatenTyp}
VAR ZeigerVariable: ZeigerTyp;
zeiger
) und dem von ihr referenzierten Datum
(zeiger^
). Das Datum wird mit nachgestelltem ^ bezeichnet:
TYPE IntPtr = ^Integer; VAR MerkZeiger: IntPtr; WriteLn (MerkZeiger^); {gib die Integerzahl aus, auf die MerkZeiger zeigt}
Heap |
Stacksegment (max. 64 KByte) |
Codesegment (- " -) |
Datensegment (- " -) |
TYPE ListPtr = ^ListElem; {hier keine explizite FORWARD-Deklaration nötig} ListElem = RECORD item: String[20]; {Datum} next: ListPtr; {Zeiger auf nächsten Record} END;
NeuZeiger:= NIL;
VAR ListBeginn, ListPtr, NeuPtr: ListPtr; ListPtr:= NIL;
New (NeuPtr); {Zeiger für einen neuen Record allozieren} ReadLn (NeuPtr.item); {Datum einlesen} NeuPtr.next:= ListBeginn; {neues Element auf erstes Element der Liste zeigen lassen} ListBeginn:= NeuPtr; {Zeiger auf Listenbeginn auf neues Element zeigen lassen}Die Reihenfolge der Operationen ist wichtig!! Andernfalls würde die Liste unterbrochen, die Daten wären noch im Heap, es könnte aber nicht auf sie zugegriffen werden.
VAR ListBeginn, ListEnde, NeuPtr: ListPtr; {*** initialisieren: ***} ListBeginn:= NIL; ListEnde:= NIL; {*** erstes Element einfügen: ***} New (NeuPtr); ReadLn (NeuPtr.item); ListBeginn:= NeuPtr; ListEnd:= NeuPtr; NeuPtr.next:= NIL; {*** weitere Elemente einfügen: ***}
VAR zeiger: Pointer;
TYPE TFriendRec = RECORD Name: string[30]; Alter: Byte; END; VAR p: pointer; BEGIN IF MaxAvail < SizeOf (TFriendRec) THEN WriteLn ('Nicht genügende Speicher') ELSE BEGIN GetMem (p, SizeOf (TFriendRec)); {Speicher auf dem Heap allozieren} {Speicher benutzen} FreeMem (p, SizeOf (TFriendRec)); {Speicher wieder freigeben} END; END.
VAR pTop: Pointer; p1,p2,p3: ^Integer; BEGIN New(p1); {Integer allozieren} Mark(pTop); {Zeiger auf Heapspitze speichern} New(p2); {zwei weitere Integer allozieren} New(p3); Release(pTop); {Speicher für p2^ and p3^ freigeben, p1^ kann weiter verwendet werden} END;
USES graph; TYPE RectObj = OBJECT x1, y1, x2, y2: Integer; PROCEDURE NewProps (nx1, ny1, nx2, ny2: Integer); PROCEDURE Draw (color: Byte); END; VAR Rechteck: RectObj; PROCEDURE RectObj.NewProps (nx1, ny1, nx2, ny2: Integer); BEGIN x1:= nx1; y1:= ny2; x2:= nx2; y2:= ny2; END; PROCEDURE RectObj.Draw (color: Byte); BEGIN SetColor (color); Rectangle (x1, y1, x2, y2); END;Auf die Methoden greift man genauso zu wie auf Datenfelder von Records, also mit Objektvariable.Methodenname, z.B.
Rechteck.Draw(LightRed);
.Rechteck.x1:= 100
usw.), doch widerspräche dies dem Konzept der OOP. Um diese direkten
Datenmanipulationen überhaupt zu verhindern, kann (und sollte) man die
Daten als PRIVATE deklarieren.TYPE BarObj = OBJECT (RectObj) {neues Objekt erbt alle Eigenschaften der Mutter} pattern: Byte; {neues Datenfeld wird hinzugefügt} PROCEDURE Draw {ererbte Methode wird modifiziert} (pattern, color: Byte); PROCEDURE Clear; {neue Methode wird hinzugefügt} END; PROCEDURE BarObj.Draw; BEGIN SetFillStyle (pattern, color); Bar (x1, y1, x2, y2); END; PROCEDURE BarObj.Clear; BEGIN SetViewport (x1, y1, x2, y2, ClipOn); ClearViewport; SetViewport (0, 0, GetMaxX, GetMaxY); END;
{*** Programmkopf: ***} UNIT queue; {der Unitname muß mit dem Dateinamen identisch sein!} USES ...; {*** Benutzerschnittstelle: ***} INTERFACE {Deklaration der Prozedur- und Funktionsköpfe, Konstanten und Variablen, die von außerhalb der Unit zugänglich sein sollen} {*** Implementation: ***} IMPLEMENTATION {Implementation der Prozeduren und Funktionen. Prozeduren, die nur hier implementiert sind, aber nicht im Interface-Teil stehen, können zwar von anderen Prozeduren dieser Unit aufgerufen werden, nicht jedoch vom Programm, das diese Unit benutzt.} {*** Programmteil:***} BEGIN {Hier können Variableninitialisierungen und Prozeduraufrufe stehen, kann aber auch leer sein.} END.
Autor: E-Mail-Kontakt)
Erstellungsdatum: Irgendwann 1996/7
Letzte Aktualisierung: 10. Juni 2024