4. Typen und Datenstrukturen
 
zurück
4.3.1.1 Aufzählungstypen


Aufzählungstypen (enumeration_type_definition <BNF>) definieren eine geordnete Menge von Werten, welche durch Bezeichner oder Zeichenliterale repräsentiert werden. Die Ordnung ist durch die Aufschreibungsreihenfolge gegeben.


Beispiel:
-- Beispiele für Typdeklarationen mit Aufzaehlungstypen
type FARBE is (ROT, GELB, GRUEN, BLAU);
type ZUSTAND is (AKTIV, NICHT_AKTIV);
type OPERATOR is ('+', '-', '*', '/', MODULO, REMAINDER);
type HEX_ZIFFER is('0', '1', '2', '3', '4', '5', '6', '7','8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );

-- nicht erlaubt dagegen ist
type ZAHLEN is ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10');
-- da '10' kein Zeichenliteral bzw Bezeichner ist


Für Ausdrücke von Aufzählungstypen sind relationalen Operationen ("=","/=","<", ">", "<=", ">=") und die Zugehörigkeitsoperationen "in" und "not in" anwendbar.


Wie für alle diskreten Typen existieren auch bei den Aufzählungstypen die Attribute  'First (untere Grenze),
'Last (obere Grenze), 'Pred (Vorgänger) und 'Succ (Nachfolger).

Die nachfolgenden Beispiele für Attribute beziehen sich auf folgende Typvereinbarung

type Wochentag is (Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Sonnabend, Sonntag);
Wochentag'First = Montag;
Wochentag'Last = Sonntag;
Wochentag'Pred(Sonntag) = Samstag;
Wochentag'Succ(Samstag) = Sonntag;


Die Ausdrücke Wochentag’Pred(Montag) und Wochentag’Succ(Sonntag) führen zur Auslösung von Constraint_Error.

Das Attribut Width gibt die maximale Anzahl von Zeichen eines Literals des Aufzählungstyps an.
Beispielsweise liefert Wochentag'Width den Wert 10, da das Literal Donnerstag die maximale Länge von 10 Zeichen liefert.

Durch die Deklaration wird eine Reihenfolge festgelegt, die durch Ordnungszahlen charakterisiert wird. Diese Zahlen sind die interne Repräsentation der Aufzählungsliterale und werden in der Regel vom Ada-Übersetzer von 0 aufsteigend vergeben. Auf diese Zahlen kann durch das Attribut Pos zugegriffen werden.

Es gilt z. B.:

Wochentag'Pos(Montag) = 0, Wochentag'Pos(Sonntag) = 6


Dem Attribut Pos ist das Attribut Val zugeordnet, mit dem man aus der Ordnungszahl das Aufzählungsliteral bestimmen kann,
z. B.:

Wochentag'Val(0) = Montag,
Wochentag'Val(6) = Sonntag.


Wochentag'Val(7) erzeugt einen Constraint_Error.

Weiterhin existieren die beiden Attribute Image und Value für die Umwandlung zwischen den Aufzählungsliteralen und Zeichenketten.

Wochentag'Image(Montag) = "MONTAG",
Wochentag'Value("MONTAG") = Montag


Zu beachten ist, daß ‘Value und ‘Image die Literale in Großbuchstaben verarbeiten. Natürlich kann in ‘Value durch Eingabe einer entsprechenden Zeichenkette Constraint_Error ausgelöst werden.

Interne Repräsentation/ Repräsentationsklauseln


Durch die Deklaration wird eine Reihenfolge festgelegt, die durch Ordnungszahlen charakterisiert wird. Diese Zahlen sind die interne Repräsentation der Aufzählungsliterale und werden in der Regel vom Ada-Übersetzer von "0" aufsteigend vergeben.

Diese Abbildung der Aufzählungsliterale auf natürliche Zahlen beginnend bei 0, die vom Übersetzer automatisch vorgenommen wird, kann vom Programmierer durch Repräsentationsklauseln verändert werden. Wem nicht gefällt, daß dem Montag eine 0 entspricht, kann schreiben:

for Wochentag use ( Montag => 1,
  Dienstag => 2,
  Mittwoch => 3,
  Donnerstag => 4,
  Freitag => 5,
  Samstag => 6,
  Sonntag => 7);


In Sprachen, die keine Aufzählungstypen kennen, bilden Programmierer solche häufig durch die Deklaration verschiedener ganzzahliger Variablen (oder Konstanten) ab. Dabei entspricht eine Variable einem Aufzählungsliteral. (Z. B. bildet das Application Programming Interface von Windows, das in C geschrieben ist, Aufzählungstypen so ab, obwohl C die Typklasse ENUM kennt.)

Besonders bei hardwarenaher Programmierung ist es oft nötig, die Repräsentation von Aufzählungsliteralen explizit anzugeben, nicht um die Programmlogik von der internen Kodierung abhängig zu machen, sondern um eine abstrakte Abbildung der von der Hardware benutzten ganzzahligen Kodierung zu erhalten.


Beispiel:

Als Beispiel soll eine Basisroutine eines Betriebssystems betrachtet werden, die die Eingabe und Ausgabe an eine bestimmte Adresse auf der Festplatte durchführen soll und dazu ein Statusbyte zurückgibt, das anzeigt, ob die Operation erfolgreich war. Alle acht Bits sollen auf 0 gesetzt sein, wenn die Operation erfolgreich ausgeführt wurde. Anderenfalls wird genau ein Bit auf 1 gesetzt, um eine spezielle Fehlersituation anzuzeigen.

Bit 0: Schreibschutzverletzung
Bit 1: Festplatte nicht bereit
Bit 2: Lesefehler
Bit 3: Spur nicht gefunden
Bit 4: Sektor nicht gefunden
Bit 5: Schreibfehler
Bit 6: Fehlerhafte Festplattenadresse
Bit 7: Hardwarefehler

Nun soll eine Routine geschrieben werden, die dieses Statusbyte nach jeder Lese-/Schreib-operation der Basisroutine untersucht. Anstatt die neun möglichen Bitmuster zu untersuchen, wird ein neunwertiger Aufzählungstyp mit einer Repräsentationsklausel deklariert, die das Bitmuster jedes der neun Literale festlegt. Danach kann man die Statusinformation als zu einem Aufzählungstyp gehörig betrachten und braucht sich nicht mehr um die ganzzahlige Kodierung zu kümmern. Die Information kann dann z. B. in einer Case-Anweisung verarbeitet werden. Die allgemeine Form einer Repräsentationsklausel für einen Aufzählungstyp lautet:

for Enumeration_Type_Name use Array_Aggregate;


Das Aggregat entspricht dem eines eindimensionalen Reihungstyps, das durch die Werte des Aufzählungstyps so indiziert wird, daß der Aufzählungswert x den internen Wert für x festlegt. Die Werte des Aggregats können positional oder durch Namen angegeben werden. Die ganzzahligen Werte müssen statische Ausdrücke vom Typ Universal_Integer sein.

Für das Beispiel kann die Deklaration wie folgt aussehen:

type Platten_Status is( Normal,
  Schreibschutzverletzung,
  Nicht_bereit,
  Lesefehler,
  Spurfehler,
  Sektorfehler,
  Schreibfehler,
  Adressfehler,
  Hardwarefehler);


for Platten_Status use( Normal => 2#0000_0000#,
  Schreibschutzverletzung => 2#0000_0001#,
  Nicht_bereit => 2#0000_0010#,
  Lesefehler => 2#0000_0100#,
  Spurfehler => 2#0000_1000#,
  Sektorfehler => 2#0001_0000#,
  Schreibfehler => 2#0010_0000#,
  Adressfehler => 2#0100_0000#,
  Hardwarefehler => 2#1000_0000#);


Hier werden die internen Werte zur Basis 2 geschrieben, was die Abbildung der Bitmuster verdeutlicht. Weniger klar hätte die Deklaration auch wie folgt notiert werden können:

for Platten_Status use (0, 1, 2, 4, 8, 16, 32, 64, 128);


Dieses Beispiel zeigt, daß die Kodierung eines Aufzählungstyps lückenhaft sein kann. Dadurch kann die Auswertung der Attribute 'Pred, 'Succ und 'Pos langsamer werden. Auch kann sich der für Variable des Aufzählungstyps nötige Speicher vergrößern. Ohne die Repräsentationsklausel könnte eine Implementierung die neun verschiedenen Werte durch vier Bits abbilden. Bei der obigen Deklaration sind 8 Bits nötig, und man sollte eine Größenklausel der Art

for Platten_Status'Size use 8;


zwischen der Deklaration von Platten_Status und der Repräsentationsklausel einfügen.


 
zurück
 Index   Ada Tour - Dokumentation  
© 2003 Förderverein Ada Deutschland e.V.