Claus Schönleber

Hitchhacker´s Guide To PASCAL  [Vol. 2]

[ zurück | weiter ]
  [ Start | Beispielprogramme Download | Home ]

Inhalt

Typisierte 
 Konstanten
Sets (Mengen)
Rekursion
Records
Dateien
 (Random Access)
Pointer
Algorithmen
- Hashing
- Sortieren
 
 

Records

Die Strukturart "record" gehört zu den komplexen Datentypen, die PASCAL zur Verfügung stellt. 
Record
Ein Record (Datensatz) ist ein willkürlicher Verbund der verschiedensten Typen zu einer Einheit. Ein mit Werten gefüllter Record heißt Datensatz, die verschiedenen Elemente Datenfelder.
Beispiele
  • Record zur Personenbeschreibung, bestehend aus den Datenfeldern Name, Vorname, Straße, Ort....
  • Record zur Artikelbeschreibung, bestehend aus den Datenfeldern Artikelbezeichnung, Artikelnummer, Hersteller, Anzahl am Lager,...
Etwas weniger formal: Um ein Objekt mit komplizierteren Eigenschaften zu beschreiben, wird eine Struktur eingeführt, die aus beliebigen Einzeltypen zusammengesetzt werden kann. Der mathematische Begriff für den Record ist "n-stellige Relation" oder "n-stelliges Kreuzprodukt".

Die Einführung von Records kann sowohl im Typedeklarationsteil als auch im Variablendeklarationsteil (anonymer record) passieren. Normalerweise sollte aber diese komplizierte Struktur in der Typdeklaration mit einem Namen versehen werden, um sich nachher viel Tipparbeit zu sparen. Da sowohl die Deklaration als auch der Zugriff nicht in gewohnter Weise ablaufen, sollen hier beide ausführlich vorgestellt werden.

Für die Deklaration gleich ein Beispiel:

TYPE person = RECORD
                name,vorname  : STRING [30];
                strasse,ort   : STRING [50];
                gehalt        : real;
                fuehrerschein : boolean;
                telephon      : ARRAY [1..3] OF STRING [25];
              END;

VAR mitarbeiter : person;
Wie man sieht, kann man beliebig viel Information über ein Objekt in so einem Record speichern. Ein Datenfeld darf sogar ein ARRAY oder eine noch kompliziertere Struktur als Typ besitzen, zum Beispiel wieder einen Record. Wie aber greift man nun auf ein Datenfeld zu? Hier ein Beispielprogrammfragment mit den entsprechenden Selektoren:
.
.
.
mitarbeiter.name := 'Müller';
mitarbeiter.vorname := 'Hans';
.
.
mitarbeiter.gehalt := 2534.50;
mitarbeiter.fuehrerschein := true;
mitarbeiter.telephon [1] := '0123/456789';
.
.
.
Also: die Selektion eines Datenfeldes einer Variablen mit Recordstruktur geschieht durch Angabe des Variablennamens, gefolgt von einem Punkt und der Bezeichnung des gewünschten Datenfeldes.

<variable>.<datenfeld>

In dieser Form kann das angesprochene Datenfeld wie eine gewöhnliche Variable des entsprechenden Typs in Ausdrücken verwendet werden.

Records werden in der Regel im Zusammenhang mit anderen Strukturen verwendet. Üblicherweise sind sie Bestandteil von Random Access Dateien oder Pointerlisten. Beide Strukturen werden später noch besprochen werden. Alleine haben Records in Programmen meist nur unterstützenden Charakter.

Das folgende Programmbeispiel soll wieder nur die Einbindung dieses Typs anhand einer einfachen Anwendung, der Definition komplexer Zahlen, zeigen:

PROGRAM record_beispiel;

  TYPE complex = RECORD
                   re,im : real;
                 END;
  VAR x,y,result : complex;

PROCEDURE sum (VAR r : complex; x,y : complex);
BEGIN
  r.re := x.re + y.re;
  r.im := x.im + y.im;
END;

BEGIN
  x.re := 2;
  x.im := 5;
  y.re := 4;
  y.im := 8;
  sum (result,x,y);
  writeln ('Summe: ',result.re:3:0,' ',result.im:3:0,'i');
END.
Das Programm berechnet die Summe zweier komplexer Zahlen mittels der Prozedur. Das Ergebnis wird per Referenz in eine zunächst nicht initialisierte Variable übergeben. Diese Programmiertechnik ist nicht uninteressant, und Sie sollten sie sich neben der Verwendung des Records genau ansehen. Im Übrigen wird dadurch das uralte, immer wieder benutzte Argument widerlegt, FORTRAN sei deshalb vorzuziehen, weil es den Datentyp COMPLEX zur Verfügung stellt. Wie man sieht, kann man den in PASCAL sehr schnell und einfach implementieren.

WITH

