9.2 Mehrdimensionale Arrays
Arrays, wie sie bisher besprochen wurden, können Sie sich als einen sequenziellen Strang von hintereinander aufgereihten Werten vorstellen. Diese Konstruktion entspricht einer Matrix bzw. Tabelle mit nur einer Zeile. In der Praxis spricht man dann von einem eindimensionalen Array. Es ist aber auch möglich, Arrays mit mehr als nur einer Dimension zu verwenden:
int tabelle[2][3]; // Zweidimensionales Array mit 2 Zeilen und 3 Spalten
Hier wurde ein zweidimensionales Array mit dem Namen tabelle definiert. Somit besteht das Array tabelle aus sechs Elementen vom Typ int. Im Zusammenhang mit zweidimensionalen Arrays wird, wie schon angedeutet, häufig auch von Matrizen gesprochen. Sie können sich dieses mehrdimensionale Array aber auch wie bei einer Tabellenkalkulation vorstellen (siehe Abbildung 9.3). Übrigens werden bei Arrays, wie in der Mathematik ebenfalls üblich, zuerst die Zeilen, und dann die Spalten angegeben.
9.2.1 Zweidimensionalen Arrays Werte zuweisen und darauf zugreifen
Im Grunde funktioniert die Initialisierung von mehrdimensionalen Arrays wie die von eindimensionalen Arrays (siehe Abschnitt 9.1.2, »Arrays mit Werten versehen und darauf zugreifen«). Anstelle eines Indizierungsoperators [] müssen nur zwei Zuweisungsoperatoren verwendet werden, um auf die einzelnen Array-Elemente zuzugreifen. Trotzdem gibt es einige Besonderheiten, die Sie beachten sollten. Wir werden im Folgenden darauf noch eingehen.
Hierzu ein Beispiel:
00 // Kapitel9/md_array_1.c
01 #include <stdio.h>
02 #include <stdlib.h>
03 int main(void) {
04 int mdarray[2][3];
05 // Array mit Werten initialisieren
06 mdarray[0][0] = 12;
07 mdarray[0][1] = 23;
08 mdarray[0][2] = 34;
09 mdarray[1][0] = 45;
10 mdarray[1][1] = 56;
11 mdarray[1][2] = 67;
12 // Inhalt ausgeben
13 for(int i=0; i < 2; i++) {
14 for(int j=0; j < 3; j++ ) {
15 printf("[%d][%d] = %d\n", i, j, mdarray[i][j]);
16 }
17 }
18 return EXIT_SUCCESS;
19 }
In den Zeilen (06) bis (11) wurden je sechs Werte mithilfe der Indizierungsoperatoren und der entsprechenden Indexnummern zugewiesen. Analog dazu werden die Werte in den Zeilen (13) bis (17) ausgegeben. Solche verschachtelten for-Schleifen sind typisch für mehrdimensionale Arrays. Mit der äußeren for-Schleife durchlaufen Sie die einzelnen Zeilen, mit der inneren die einzelnen Spalten dieser Zeile. Die eckigen Klammern bei der Formatanweisung von printf() in Zeile (15) sind eine reine Designentscheidung und haben keine Bedeutung.
Das Programm gibt bei der Ausführung Folgendes aus:
[0][0] = 12
[0][1] = 23
[0][2] = 34
[1][0] = 45
[1][1] = 56
[1][2] = 67
Initialisieren mit Initialisierungsliste
Ein mehrdimensionales Array können Sie bei der Definition mit einer Initialisierungsliste, ähnlich wie bei den eindimensionalen Arrays, explizit initialisieren. Hierbei wird dem Array bei der Definition eine Liste von Werten, getrennt mit einem Komma, in geschweiften Klammern zugewiesen. Einzelne Zeilen werden für gewöhnlich zwischen weiteren geschweiften Klammern zusammengefasst. Ein einfaches Beispiel:
int mdarray[2][3] = { {12, 23, 34},
{45, 56, 67} };
Nach dieser Initialisierung haben die einzelnen Elemente im Array mdarray folgende Werte:
mdarray[0][0] = 12
mdarray[0][1] = 23
mdarray[0][2] = 34
mdarray[1][0] = 45
mdarray[1][1] = 56
mdarray[1][2] = 67
Auf die zusätzlichen geschweiften Klammern hätten Sie aber theoretisch auch verzichten können. Mit folgender Definition hätten Sie dasselbe erreicht, da ja die Werte im Speicher sequenziell abgelegt werden:
int mdarray[2][3] = { 12, 23, 34, 45, 56, 67 };
Wenn Sie die Array-Elemente in einer Liste von Initialisierungswerten angeben, können Sie die erste Dimension auch weglassen. So ist also auch Folgendes möglich:
int mdarray[][3] = { {12, 23, 34},
{45, 56, 67} };
// oder auch:
int mdarray[][3] = { 12, 23, 34, 45, 56, 67 };
Die erste Dimension wird dann anhand der angegebenen Anzahl in der zweiten Dimension und der vorhandenen Initialisierungselemente berechnet.
Deklaration unvollständiger mehrdimensionaler Arrays
Bei der Deklaration von mehrdimensionalen Arrays darf die Längenangabe der ersten Dimension auch fehlen. Allerdings muss sie dann an einer anderen Stelle im Programm definiert werden. Wir raten aber von solchen Konstruktionen ab, weil Sie damit sehr schnell schwer lesbaren Code erzeugen, vor allem, wenn die entsprechenden Kommentare fehlen.
Elemente, die in einem mehrdimensionalen Array bei der Definition mit der Initialisierungsliste nicht ausdrücklich initialisiert wurden, erhalten automatisch den Wert 0. Hier ein Beispiel:
int mdarray[2][3] = { { 1 },
{ 2, 3 } };
Nach dieser Initialisierung haben die einzelnen Elemente im Array mdarray folgende Werte:
mdarray[0][0] = 1
mdarray[0][1] = 0
mdarray[0][2] = 0
mdarray[1][0] = 2
mdarray[1][1] = 3
mdarray[1][2] = 0
9.2.2 Zweidimensionale Arrays an eine Funktion übergeben
Die Übergabe von zweidimensionalen Arrays an eine Funktion ist natürlich auch möglich. Allerdings ist es auch hier häufig ein wenig verwirrend, wie der Funktionskopf aussieht.
Sehen Sie sich hierzu folgende Funktion an – sie demonstriert die Übergabe von mehrdimensionalen Arrays an Funktionen:
00 // Kapitel9/md_funcarray.c
01 #include <stdio.h>
02 #include <stdlib.h>
03 #define WOCHE 2
04 #define TAGE 7
05 void durchschnitt( int arr[][TAGE] ) {
06 int durchs=0;
07 for( int i=0; i < WOCHE; i++) {
08 for( int j=0; j < TAGE; j++) {
09 durchs+=arr[i][j];
10 }
11 }
12 printf("Besucher in %d Tagen\n", WOCHE*TAGE);
13 printf("Gesamt : %d\n", durchs);
14 printf("Tagesschnitt: %d\n", durchs /(WOCHE*TAGE));
15 }
16 int main(void) {
17 int besucher[WOCHE][TAGE];
18 printf("Besucherzahlen eingeben\n\n");
19 for(int i=0; i < WOCHE; i++) {
20 for(int j=0; j < TAGE; j++) {
21 printf("Woche %d, Tag %d: ", i+1, j+1);
22 if( scanf("%d", &besucher[i][j]) != 1 ) {
23 printf("Fehler bei der Eingabe\n");
24 return EXIT_FAILURE;
25 }
26 }
27 }
28 durchschnitt( besucher );
29 return EXIT_SUCCESS;
30 }
In diesem Beispiel wird eine Besucherstatistik erstellt. Dabei werden die Besucherzahlen für jeden Tag der letzten zwei Wochen in Zeile (22) an das mehrdimensionale Array besucher übergeben. Sie können hierbei auch gleich sehen, wie Sie mit scanf() einzelne Werte in ein zweidimensionales Array einlesen können. Auch hier dürfen Sie den Adressoperator & nicht vergessen. In Zeile (28) wird dann die Anfangsadresse des mehrdimensionalen Arrays an die Funktion durchschnitt() übergeben.
In der Funktion selbst machen wir in den Zeilen (05) bis (15) nichts anderes, als die Besucherzahlen der einzelnen Wochen und Tage in der verschachtelten for-Schleife zu addieren und am Ende die gesamte Besucherzahl und den Tagesdurchschnitt zu berechnen.
Das Programm gibt bei der Ausführung Folgendes aus:
Woche 1, Tag 1: 123
Woche 1, Tag 2: 234
Woche 1, Tag 3: 246
Woche 1, Tag 4: 467
Woche 1, Tag 5: 147
Woche 1, Tag 6: 268
Woche 1, Tag 7: 345
Woche 2, Tag 1: 134
Woche 2, Tag 2: 234
Woche 2, Tag 3: 232
Woche 2, Tag 4: 126
Woche 2, Tag 5: 105
Woche 2, Tag 6: 101
Woche 2, Tag 7: 223
Besucher in 14 Tagen
Gesamt : 2985
Tagesschnitt : 213
9.2.3 Können wir noch mehr Dimensionen verwenden?
Die Antwort auf die letzte Frage ist »ja«. Natürlich ist die Anzahl der möglichen Dimensionen nicht nur auf zwei beschränkt. Sie können durchaus auch drei, vier oder mehr Dimensionen definieren. Alles bisher Beschriebene lässt sich also in ähnlicher Weise bei einem drei- oder vierdimensionalen Array anwenden. Ein Beispiel einer solchen Definition könnte sein: