====== Strukturen ======
Oft ist es sinnvoll, nicht nur wie in einem Array Daten desselben Datentyps zusammenzufassen,
sondern auch Daten verschiedener Datentypen. Das ist mit Klassen
möglich, die zusammen mit der objektorientierten Programmierung
noch ausführlich behandelt werden. Hier werden (nur) einige Grundbegriffe
in Zusammenhang mit sogenannten **Strukturen** betrachtet.
===== Der Datentyp struct =====
Eine mit dem Schlüsselwert **//struct//** definierte Klasse ist ein **Datentyp**, der auch als
Struktur bezeichnet wird. Die wie Variablen zwischen den geschweiften Klammern
aufgeführten Elemente einer solchen Klasse werden auch als **Datenelemente**
bezeichnet.
**Beispiel 1a:** Der umgangssprachliche Begriff „Kalenderdatum“ steht für drei Werte,
die einen Tag, einen Monat und ein Jahr bezeichnen. Ein solches Datum
kann durch die Klasse //CDatum// mit den Datenelementen //Tag, Monat//
und //Jahr// dargestellt werden:
struct CDatum
{int Tag;
int Monat;
int Jahr;
}; // Das Semikolon ist hier notwendig.
Mit diesem Datentyp kann man wie mit einem der vordefinierten Datentypen
int usw. eine Variable des Datentyps ''CDatum'' definieren:
''CDatum d;''
Gibt man vor dem Semikolon, das eine Klassendefinition abschließt, einen Bezeichner
an, ist dieser eine Variable des zugehörigen Klassentyps. Lässt man den
Namen der Klasse aus, erhält man eine Variable des Klassentyps. Der Datentyp hat
in diesem Fall keinen eigenen Namen.
**Beispiel 1b:** Die Definition
struct CDatum
{int Tag;
int Monat;
int Jahr;
} d; // d ist eine Variable des Datentyps CDatum.
ist gleichwertig mit den beiden Definitionen aus dem letzten Beispiel.
Durch
struct // Dieser Datentyp hat keinen eigenen Namen.
{int Tag;
int Monat;
int Jahr;
} d; // Der Datentyp von d ist anonym
wird nur eine Variable des Klassentyps definiert. Dieser hat aber keinen
eigenen Namen.
Normalerweise wählt man für eine Klasse einen Namen, der genau dem Konzept
entspricht, das sie darstellen soll, wie z.B. Datum für ein Kalenderdatum. Da
dieser Name aber später noch für eine Variable dieses Typs verwendet werden
soll, wurde //CDatum// gewählt. Mit englischen Namen kann man solche Namenskonflikte
durch Groß- und Kleinschreibung umgehen (//Date// für die Klasse und
//date// für eine Variable des Klassentyps).
Eine Zusammenfassung inhaltlich zusammengehöriger Daten zu einer Klasse kann
zur **Verständlichkeit eines Programms** beitragen und ist generell empfehlenswert.
**Beispiel 2:** Die Zusammengehörigkeit und Bedeutung der Daten kommt in
struct CKreis
{int x,y,r;
} k1,k2;
unmittelbar zum Ausdruck. Findet man dagegen die Definitionen
int x1, x2, y1, y2, r1, r2;
in einem Programm, das man nicht selbst geschrieben hat, lassen sich
nur aus der Verwendung der Variablen Rückschlüsse auf ihre Bedeutung
ziehen. Das kann aber bei einem größeren Programm ziemlich
aufwendig werden, insbesondere wenn keine zusätzlichen Kommentare
die Bedeutung der Daten erklären.
Der etwas höhere Schreibaufwand für Strukturen wird durch die Ersparnis an
Kommentaren und die leichtere Verständlichkeit meist kompensiert.
Typische Anwendungen von Strukturen findet man auch in der betriebswirtschaftlichen
Datenverarbeitung. Dabei werden oft die einzelnen Zeilen einer Tabelle
durch eine Struktur dargestellt, die auch als Datensatz bezeichnet wird. Aus
solchen Strukturen werden dann Arrays oder Dateien aufgebaut. Datenbanken sind
im Wesentlichen eine mehr oder weniger große Anzahl von Dateien, die alle aus
solchen Datensätzen bestehen.
===== Verschachtelung von Strukturen =====
**Beispiel 3a:** Eine Zeile der Tabelle
{{:inf:inf8bi_201112:datenstrukturen:bck-240.jpg?600}}
kann für eine Kontobewegung stehen und durch die folgende Struktur
dargestellt werden:
struct Kontobewegung
{int KontoNr;
char NameInhaber[20];
...
double Betrag;
};
Dieser Datensatz enthält mit dem Datum einen weiteren Datensatz. Will man
dieses Datum unter einem eigenständigen Begriff ansprechen, kann man es innerhalb
der Struktur ebenfalls als Struktur definieren:
struct Kontobewegung
{int KontoNr;
char NameInhaber[20];
struct
{int Tag;
int Monat;
int Jahr;
} Datum;
char BewArt;
double Betrag;
};
Die Verschachtelung von Strukturen kann im Prinzip unbegrenzt fortgesetzt
werden. Wenn zuvor ein Name für die Datenstruktur vereinbart wurde, kann auch dieser verwendet werden:
struct Kontobewegung
{int KontoNr;
char NameInhaber[20];
CDatum Datum;
char BewArt;
double Betrag;
};
===== Zugriff auf Datenelemente einer Struktur =====
Eine Variable, deren Datentyp eine Klasse ist, enthält alle Elemente, die bei der
Definition der Klasse angegeben wurden. Diese Elemente werden durch den Namen
der Variablen angesprochen, auf den ein Punkt und der Name des Elements
folgt. Jeder so gebildete Ausdruck ist ein Ausdruck des Datentyps, der bei der
Definition des Elements angegeben wurde.
**Beispiel 3b:** Nach der Definition
Kontobewegung k;
kann man die Elemente der Variablen k folgendermaßen ansprechen:
k.KontoNr // ein Ausdruck des Datentyps int
k.Datum // ein Ausdruck des Datentyps CDatum
Die drei Elemente von //K.Datum// lassen sich einzeln ansprechen durch
k.Datum.Tag // ein Ausdruck des Datentyps int
k.Datum.Monat
k.Datum.Jahr
Für den Compiler wird durch jede Definition einer Klasse ein neuer Datentyp
erzeugt. Deshalb werden durch die beiden Klassendefinitionen in
struct { int i;} s1;
struct { int i;} s2;
zwei verschiedene Datentypen erzeugt, obwohl man auch erwarten könnte, dass
die Datentypen von //s1// und //s2// gleich sind. Da die Datentypen von s1 und s2
verschieden sind, verweigert der Compiler die Übersetzung der Zuweisung
s1=s2; // Fehler: Konvertierung nicht möglich
Verwendet man dagegen denselben Klassennamen bei der Definition von Variablen,
haben sie denselben Datentyp und können einander zugewiesen werden. Nach
der Definition
Kontobewegung k1;
Kontobewegung k2;
wird die folgende Zuweisung vom Compiler akzeptiert:
k1=k2;
----
[[.:strukturen:Aufgaben Strukturen]]