Sehen wir uns noch einmal das letzte Beispiel an. Man muß öfter einem kompletten Record seine Werte irgendwie zuweisen. Das ist mit viel Tipparbeit verbunden. Deshalb kann man eine Abkürzung einführen, die nur diesem Zweck dient. Die Übersichtlichkeit wird dadurch etwas eingeschränkt; deshalb ist an so einer Stelle reichhaltige Kommentierung notwendig. Die Abkürzung soll gleich in das obige Programm eingebaut werden; allerdings wieder nur beispielhaft, d.h. scheinbar überflüssig:
.
.
PROCEDURE sum (VAR r : complex; x,y : complex);
BEGIN
  WITH r DO
  BEGIN
    re := x.re + y.re;
    im := x.im + y.im;
  END;
END;

BEGIN

  WITH x DO
  BEGIN
    re := 2;
    im := 5;
  END;

  WITH y DO
  BEGIN
    re := 4;
    im := 8;
  END;

  sum (result,x,y);
  writeln ('Summe: ',result.re:3:0,' ',result.im:3:0,'i');
END.
Formal:
WITH <recordvariable>{,<recordvariable>} DO
  <block>;
wobei die Datenfelder der in <recordvariable> angegebenen Recordvariablen alleine angegeben werden. Also statt 
x.re := 2;
einfach
WITH x DO
  re := 2;
Das Datenfeld bezieht sich dann auf die nach WITH genannte Variable.

Die Anwendung sieht hier im Beispiel überflüssig aus. Man kann sich aber vorstellen, daß ein reichhaltig mit Datenfeldern ausgestatteter Record viel Schreibarbeit mit sich bringt. Somit ist diese Konstruktion schon eine Hilfe. Allerdings, und das ist meine persönliche Meinung, sollte diese Konstruktion nur sehr sparsam eingesetzt werden, da die Recordvariable nur in der WITH-Zeile steht; man weiß dann im laufenden Programmtext nicht sofort, um welche Variable es sich handelt. Wenn zwei oder mehr Records unterschiedliche Datenfelder haben, kann man auch eine ganze Liste in der WITH-Anweisung unterbringen:

WITH x,y DO
  .....
Sollte in beiden Records jedoch ein Feldname mit gleicher Bezeichnung stehen, ist das Ergebnis undefiniert! Also höllisch aufpassen!

Variantenrecords

Eine der trickreichsten Strukturen in PASCAL ist der Variantenrecord. Von den Puristen als Teufelswerk eingeordnet, kann ein Variantenrecord schon mal geeignetes Werkzeug sein. Allerdings ist hier größte Vorsicht geboten! Man muß genau wissen, was man tut, um nicht in einen "gordischen" Knäuel von logischen Fehlern zu geraten. Ich will hier auch nur die Möglichkeit andeuten. Unter C heißt diese Konstruktion "union".

Deswegen auch nur ein kurzes Beispiel:

PROGRAM varianten_beispiel;
  TYPE status = (male,female);
       person = RECORD
                  name : STRING;
                  CASE sex : status OF
                    male : (beard : boolean);
                    female : (maidenname : STRING);
                END;
  VAR x : person;
      a : char;

BEGIN
  x.name := 'Dampf';
  x.sex := male;
  CASE x.sex OF
    male : BEGIN
             readln (a);
             x.beard := (a = 'J');
           END;
    female : readln (x.maidenname);
  END;
  .
  .
END.
Ja, Sie sehen richtig! In der Deklaration des Variantenrecords fehlt ein END. Das hat seinen Grund. Da pro Record nur ein Variantenteil benutzt werden darf, der auch nur am Ende des Records eingeführt werden darf, hat man sich hier das zusätzliche END gespart. Fehlerquelle!

Wie ist die Bedeutung zu verstehen? Nun, wenn dem Datenfeld "sex" ein "male" zugewiesen werden sollte, dann gibt es ein weiteres Datenfeld "beard" (=Bart) zur Benutzung. Ist "sex" ein "female" zugewiesen, dann gibt es "maidenname" als zusätzliches Feld. "beard" und "maidenname" sind also nur alternativ zu benutzen.

Zu beachten ist, daß das Laufzeitsystem des Compilers sich, jedenfalls im Falle von Turbo PASCAL, nicht darum kümmert, ob man die alternativen Datenfelder richtig benutzt oder nicht. Es liegt also in der Hand des Programmierers, hier schwere Programmierfehler zu vermeiden (oder auch nicht).

Operationen, die von so einem Variantenfeld abhängen, werden deshalb am besten in eine CASE-Anweisung gesteckt, wie im Beispiel gezeigt. Da kann man sie auch am besten überblicken.

Wo ist der Vorteil einer solchen Formulierung? Man spart einfach Speicherplatz! Denn die alternativ benutzten Datenfeldnamen im Variantenteil benutzen denselben Speicherplatz. Will man diese Konstruktion wirklich benutzen, sollte man sich fragen, ob nicht ein paar Bytes mehr heutzutage nicht weniger kosten als schwierig zu entdeckende Programmierfehler.

 

[ zurück | weiter ]
   (c) 2001 Schoenleber.com