2.5 Datenfelder (Arrays)
Arrays, die manchmal auch als Datenfelder bezeichnet werden, ermöglichen es, eine nahezu beliebig große Anzahl von Variablen gleichen Namens und gleichen Datentyps zu definieren. Unterschieden werden die einzelnen Elemente nur anhand einer Indizierung. Arrays kommen insbesondere dann zum Einsatz, wenn in Programmschleifen dieselben Operationen auf alle oder einen Teil der Elemente ausgeführt werden sollen.
2.5.1 Die Deklaration und Initialisierung eines Arrays
Die Deklaration eines Arrays wird am besten an einem Beispiel verdeutlicht:
int[] elements;
Mit dieser Anweisung wird das Array elements deklariert, das Integer-Werte beschreibt. Um wie viele es sich handelt, ist noch nicht festgelegt. Die Kennzeichnung als Array erfolgt durch die eckigen Klammern, die hinter dem Datentyp angegeben werden müssen. Danach folgt der Bezeichner des Arrays.
Das Array elements ist zwar deklariert, aber noch nicht initialisiert. Insbesondere benötigt die Laufzeitumgebung eine Angabe darüber, wie viele Elemente sich im Array befinden. Arrays werden von der .NET-Laufzeitumgebung als Objekt angesehen, deshalb unterscheidet sich die Initialisierung von der einer herkömmlichen Variablen:
int[] elements;
elements = new int[3];
Das Schlüsselwort new kennzeichnet die Erzeugung eines Objekts, dahinter wird der Datentyp genannt. Die Anzahl der Array-Elemente – man spricht auch von der Größe des Arrays – geht aus der Zahlenangabe in den eckigen Klammern hervor: In unserem Fall verwaltet das Array elements genau drei Integer. Die Angabe in den eckigen Klammern der Initialisierung ist immer eine Zahl vom Typ int.
Die Anzahl der Elemente eines Arrays ergibt sich aus der Angabe in den eckigen Klammern bei der Initialisierung mit new.
Eine alternativ gleichwertige Deklarations- und Initialisierungsanweisung ist einzeilig und bietet sich insbesondere dann an, wenn bei der Deklaration bekannt ist, wie viele Elemente das Array haben soll:
int[] elements = new int[3];
Alle Elemente dieses Arrays sind danach mit dem Wert 0 vorinitialisiert. Steht zum Deklarationszeitpunkt bereits fest, welche Daten die Array-Elemente aufnehmen sollen, bietet sich auch die literale Initialisierung an, bei der die Daten in geschweiften Klammern bekannt gegeben werden:
int[] elements = new int[3]{23, 9, 7};
Gleichwertig ist auch diese Initialisierung:
int[] elements = new int[]{23, 9, 7};
Wer es ganz besonders kurz mag, darf auch die folgende Schreibweise einsetzen, bei der die Größe des Arrays automatisch anhand der Anzahl der zugewiesenen Elemente bestimmt wird:
int[] elements = {23, 9, 7};
Die literale Initialisierung setzt voraus, dass allen Elementen ein gültiger Wert übergeben wird. Deshalb ist die folgende Initialisierung falsch:
// falsche literale Initialisierung
int[] elements = new int[3]{23};
2.5.2 Der Zugriff auf die Array-Elemente
Bei der Initialisierung eines Arrays werden die einzelnen Elemente durchnummeriert. Dabei hat das erste Element den Index 0, das letzte Element den Index Anzahl der Elemente - 1.
Ein Array, das mit
int[] elements = new int[3];
deklariert und initialisiert worden ist, enthält somit drei Elemente:
elements[0]
elements[1]
elements[2]
Beabsichtigen wir, dem ersten Element des Arrays die Zahl 55 zuzuweisen, müsste die Anweisung wie folgt lauten:
elements[0] = 55;
Analog erfolgt auch die Auswertung des Elementinhalts durch die Angabe des Index:
int value = elements[0];
Im folgenden Beispiel werden zwei Arrays deklariert und mit Werten initialisiert, die anschließend an der Konsole ausgegeben werden.
// Beispiel: ..\Kapitel 2\ArraySample
class Program {
static void Main(string[] args) {
long[] lngVar = new long[4];
string[] strArr = new String[2];
// Wertzuweisungem
lngVar[0] = 230;
lngVar[1] = 4711;
lngVar[3] = 77;
strArr[0] = "C# ";
strArr[1] = "macht Spaß!";
// Konsolenausgaben
Console.WriteLine("lngVar[0] = {0}",lngVar[0]);
Console.WriteLine("lngVar[1] = {0}",lngVar[1]);
Console.WriteLine("lngVar[2] = {0}",lngVar[2]);
Console.WriteLine("lngVar[3] = {0}",lngVar[3]);
Console.Write(strArr[0]);
Console.WriteLine(strArr[1]);
Console.ReadLine();
}
}
Listing 2.18 Beispielprogramm mit einem Array
Das Array lngVar hat eine Größe von insgesamt vier Elementen und ist vom Typ long; das Array strArr vom Typ string enthält zwei Elemente. Bis auf das dritte Element des long-Arrays mit dem Index 2 wird allen Elementen ein Wert zugewiesen. Die Ausgabe des Programms zur Laufzeit lautet:
lngVar[0] = 230
lngVar[1] = 4711
lngVar[2] = 0
lngVar[3] = 77
C# macht Spaß!
2.5.3 Mehrdimensionale Arrays
Die bisher behandelten Arrays können Sie sich als eine einfache Folge von Daten auf einer Geraden vorstellen. Sie werden als eindimensionale Arrays bezeichnet. Zur Darstellung komplexer Datenstrukturen, beispielsweise räumlicher, sind eindimensionale Arrays aber nicht besonders gut geeignet. Daher kommen in der Praxis auch häufig zweidimensionale oder noch höher dimensionierte Arrays zum Einsatz.
Ein zweidimensionales Array kann man sich als Matrix oder Tabelle vorstellen. Bekanntermaßen ist jede Zelle einer Tabelle eindeutig durch die Position in einer Reihe und einer Spalte identifizierbar. Um den Inhalt einer Tabellenzelle durch ein bestimmtes Array-Element zu beschreiben, bietet sich ein zweidimensionales Array an: Eine Dimension beschreibt die Reihe, die andere Dimension die Spalte.
Angenommen, eine Tabelle hat vier Reihen und drei Spalten, dann könnte die Deklaration
int[,] zelle = new int[4,3];
lauten. Etwas schwieriger ist die literale Initialisierung eines mehrdimensionalen Arrays. Jede Dimensionsebene wird durch ein Paar geschweifter Klammern dargestellt, bei einem eindimensionalen Array also – wie oben eingangs gezeigt – durch ein Klammerpaar:
{Anzahl der Elemente der ersten Dimension}
Da ein zweidimensionales Array als ein Feld zu verstehen ist, bei dem jedes Array-Element selbst wieder ein eigenes Feld gleichen Typs definiert, wird jedes Element der Initialisierung eines eindimensionalen Arrays durch ein Paar geschweifter Klammern ersetzt, in dem wiederum Werte des »Unterarrays« angegeben werden:
{{Anzahl der Elemente der zweiten Dimension}, { }, ...}
Die literale Zuweisung an ein zweidimensionales Array könnte demnach wie folgt aussehen:
int[,] point = new int[,]{{1,2,3},{4,5,6}};
Zulässig ist auch ebenfalls die kürzere Schreibweise mit:
int[,] point = {{1,2,3},{4,5,6}};
Diese Systematik setzt sich mit jeder weiteren Dimension fort. Beispielhaft sei das noch an einem dreidimensionalen Array gezeigt:
{{{Anzahl der Elemente der dritten Dimension}, { }, ...}, { }, ...}
Das folgende Codebeispiel zeigt anhand eines dreidimensionalen Arrays, dass die Initialisierung mit zunehmender Dimensionstiefe schon verhältnismäßig komplex und dazu auch noch schlecht lesbar ist:
int[,,] elements = {
{ {1,2,3,4},{3,4,5,6},{6,7,8,9}},
{ {3,4,6,1},{6,19,3,4},{4,1,8,7}}
};
Das Array elements entspricht einem Array elements[2,3,4]. Es weist in der dritten Dimension vier Elemente auf, in der zweiten drei und in der ersten zwei.
Beim Zugriff auf ein mehrdimensionales Array muss man jede Dimension des entsprechenden Elements angeben. Beispielsweise schreibt die Anweisung
Console.WriteLine(elements[1,1,1]);
die Zahl 19 in das Konsolenfenster.
2.5.4 Festlegen der Array-Größe zur Laufzeit
Nicht immer sind wir in der glücklichen Lage, schon zur Entwicklungszeit die Größe eines Arrays zu kennen, da diese sich möglicherweise erst zur Laufzeit ergibt. In dieser Situation kann die Festlegung der Größe auch über eine Variable erfolgen, die zur Laufzeit mit einem konkreten Wert initialisiert wird. Das folgende Beispiel demonstriert das. Die Aufgabenstellung soll dabei sein, jedem Array-Element als Wert das Quadrat seines Index zuzuweisen.
// Beispiel: ..\Kapitel 2\ArrayInitialisierung
class Program {
static void Main(string[] args) {
int[] liste;
// Eingabe der Arraygröße
Console.Write("Geben Sie die Anzahl der Elemente ein: ");
int number = Convert.ToInt32(Console.ReadLine());
// Initialisierung des Arrays
liste = new int[number];
// jedes Element des Arrays in einer Schleife durchlaufen
// und jedem Array-Element einen Wert zuweisen und danach
// an der Konsole ausgeben
for (int i = 0; i < number; i++)
{
liste[i] = i * i
Console.WriteLine("myArr[{0}] = {1}", i, liste[i]);
}
Console.ReadLine();
}
}
Listing 2.19 Das Beispielprogramm »ArrayInitialisierung«
Zuerst wird das Array liste deklariert, dessen Größe zunächst noch unbestimmt ist. Im nächsten Schritt wird der Anwender zur Angabe der gewünschten Elementanzahl aufgefordert. Die Eingabe wird von der Methode ReadLine entgegengenommen und als Rückgabewert vom Typ string geliefert. Da wir das Array mit einem Integer initialisieren müssen, muss die Benutzereingabe vor der Zuweisung an die Variable number zuerst in den richtigen Typ konvertiert werden. Wir benutzen dazu wieder die Methode ToInt32 der Klasse Convert. Jetzt wissen wir, wie groß das Array liste tatsächlich werden soll, und können es mit
liste = new int[number];
initialisieren.
Thematisch noch nicht behandelt haben wir bisher Schleifen, um Anweisungen wiederholt auszuführen. Das soll uns aber in diesem Beispiel nicht davon abhalten, schon einmal einen kurzen Blick auf die for-Schleife zu werfen, die solche Anforderungen erfüllt. Die Anzahl der Schleifendurchläufe muss dabei vor dem Eintreten in die Schleife bekannt sein. Auf die Details der Syntax kommen wir in Abschnitt 2.7.1 noch zu sprechen.
In unserem Beispiel wird die Schleife vom ersten Index (= 0) bis zum letzten Index, der erst zur Laufzeit der Anwendung festgelegt wird, durchlaufen. Innerhalb des Anweisungsblocks wird anforderungsgerecht zuerst das Quadrat des Index ermittelt und das Ergebnis dem entsprechenden Array-Element zugewiesen. Anschließend erfolgt die Ausgabe an der Konsole.
Wenn Sie zur Laufzeit auf Aufforderung hin die Zahl 4 eingeben, wird im Fenster der Eingabekonsole die folgende Ausgabe erscheinen:
liste[0] = 0
liste[1] = 1
liste[2] = 4
liste[3] = 9
2.5.5 Bestimmung der Array-Obergrenze
Es kommt häufig vor, dass Sie zur Laufzeit die Array-Obergrenze ermitteln müssen, bei einem mehrdimensionalen Array vielleicht sogar die Obergrenze einer bestimmten Dimension. Insbesondere bei Arrays, deren Größe ähnlich wie im vorhergehenden Abschnitt gezeigt erst zur Laufzeit festgelegt wird, kommt dieser Fragestellung Bedeutung zu.
Da ein Array ein Objekt ist, können auf dem Array-Bezeichner Methoden aufgerufen werden. Dazu gehört auch die Methode GetLength, die uns für jede beliebige Dimension eines vorgegebenen Arrays die Anzahl der Elemente zurückliefert.
Auch wenn wir thematisch jetzt ein wenig vorgreifen, sollten wir uns kurz die Definition dieser Methode in der Klassenbibliothek ansehen:
public int GetLength(int dimension)
Der Zugriffsmodifizierer public interessiert uns an dieser Stelle noch nicht. In einem anderen Zusammenhang werden wir uns mit ihm noch genau beschäftigen. Die Methode liefert einen int als Resultat zurück, gekennzeichnet durch die entsprechende Angabe vor dem Methodenbezeichner. In den runden Klammern ist ebenfalls ein int deklariert. Hier erwartet die Methode von uns die Angabe, von welcher Dimension wir die Elementanzahl, also die Größe, erfahren wollen. Dabei gilt, dass die erste Dimension mit 0 angegeben wird, die zweite mit 1 usw.
Haben wir ein zweidimensionales Array mit
int[,] elements = new int[20,45];
deklariert, wird uns die Anweisung
Console.WriteLine(elements.GetLength(1));
die Größe der zweiten Dimension ausgeben, also 45.
2.5.6 Die Gesamtanzahl der Array-Elemente
Liegt ein mehrdimensionales Array vor, können wir die Gesamtanzahl der Elemente ermitteln, indem wir die Methode GetLength auf jeder Dimension aufrufen und anschließend die Rückgabewerte multiplizieren – aber es geht auch anders. Die Klasse Array bietet mit der Eigenschaft Length die Möglichkeit, auf einfache Art und Weise an die gewünschte Information zu gelangen:
int[,] elements = new int[20,45];
Console.WriteLine(elements.Length);
Die Ausgabe dieses Codefragments wird 900 sein, denn das Array enthält insgesamt 20 * 45 Elemente.
Bei einem eindimensionalen Array wird uns Length ebenfalls die Anzahl der Elemente liefern. In Schleifen, die Element für Element durchlaufen werden sollen, benötigen wir jedoch meist den letzten Index des Arrays. Dieser ist um genau eins niedriger als der Wert, der von Length zurückgegeben wird, also:
letzterArrayIndex = Array-Bezeichner.Length – 1;
2.5.7 Verzweigte Arrays
In allen bisherigen Ausführungen hatten unsere Arrays eine rechteckige Struktur. In C# haben Sie aber auch die Möglichkeit, ein Array zu deklarieren, dessen Elemente selbst wieder Arrays sind. Ein solches Array wird als verzweigtes Array bezeichnet. Da die Anzahl der Dimensionen eines verzweigten Arrays für jedes Element unterschiedlich groß sein kann, ist ein solches Array äußerst flexibel.
Die Deklaration und Initialisierung eines verzweigten Arrays ist nicht mehr so einfach wie die eines herkömmlichen mehrdimensionalen Arrays. Betrachten wir dazu zunächst ein Beispiel:
int[][] myArray = new int[4][];
Das Array myArray enthält insgesamt vier Elemente, die ihrerseits wieder Arrays sind. Kennzeichnend für verzweigte Arrays ist die doppelte Angabe der rechteckigen Klammern sowohl links vom Gleichheitszeichen bei der Deklaration als auch rechts bei der Initialisierung. Im ersten Moment mag das verwirrend erscheinen, aber vergleichen wir doch einmal: Würden wir ein eindimensionales Array deklarieren und initialisieren, müsste die Anweisung dazu wie folgt lauten:
int[] myArray = new int[4];
Durch das Hinzufügen einer zweiten Klammer, sowohl im deklarierenden als auch im initialisierenden Teil, machen wir deutlich, dass jedes Array-Element seinerseits ein Array repräsentiert.
Hätten wir es mit einem einfachen Array zu tun, würde dieses als initialisiert gelten. Nun ist der Sachverhalt aber anders, denn jedes Element eines verzweigten Arrays muss seinerseits selbst initialisiert werden. Bezogen auf das oben deklarierte Array myArray könnte das beispielsweise wie folgt aussehen:
myArray[0] = new int[3];
myArray[1] = new int[4];
myArray[2] = new int[2];
myArray[3] = new int[5];
Wenn die einzelnen Elemente aller Arrays bekannt sind, kann alternativ auch literal mit
myArray[0] = new int[3]{1,2,3};
myArray[1] = new int[4]{1,2,3,4};
myArray[2] = new int[2]{1,2};
myArray[3] = new int[5]{1,2,3,4,5};
oder mit
int[][] myArray = {new int[]{1,2,3},
new int[]{1,2,3,4},
new int[]{1,2},
new int[]{1,2,3,4,5}};
initialisiert werden.
Beim Zugriff auf das Element eines verzweigten Arrays muss zuerst berücksichtigt werden, in welchem Unterarray sich das gewünschte Element befindet. Danach wird die Position innerhalb des Unterarrays bekannt gegeben. Angenommen, Sie möchten den Inhalt des fünften Elements im Unterarray mit dem Index 3 auswerten, würde auf dieses Element wie folgt zugegriffen:
Console.WriteLine(myArray[3][4]);
Verzweigte Arrays sind nicht nur auf eindimensionale Arrays beschränkt, sondern können auch mit mehrdimensionalen kombiniert werden. Benötigen Sie zum Beispiel ein verzweigtes, zweidimensionales Array, müssen Sie das sowohl im Deklarations- als auch im Initialisierungsteil berücksichtigen. In jedem Teil dient die jeweils zweite eckige Klammer zur Angabe der Dimensionsgröße:
int[][,] myArray = new int[2][,];
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.