IT-Academy Logo
Sign Up Login Help
Home - Programmieren - C++ - Arrays2 (Strukturen und benutzerdefinierte Datentypen)



Arrays2 (Strukturen und benutzerdefinierte Datentypen)

Nach dem ersten Artikel, der sich noch mit den 'Basics' der Arrays beschäftigte, steigen wir jetzt voll in die Materie ein und programmieren schon Teile von Personalverwaltungen und beinahe komplexe Datenbanken mit der Hilfe von Array-Strukturen.


Autor: Peter Schmitz (dav133)
Datum: 01-02-2006, 23:58:17
Referenzen: Wissen aus dem Informatikunterricht
Schwierigkeit: Fortgeschrittene
Ansichten: 6425x
Rating: 10 (1x bewertet)

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



Arrays2 (Strukturen und benutzerdefinierte Datentypen)

Ein weiterer wichtiger Punkt sind die Strukturen, da diese eine stark vereinfachte Möglichkeit darbieten, mehrere Informationen konzentriert zu verarbeiten.
Datenverbund: struct

Strukturen sind benutzerdefinierte Datentypen. Während Arrays nur Elemente des gleichen Datentyps beinhalten, besteht eine Struktur aus einer Zusammenfassung von verschiedenen - aber vorher festgelegten - Datentypen. Dies ermöglicht, logisch zusammengehörende Daten zusammenzufassen, obwohl sie nicht vom selben Datentyp sind.
Die Struktur entspricht einem Record der Sprache Pascal.
Strukturen werden bei der Deklaration durch das Schlüsselwort struct gekennzeichnet. Diesem folgt der Name der Struktur und dann - in geschweiften Klammern - eine Liste der einzelnen Variablen, aus denen die Struktur besteht.
Die Syntax der Struktur-Deklaration sieht also folgendermaßen aus:

struct Typname {  Strukturaufbau } Variablenliste ;


Typname und Variablenliste müssen nicht sein.
Typname sollte aber sein, da eine Struktur ohne Namen im weiteren Programmverlauf nicht mehr ansprechbar ist; nur die bei der Deklaration gleich definierten Strukturvariablen sind verwendbar.
Die Strukturvariablen müssen nicht gleich bei der Deklaration mit vereinbart werden, denn mit einem vorhandenen Strukturnamen kann man dies jederzeit, bei bedarf, durchführen.

Genug der Sprüche, ein Beispiel soll die Verwendung deutlich machen. In der Personalabteilung einer Firma finden wir z.B. folgenden zusammenhängenden Aufbau :
struct
{
	long	PersNr;
	short	Geburtsjahr;
	double	Gehalt;
	char	Wohnort[25];
	char	Strasse[25];
} Otto, Anton , Eva, Maria;			// Semikolon beendet hier
						// Deklaration + Definition in einem Stück
oder
struct  Personal
{
	long	PersNr;
	short	Geburtsjahr;
	double	Gehalt;
	char	Wohnort[25];
	char	Strasse[25];
};						// Semikolon beendet Deklaration 
						// des Typs Personal

Personal		Otto, Anton , Eva, Maria;		// hier erfolgt die Definition von
4 Variablen
						// des Typs Personal


Mit der Struktur wird ein neuer (selbst gebastelter) Datentyp erzeugt, der aus einzelnen Strukturelementen besteht (Hier: PersNr, Geburtsjahr,....). Eine Struktur hilft also die Übersichtlichkeit in einem Programm zu wahren und erleichtert darüber hinaus auch den Umgang mit den Daten, wie wir noch sehen werden.

Im ersten Fall wird die Struktur ohne Typnamen (Strukturnamen) deklariert. Da aber gleich mit der Deklaration eine Variablenliste definiert wird, kann man diese Variablen namens Otto, Anton, Eva und Maria auch benutzen; im weiteren Verlauf aber keine neuen Variablen mehr definieren.

Im zweiten Fall wird eine reine Deklaration vorgenommen, die auch den Typnamen (Strukturnamen) enthält. Damit sind noch keine Variablen zur Verwendung der Struktur bereitgestellt; also ist bis dahin auch noch kein Speicher reserviert worden. Lediglich die 'Bekanntmachung' der Struktur (=Deklaration) wird, bis zum abßenden Semikolon hinter der Klammer, durchgeführt. Die Definition der Variablen und damit auch die Speicherbereiterfolgt an einer (u.U. ganz) anderen Stelle mit Datentyp und Variablennamen - wie sonst auch.

Personal Otto, Anton, Eva, Maria;

Der Vorteil der 2. Version liegt auf der Hand. Da ein neuer Typ mit Namen (Personal) eingeführt wurde, besteht jederzeit im Programmverlauf die Möglichkeit weitere Variablen zu definieren.

