Arrays

Einführung

Ein Array (Feld) ist mit einer Variable mit einer bestimmten Anzahl von Elementen zu verstehen. Angenommen Sie wollen in einem Programm den Klassenspiegel einer Klasse festhalten, mit den Noten von 1 bis 6. Sie könnten nun 6 Variablen deklarieren, welche die Anzahl einer jeden Note beschreibt.

unsigned short mark_1, mark_2, mark_3, mark_4, mark_5, mark_6;

Bei 6 verschiedenen "Noten" ist dies vielleicht noch zu überblicken. Stellen Sie sich jedoch einmal vor Sie wollen das Alter von beispielsweise 100 Clubmitgliedern festhalten. Natürlich könnten sie 100 Variablen deklarieren, aber ich denke das Problem wird offenkundig.

Zu diesem Zweck lassen sich Arrays verwenden. Auf diese Weise lassen sich praktisch eine ganze Liste von Variablen in einer zusammenfassen. 

Deklaration

Um das Beispiel mit den Noten noch einmal aufzugreifen, als Arraydeklaration würde dies so aussehen:

unsigned short marks[6];

Die 6 steht einfach nur für die Anzahl der Elemente. Unser zweites Beispiel ließe sich dann so realisieren:

unsigned short ages[100];	//das jeweilige Alter von 100 Mitgliedern

Allgemein sieht das so aus:

<Datentyp> <Feldname>[<Anzahl>];

Es werden also einzelne Deklarationen zusammengefasst. 

Initialisierung

Man kann jedes Element einzeln initialisieren. Dazu verwendet man den Feldnamen zusammen mit einem Index in eckigen Klammern eingeschlossen. Dies gilt sowohl für den Lese- als auch für den Schreibzugriff. ACHTUNG: Das erste Element in einem Array besitzt nicht den Index 1 sondern 0. Das heißt, wenn sie die Anzahl der 6en festlegen wollen, schreiben sie nicht etwa:

marks[6]

sondern

marks[5]	//für das 6te Element

Der Index für die 2en wäre demnach 1. Sollten sie den Bereich eines Arrays überschreiten, wird ihr Programm entweder abstürzen oder unter Umständen unmögliche Werte liefern, und einen solchen Fehler später ausfindig zu machen ist nicht unbedingt einfach. Wollen Sie nun also die Anzahl der 6en festlegen, dann machen Sie dies wie folgt (angenommen die Klasse ist eine der besseren und schreibt keine 6en ;-D):

marks[5] = 0;

Von nun an ist das letzte, das 6. Element mit 0 belegt. Wollen Sie diesen Wert nachher ausgeben, so könnte dies wie folgt aussehen:

cout << marks[5] << " Schüler haben eine 6" << endl;

Wollen Sie nun die Anzahl der Schüler, welche eine 1 haben vom Benutzer eingeben lassen, so könnten Sie dies wie folgt tun:

cout << "Wieviele Schüler haben eine 1? " << endl;
cin >> marks[0];

Sind Ihnen die Werte schon bei der Deklaration bekannt, so können Sie den Array folgendermaßen initialisieren:

unsigned short marks[6] = {2, 4, 6, 3, 1, 0};

Da durch die Initialisierung durch die Werte innerhalb der geschweiften Klammern, die Dimension des Arrays bereits festgelegt ist, kann man die Anzahl der Elemente bei der Deklaration auch weglassen:

unsigned short marks[] = {2, 4, 6, 3, 1, 0};

Allgemein sieht das dann so aus:

<Datentyp> <Feldname>[] = { <Wert_1>, <Wert_2>, (...), <Wert_n>};

Als Datentypen sind soweit alle erlaubt, also auch Zeiger aber keine Referenzen. 

Zeiger und Arrays

Am Ende der letzten Lektion wurde erwähnt, dass ein Array mit Zeigern einiges zu tun hat. Nun die Auflösung: Ein Array lässt sich ganz einfach als Zeiger auf das erste Element verstehen. Erstellen wir nun einen Zeiger welcher auf den Array zeigt, dann haben folgende Anweisungen die gleiche Funktion:

unsigned short *p = &marks[0];

oder

unsigned short *p = marks;

Weiterhin ist es möglich auf alle Elemente mit Hilfe des Zeigers zuzugreifen. Dies ist mit Hilfe verschiedener Wege zu realisieren. Der deutlichste ist wohl folgender:

marks[<index>] 

entspricht

p[<index>];

'p[0]' wäre demnach 2. Man kann jedoch auch mithilfe des Zeigers folgendermaßen auf ein jedes Element zugreifen:

*(p + <index>);

Dies ist gleichbedeutend mit 'p[<index>]'. Grundsätzlich ist dies Geschmackssache. Das eine Arrayvariable mit einem Zeiger auf das erste Element zu vergleichen ist, lässt sich auch an folgender Notation erkennen:

marks[<index>] entspricht *(marks + <index>)

Es lässt sich außerdem ein Zeiger konstruieren, der nicht auf das erste Element (Index null), sondern auf jedes beliebige Element zeigt. Angenommen man möchte einen Zeiger 'p' erstellen, der auf das Element mit dem Index 'm' eines Arrays 'Arr'  zeigt, dann ließen sich folgende Aufrufe verwenden:

p = &Arr[m];

oder

p = Arr + m;

Dieser Zeiger lässt sich dann wie gewohnt verwenden. Ein Aufruf von 'p[n]' (bzw. '*(p + n)') wäre gleichbedeutend mit einem Aufruf von 'Arr[m + n]' (bzw. '*(Arr + m + n)' . Es ist natürlich darauf zu achten, dass bei diesen Operationen die ursprünglichen Arraygrenzen nicht überschritten werden. Der Zeiger 'p' lässt sich im Prinzip wie ein eigener Array verwenden. Veränderungen an diesem "Array" haben dann aber unmittelbare Folgen an dem "richtigen" Array.

Bestimmen der Größe eines Arrays

Mit dem Operator 'sizeof' lässt sich die Größe in Bytes eines Datentyps oder einer Variablen bestimmen. Beispielsweise wären folgende Aufrufe möglich:

size = sizeof(int);	//size = 4;
size = sizeof(char);	//size = 1;
size = sizeof(char*);	//size = 4;

int i, *pi, Arr[50];
size = sizeof(i);	//size = sizeof(int) = 4;
size = sizeof(pi);	//size = sizeof(int*) = 4;
size = sizeof(Arr);	//size = 50 * sizeof(int) = 200;

Möchte man nun die Länge eines Arrays 'Arr' beliebigen Datentyps bestimmen, so funktioniert dies wie folgt:

length = sizeof(Arr) / sizeof(Arr[0]);

Da der Array aber statisch angelegt wird und die Länge konstant ist, wird die Länge dem Programmierer wohl bekannt sein. Entscheidender ist die Möglichkeit mithilfe des 'sizeof'-Operators die Größe in Bytes einer Variablen oder eines Datentyps zu bestimmen. Dies kann für die folgenden Funktionen von Nützen sein.

Übrigens: Die Größe eines Zeigers egal welchen Datentyps ist immer vier Bytes. Dies ist auch der Fall wenn der Zeiger auf ein Array mit mehreren Elementen zeigt. Dies wird an folgendem Beispiel verdeutlicht:

int Arr[50];
int *pArr = Arr;

size = sizeof(Arr);	//size = 50 * sizeof(int) = 200;
size = sizeof(pArr);	//size = sizeof(int*) = 4;

Immer wenn man Byteangaben bei Funktionen machen muss, dann sollte man den Operator 'sizeof' verwenden, selbst wenn die Größe bekannt ist.

Funktionen für den Umgang mit Arrays

Es existieren vor allem in der Datei "memory.h" nützliche Funktionen um Arrays zu initialisieren und Speicher zu kopieren.

Array initialisieren:

Wird ein Array deklariert, dann sind seine Daten rein willkürlich. Mit der Funktion 'memset' können die Daten einheitlich mit einem festgelegten Wert initialisiert werden. Sinnvoll wäre z.B. alle Elemente auf null zu setzen. Angenommen 'Arr' ist der Array 'uiSize' ist die Größe des Arrays in Bytes, dann lässt sich der gesamte Array wie folgt auf null setzen:

memset(Arr, 0, uiSize);

Da sich die Größe mithilfe des 'sizeof'-Operators bestimmen lässt, kann man die Methode auch wie folgt ausführen:

memset(Arr, 0, sizeof(Arr));

Es muss natürlich nicht unbedingt der gesamte Array auf null gesetzt werden. Denkbar wäre z.B., dass nur die ersten 'cBytes' ('cBytes <= uiSize') initialisiert werden. Der Aufruf sähe dann wie folgt aus:

memset(Arr, 0, cBytes);

Speicher von einem Array in den andern kopieren:

Oft sollen Daten von einem Array in den anderen kopiert werden. Für diesen Zweck wird die Methode 'memcpy' bereitgestellt. Angenommen von einem Array 'Arr1' sollen die ersten 'cBytes' in einen weiteren Array 'Arr2' kopiert werden. Der entsprechende Aufruf lautet wie folgt:

memcpy(Arr2, Arr1, cBytes);

Angenommen die beiden Arrays sind vom Datentyp 'int' und es sollen die ersten 'cElements' Elemente kopiert werden. Der entsprechende Aufruf würde wie folgt aussehen:

memcpy(Arr2, Arr1, cElements * sizeof(int));

Mehrdimensionale Arrays

Es lassen sich auch mehrdimensionale Arrays erstellen. Angenommen Sie wollen ein Kreuzworträtsel mit 50 x 50 Kästchen programmieren. Sie könnten dann auf jedes Element zugreifen indem Sie Reihe und Spalte angeben. Sie benötigen demnach 2 Angaben. Die Deklaration sieht wie folgt aus:

unsigned char field[50][50];             

Wenn Sie die erste Angabe als die Reihe und die zweite als die Spalte festgelegt haben, könnten sie folgendermaßen auf das Kästchen in der n. Reihe und der m. Spalte zugreifen (Zählung von 0 beginnend):

field[n][m];

Sie können dies natürlich noch auf den 3-dimensionalen oder gar den 4-dimensionalen Raum ausweiten. Dazu brauchen sie nur weitere Dimensionsangaben anfügen. Auf weitere Beispiele verzichte ich an dieser Stelle.

Für die nächsten Lektionen

Dies sollte erst einmal für das Thema Arrays reichen. In dieser Lektion sollte Ihnen klar werden, was ein Array ist, wie ein solcher deklariert wird und wie man den Zugriff auf ein jedes Element erhält. Außerdem sollte Ihnen die Verbindung von Array und Zeiger bekannt sein.

Zurück Nach oben Weiter