Bevor wir zur Verwertung der Strukturvariablen kommen, noch etwas zur Deklaration.
Obige Deklaration legt z.B. fest, dass ein Datentyp long , ein short, ein double,....... vorkommt. Da die Datentypen der Struktur hintereinander im Speicher abgelegt werden, benötigt jede Variable des Typs Personal eine gleich große Speichergröße.

Diese können Sie einzeln addieren (long = 4 Byte, short=2 Byte, ....), oder Sie ermitteln ganz einfach die Größe des Datentyps mit der Funktion sizeof.
Im übrigen bieten Compiler i.d.R. eine Einstellungsmöglichkeit (Option), ob eine Ausrichtung auf gerade Adressen erfolgen soll. Eine Ungerade tritt z.B. dann auf, wenn ein Strukturelement vom Typ char variable[x] in x eine ungerade Zahl stehen hat. Sie sollten allerdings beachten, dass Sie bei 2 Programmen die auf die gleiche Struktur zugreifen, z.B. einmal schreibend und das andere lesend, mit der gleichen Einstellung (gerade/ungerade) Compilieren. Wenn nicht könnten Sie ein kleines Chaos produzieren.

Der Zugriff auf die struct-Variablen erfolgt mittels Struktur-Operator (auch Punkt-Operator genannt); also einem Punkt zwischen Variablennamen und Elementnamen.

Variablenname.Elementname

Für obiges Beispiel könnte es so aussehen:
Otto.PersNr =12345L ;
Maria.Geburtsjahr = 1977 ;
Anton.Gehalt = 3125.25 ;
strcpy(Eva.Wohnort, "München") ;
strcpy(Otto.Strasse, "Mühlenstraße 33");

Es besteht auch die Möglichkeit, die char-Felder mit einzelnen Buchstaben zu belegen. Diese (Umstands-)Methode erfolgt in gleicher Art und Weise, wie wir es bei Zeichenketten schon mal kennengelernt haben;NUR mit vorangestelltem Variablennamen (man muss wissen WER gemeint ist) und dem Punkt-Operator (WELCHES Element von der Variablen). Also:

Eva.Wohnort[0] = 'M';
Eva.Wohnort[1] = 'ü';
Eva.Wohnort[2] = 'n';
......
.....
.....
Eva.Wohnort[7] = '\0';


Strukturen lassen sich auch schachteln. Hierzu sei das obige Beispiel struct Personal dahingegen geändert, dass nicht nur das Geburtsjahr, sondern das komplette Geburtsdatum (Tag, Monat, Jahr) verwendet werden soll. Da man davon ausgehen kann, dass die Kombination Tag-Monat-Jahr öfter vorkommen kann, bietet es sich an, hierfür eine extra Struktur anzulegen. Diese Struktur, hier als Typ Datum bezeichnet, lässt sich dann in vielen Strukturen und auch Programmteilen verwenden (Prinzip der Wiederverwertung).
struct Datum
{
	short Tag, Monat, Jahr;
};

struct  Personal
{
	long	PersNr;		// wie zuvor
	Datum 	GebDatum;	// In Struktur Datum mit dem Variablennamen GebDatum geändert
	double	Gehalt;		// wie zuvor ....
	char	Wohnort[25];
	char	Strasse[25];
};						// Semikolon beendet Deklaration 
						// des Typs Personal

Personal		Otto, Anton , Eva, Maria;		// hier erfolgt die Definition von
4 Variablen
						// des Typs Personal


Der in der Struktur eingesetzte Datentyp muss (bei der Verwendung) bekannt sein. Wenn also in struct Personal, eine Struktur Datum verwendet wird (geschachtelt), dann ist die Struktur Datum vorher zu deklarieren damit der neue Datentyp überhaupt besteht (bekannt ist).

Der Zugriff erfolgt nach den gleichen Regeln wie bisher, nur besteht hier eine Struktur in einer Struktur (deshalb verschachtelt), so dass die Qualifizierung - also die Auswahl der gewünschten Strukturkomponente - mittels Punkt zweimal vorkommen muss. Dementsprechend könnte die Programmierung eine Ausgabe auf den Bildschirm mit obigem Beispiel folgendes Aussehen haben :
cout  	<<  "Der Geburtstag von Maria : "
	<<  Maria.GebDatum.Tag   	<<  "."
	<<  Maria.GebDatum.Monat	<<  "."
	<<  Maria.GebDatum.Jahr		<<  endl ;
wenn z.B. zuvor die Daten-Eingabe in dieser Art vorgenommen wurde:
Maria.GebDatum.Tag = 10 ;
Maria.GebDatum.Monat = 2 ;
Maria.GebDatum.Jahr = 1978 ;

Auch bei Strukturen besteht die Möglichkeit, die Struktur mit Werten vorzubesetzen (zu initialisieren). Dies soll an einem einfachen Beispiel - in 2 Versionen - demonstriert werden.

Version 1: Kein Strukturname und eine einzige Strukturvariable im Programm
struct
{
	short  	tag;
	char	monat[[10];
	short	jahr;
}jahrestag = { 1, "Januar", 1997 } ;


Die Strukturvariable jahrestag wird - in geschweiften Klammern - initialisiert; die Werte der einzelnen Strukturelemente sind durch Kommata getrennt.

Version 2: Die (gleiche) Initialisierung erfolgt erst nachträglich bei der Definition einer Strukturvariablen und nicht schon in Verbindung mit der Deklaration der Struktur
struct Datum
{
	short  	tag;
	char	monat[[10];
	short	jahr;
};						//  Deklaration der Struktur

Datum  jahrestag = { 1, "Januar", 1997 } ;		//  Definition einer Variablen mit
Initialisierung

Auch verschachtelte Strukturen können initialisiert werden; z.B:
struct Datum
{
	short Tag, Monat, Jahr;
};
struct  Name
{
	char	Vorname[20];
	char	Zuname[30];
};						
struct  Personen
{
	Datum 	GebDatum ;	// In Struktur Personen ist Struktur Datum eingebettet
	Name	Person ;		// In Struktur Personen ist Struktur Name eingebettet
};

// jetzt erfolgt die Definition von 2 Variablen vom Typ Personen; mit gleichzeitiger Initialisierung

Personen	P1 = { {26, 7, 1940}, {"Karl", "Baumann"} },	// gut strukturiert
		P2 = { 24, 5, 88, "Hein", "vom Deich" } ;		// schlecht strukturiert !!

Auch ein komplettes oder teilweises kopieren ist bei Strukturen einfach möglich:
// Struktur nach vorhergehendem Aufbau
struct Personen 	Peter = 	{	{13, 4, 1977},
				{"Peter-Paul", "Bspname"} 
			}, 
		Paul, Person3;	// Drei Variable vereinbart, davon eine initialisiert
.....
....
Paul = Peter ;			// kopiert ganze (mit Werten belegte) Struktur Peter in Struktur
Paul
Person3.Person = Peter.Person ;	// kopiert nur eine Unterstruktur (struct Name) von Peter in Person3

Varianten: union

Ein kleines Feature, mit dem man manchmal etwas Speicherplatz sparen kann ; aber wer spart heute noch, und dann noch ausgerechnet Speicherplatz. Es handelt sich um eine Variante der Struktur.
Wenn man sich ein struct aus mehreren Daten vorstellt, so werden diese nacheinander im Speicher abgelegt. Der Unterschied einer union besteht darin, dass die einzelnen Komponenten der Union nicht hintereinander im Speicher liegen, sondern quasi übereinander. Die Größe des Speicherbedarfs ,und damit die Länge, richtet sich bei der Union nach der Länge der längsten Komponente.

Gehen wir von folgendem Beispiel aus:
union					Die 3 Komponenten der union
{					beisp.i  ,  beisp.c  ,  beisp.d
	short	i;			nehmen denselben Speicherplatz ein !
	char	c;
	double	d;
}beisp;					// Union-Variable namens beisp

Die Größe des Speicherbedarfs richtet sich nach dem längsten Element.
Da die Datenstruktur union nur sehr selten verwendet wird, soll hier auf weitere Beispiele eingegangen werden. Sie kann allerdings durchaus auch innerhalb von Strukturen verschachtelt vorkommen.
Aufzählungstyp: enum

Häufig gibt es nicht-numerische Wertebereiche, denen man gerne für bestimmte Aufgaben Zahlenwerte zuordnen würde. Denkt man nur an die Wochentage: Montag, Dienstag ......., Sonntag.
Die Lösung für solche Fälle sind die Aufzählungs- oder Enumerationstypen.

Eine Variable vom Typ enum kann nur die Werte annehmen, die bei der Definition des Aufzählungstyps angegeben wurden. Dabei werden Aufzählungstypen bei der Deklaration durch das Schlüsselwort enum gekennzeichnet. Diesem folgt der Typname der Enumeration und dann - in geschweiften Klammern - eine Liste der einzelnen Aufzählungen, aus denen der Enumerationstyp bestehen soll. Eine Variablenliste kann noch folgen.
Die Syntax der enum-Deklaration sieht also folgendermaßen aus:

enum Typname {  Aufzählung } Variablenliste ;


Typname und Variablenliste müssen - wie bei Strukturen - nicht sein.

Beipiel Deklaration:

enum Wochentage
{
	Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag
};


Wenn der Datentyp bekannt ist (hier: Wochentage), können weitere Variablen definiert werden:

Wochentage	feiertag, werktag,		// Variablendefinition
		heute = Dienstag;		// Definition mit Initialisierung des 'Wertes 2'
für Dienstag !


Was soll das Ganze ? Nun, den mit Hilfe von Aufzählungstypen definierten Variablen können ausschließlich Werte aus der zugehörigen Aufzählung zugewiesen werden. Und welche Werte werden durch die Aufzählung repräsentiert:

Intern werden Aufzählungstypen durch ganze Zahlen dargestellt, wobei die Zählung mit 0 beginnt.

Falls der Enumerationstyp nur 1x in einer Variablendefinition benötigt wird, kann der Typname entfallen; die anonyme Typdefinition könnte folgendermaßen aussehen:
enum { rot, gruen, blau } Grundfarbe;	// Variablendefinition => Grundfarbe
oder
enum { fahrrad, roller, moped, pkw, lkw , bus, zug} Fahrzeug;		// Variable => Fahrzeug

Es besteht wie bei Strukturen auch die Möglichkeit, Deklaration und Definition zu kombinieren. Eine nicht anonyme Ausführung könnte z.B. so gestaltet sein :

enum BOOL {FALSE, TRUE } Fehler, Programmende;


Hier wird der Datentyp BOOL und die Variablen Fehler und Programmende definiert, wobei FALSE den Zahlenwert 0 und TRUE den Zahlenwert 1 darstellt.

Gelegentlich kann es vorkommen, dass man Aufzählungen für bestimmte Kodierungen benutzen möchte, die nicht der internen Ganzzahlreihenfolge 0, 1,.... entsprechen. Auch dies ist möglich:

Man kann die vorgegebene interne Numerierung der enum-Werte (0, 1,....) durch explizite Wertangaben überschreiben (Ganzzahlen).
Beispiele:
enum Farbe { rot, gruen = 5, gelb, blau , weiss = 15, schwarz };
	beinhaltet : rot Þ 0 ; gruen Þ 5 ; gelb Þ 6 ; blau Þ 7 ; weiss Þ 15 ; schwarz Þ 16
enum Interrupts { Video = 0x10, Reset = 0x19, MSDOS = 0x21, User1 = 0x80 };
	beinhaltet : Video Þ 16 ; Reset Þ 25 ; MSDOS Þ 33 ; User1 Þ 128

Wenn noch Klärungsbedarf zur Artikelserie besteht, zögern Sie nicht, einen Kommentar zu verfassen.

Zusammenfassung
  • Bei Strukturen handelt es sich um benutzerdefinierte (selbst festgelegte) Datentypen, die zusammengehörende Informationen verschiedenen Typs zusammenfassen.
  • Strukturen werden bei der Deklaration durch das Schlüsselwort struct gekennzeichnet , gefolgt vom Namen des neuen Datentyps (Strukturname) und -in geschweiften Klammern- dem Strukturaufbau.
  • Strukturen können auch geschachtelt aufgebaut werden. Strukturgrößen sind leicht über den Operator sizeof zu ermitteln.
  • Strukturvariablen können gleich bei der Deklaration vereinbart werden; auch eine Gesamt-Initialisierung ist möglich.
  • Der Punkt zwischen Variablennamen und Elementname dient beim Zugriff als Auswahl-Operator für das gewünschte Element.
  • Das Kopieren kompletter (selbst verschachtelter) Strukturen bzw. kompletter Unterstrukturen ist überaus einfach.
  • Unions sind Strukturen, in denen verschiedene Elemente denselben Speicherbereich bezeichnen. Sie sind nur in Sonderfällen einzusetzen.
  • Die Variablen von Aufzählungs- oder Enumerationstypen (enum) können nur die Werte annehmen, die bei der Definition des Aufzählungstyps angegeben wurden.
  • Intern werden Aufzählungstypen durch ganze Zahlen dargestellt, wobei die Zählung mit 0 beginnt. Diese vorgegebene interne Numerierung kann durch explizite Wertangaben bei der Definition überschrieben werden.
Aufgabe
  • Erstellen Sie eine Struktur, welche einen Bildschirmpunkt repräsentiert. Dabei sollen die Werte
    Sichtbar (ja/nein), Farbummer, X-Koordinate und Y-Koordinate repräsentiert sein.
Lösung

//---------------------------------------------------------------------------

#pragma hdrstop
#include 


//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{

struct Bildschirmpunkt
{
short koordinateX;
short koordinateY;
char farbnummer[10];
bool sichtbarkeit;
};
Bildschirmpunkt Punkt1; // beliebige Punkte hinzufügen


Punkt1.koordinateX=512;
Punkt1.koordinateY=256;
strcpy(Punkt1.farbnummer,"#FFFFFF");
Punkt1.sichtbarkeit=1;


return 0;
}
//---------------------------------------------------------------------------


[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04508
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06246
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1154
Comments: 0