vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Woche 1

Tag 7

Numerische Arrays

Arrays sind eine bestimmte Form von Datenspeicher, die in C-Programmen oft Verwendung finden. Am Tag 5, »Grundlagen der Programmsteuerung«, wurde bereits eine kurze Einführung in Arrays gegeben. Heute lernen Sie:

Was ist ein Array?

Ein Array ist eine Sammlung von Speicherstellen für Daten, die alle den gleichen Datentyp aufweisen und den gleichen Namen tragen. Die einzelnen Speicherstellen in einem Array nennt man auch Array-Elemente. Wozu benötigen Sie Arrays in Ihren Programmen? Diese Frage lässt sich am besten mit einem Beispiel beantworten. Wenn Sie die Übersicht über Ihre Geschäftsausgaben für 2001 behalten wollen, werden Sie Ihre Quittungen monatsweise abheften. Dazu könnten Sie für jeden Monat einen eigenen Hefter anlegen; bequemer wäre es jedoch, wenn Sie nur einen Hefter hätten, der zwölf Register aufwiese.

Dieses Beispiel lässt sich auf die Computerprogrammierung übertragen. Stellen Sie sich vor, dass Sie ein Programm entwerfen, mit dem Sie Ihre Geschäftsausgaben kontrollieren. In diesem Programm könnten Sie zwölf einzelne Variablen deklarieren - jeweils für die Gesamtausgaben eines jeden Monats. Dieser Ansatz entspricht den zwölf einzelnen Heftern für Ihre Quittungen. Versierte Programmierer würden jedoch ein Array mit zwölf Elementen verwenden und dort in den entsprechenden Array- Elementen die Gesamtausgaben der einzelnen Monate abspeichern. Dieser Ansatz entspricht der Ablage Ihrer Quittungen in einem einzigen Hefter mit zwölf Registern. Abbildung 7.1 veranschaulicht den Unterschied zwischen der Verwendung von einzelnen Variablen und einem Array.

Abbildung 7.1:  Variablen sind vergleichbar mit einzelnen Heftern, während ein Array einem Hefter mit mehreren Registern entspricht.

Eindimensionale Arrays

Eindimensionale Arrays haben nur einen Index. Unter dem Index versteht man eine Zahl in eckigen Klammern, die auf den Arraynamen folgt. Diese Zahl gibt an, wie viele Elemente im Array enthalten sind. Verdeutlichen wir uns dies anhand eines Beispiels. In unserem Programm zur Kontrolle der Geschäftsausgabe könnten Sie mit der folgenden Zeile ein Array des Typs float deklarieren:

float ausgaben[12];

Das Array trägt den Namen ausgaben und enthält zwölf Elemente. Jedes dieser zwölf Elemente entspricht genau einer float-Variablen. Alle Datentypen, die es in C gibt, können auch für Arrays verwendet werden. Array-Elemente in C sind immer durchnummeriert, wobei das erste Element die Nummer 0 hat. Deshalb erhalten die zwölf Elemente für die Ausgaben die Indizes 0 bis 11. In dem nachstehenden Beispiel sind die Gesamtausgaben für Januar in ausgaben[0], die für Februar in ausgaben[1] und so weiter gespeichert.

Wenn Sie ein Array deklarieren, reserviert der Compiler einen Speicherblock, der das ganze Array aufnimmt. Die einzelnen Array-Elemente werden, wie Abbildung 7.2 zeigt, hintereinander im Speicher abgelegt.

Abbildung 7.2:  Array-Elemente werden hintereinander im Speicher abgelegt.

Wichtig ist vor allem, wo in Ihrem Quellcode Sie die Arrays deklarieren. Denn die Position der Deklaration bestimmt - genau wie bei den normalen Variablen -, wie das Programm das Array nutzen kann. Am Tag 11, »Gültigkeitsbereiche von Variablen«, wird ausführlich erläutert, welche Auswirkung die Position der Deklaration hat. Für heute reicht es, wenn Sie Ihre Arrays zusammen mit den anderen Variablen deklarieren.

Ein Array-Element kann in einem Programm überall dort verwendet werden, wo auch eine normale Variable des gleichen Typs eingesetzt werden kann. Der Zugriff auf die einzelnen Elemente des Arrays erfolgt über den Array-Namen gefolgt von dem in eckigen Klammern stehenden Index des Elements. Die folgende Anweisung speichert den Wert 89.95 in dem zweiten Array-Element (zur Erinnerung, das erste Array- Element lautet ausgaben[0] und nicht ausgaben[1]):

ausgaben[1] = 89.95;

Genauso kann man mit der Anweisung

ausgaben[10] = ausgaben[11];

den Wert, der im Array-Element ausgaben[11] gespeichert ist, auch dem Array- Element ausgaben[10] zuweisen. Für den Zugriff auf die Array-Elemente wurde in diesen Beispielen jeweils eine literale Konstante als Array-Index verwendet. Oft jedoch werden Sie in Ihren Programmen Integer-Variablen, Ausdrücke oder sogar andere Array-Elemente als Index verwenden. Sehen Sie im Folgenden einige Beispiele:

float ausgaben[100];
int a[10];
/* weitere Anweisungen */
ausgaben[i] = 100; /* i ist eine Integer-Variable */
ausgaben[2 + 3] = 100; /* entspricht ausgaben[5] */
ausgaben[a[2]] = 100; /* a[] ist ein Integer-Array */

Das letzte Beispiel bedarf einer Erklärung. Angenommen Sie haben ein Integer-Array namens a[], in dessen Element a[2] der Wert 8 gespeichert ist, dann hätte der Ausdruck

ausgaben[a[2]]

die gleiche Bedeutung wie

ausgaben[8]

Wenn Sie mit Arrays arbeiten, sollten Sie sich das Nummerierungssystem für die Array-Elemente merken: In einem Array mit n Elementen reicht der zulässige Index von 0 bis n-1. Wenn Sie n als Index verwenden, führt das eventuell zu Programmfehlern. Ihr C-Compiler kann nicht erkennen, ob das Programm einen Array-Index verwendet, der außerhalb des Gültigkeitsbereiches liegt, das heißt, Ihr Programm lässt sich auch mit ungültigen Indizes kompilieren und linken - was im Allgemeinen zu fehlerhaften Ergebnissen führt.

Denken Sie daran, dass die Indizierung der Array-Elemente mit 0 und nicht mit 1 startet. Das hat zur Folge, dass der Index des letzten Elements um eins kleiner ist als die Anzahl der Elemente im Array. Ein Array mit zehn Elementen enthält zum Beispiel die Elemente 0 bis 9.

Manchmal ist es jedoch sinnvoll, ein Array mit n Elementen so zu behandeln, als ob dessen Elemente von 1 bis n nummeriert wären. So wäre es zum Beispiel in unserem obigen Beispiel nahe liegend, die Gesamtausgaben von Januar in ausgaben[1], die von Februar in ausgaben[2] und so weiter abzuspeichern. Die einfachste Lösung besteht darin, ein Array mit einem zusätzlichen Element zu deklarieren und dann das Element 0 zu ignorieren. In diesem Fall würden Sie das Array wie folgt deklarieren.

float ausgaben[13];

Sie können das freie Element 0 aber auch zum Speichern zusätzlicher Daten verwenden (beispielsweise für die jährlichen Gesamtausgaben).

Das Programm aus Listing 7.1 zeigt Ihnen, wie Arrays verwendet werden. Es ist ein einfaches Programm ohne direkten praktischen Nutzen. Dennoch zeigt es beispielhaft die Verwendung eines Arrays.

Listing 7.1: Einsatz eines Arrays.

1:   /* Beispiel für die Verwendung eines Arrays */
2:
3: #include <stdio.h>
4:
5: /* Deklaration eines Arrays und einer Zählervariablen */
6:
7: float ausgaben[13];
8: int count;
9:
10: int main(void)
11: {
12: /* Daten von der Tastatur in das Array einlesen */
13:
14: for (count = 1; count < 13; count++)
15: {
16: printf("Ausgaben für Monat %d: ", count);
17: scanf("%f", &ausgaben[count]);
18: }
19:
20: /* Array-Inhalt ausgeben */
21:
22: for (count = 1; count < 13; count++)
23: {
24: printf("Monat %d = %.2f DM\n", count, ausgaben[count]);
25: }
26: return 0;
27: }

Ausgaben für Monat 1: 100
Ausgaben für Monat 2: 200.12
Ausgaben für Monat 3: 150.50
Ausgaben für Monat 4: 300
Ausgaben für Monat 5: 100.50
Ausgaben für Monat 6: 34.25
Ausgaben für Monat 7: 45.75
Ausgaben für Monat 8: 195.00
Ausgaben für Monat 9: 123.45
Ausgaben für Monat 10: 111.11
Ausgaben für Monat 11: 222.20
Ausgaben für Monat 12: 120.00
Monat 1 = 100.00 DM
Monat 2 = 200.12 DM
Monat 3 = 150.50 DM
Monat 4 = 300.00 DM
Monat 5 = 100.50 DM
Monat 6 = 34.25 DM
Monat 7 = 45.75 DM
Monat 8 = 195.00 DM
Monat 9 = 123.45 DM
Monat 10 = 111.11 DM
Monat 11 = 222.20 DM
Monat 12 = 120.00 DM

Wenn Sie das Programm ausführen, fordert es Sie als Erstes auf, die Ausgaben für die zwölf Monate einzugeben. Die von Ihnen eingegebenen Werte werden in einem Array gespeichert. Sie müssen für jeden Monat einen Wert eingeben. Nach der Eingabe des zwölften Wertes wird der Inhalt des Arrays auf dem Bildschirm angezeigt.

Der Programmfluss sollte Ihnen bereits aus den vorangehenden Listings bekannt sein. Zeile 1 beginnt mit einem Kommentar, der das Programm beschreibt.

Zeile 5 enthält einen weiteren Kommentar, der die nachfolgend deklarierten Variablen erläutert. In Zeile 7 wird ein Array mit 13 Elementen deklariert. Für das Programm werden zwar nur zwölf Elemente benötigt (eines für jeden Monat), aber 13 werden deklariert. Die for-Schleife in den Zeilen 14 bis 18 ignoriert das Element 0. Auf diese Weise kann das Programm die Elemente 1 bis 12 verwenden, die direkteren Bezug zu den zwölf Monaten haben. Doch zurück zu Zeile 8. Hier wird eine Variable namens count deklariert, die im Programm als Zähler und als Array-Index verwendet wird.

Die main()-Funktion des Programms beginnt in Zeile 10. Das Programm verwendet eine for-Schleife, um eine Eingabeaufforderung auszugeben und einen Wert für jeden der zwölf Monate zu übernehmen. Beachten Sie, dass die scanf()-Funktion in Zeile 17 ein Array-Element verwendet. In Zeile 7 wurde das Array ausgaben mit dem Typ float deklariert, so dass %f verwendet wird. Außerdem wird der Adressoperator (&) vor das Array-Element gesetzt, ganz so als ob es eine normale float-Variable wäre und kein Array-Element.

Die Zeilen 22 bis 25 enthalten eine zweite for-Schleife, die die eingegebenen Werte ausgibt. Die printf()-Funktion wurde um einen zusätzlichen Formatierungsbefehl ergänzt, damit die Werte von ausgaben auf dem Bildschirm etwas übersichtlicher dargestellt werden. Zur Erläuterung sei erwähnt, dass %.2f eine Fließkommazahl mit zwei Stellen rechts des Dezimalpunktes ausgibt. Weitere Formatierungsbefehle finden Sie am Tag 13, »Mit Bildschirm und Tastatur arbeiten«.

Was Sie tun sollten

Was nicht

Verwenden Sie Arrays anstatt einer Vielzahl von Variablen, um zusammengehörende Informationen gleichen Datentyps zu speichern. Wenn Sie zum Beispiel die Verkaufszahlen für jeden Monat im Jahr speichern wollen, sollten Sie ein Array mit zwölf Elementen erzeugen, die diese Verkaufszahlen aufnehmen, und nicht für jeden Monat eine Variable für die Verkaufszahlen.

Und vergessen Sie nicht, dass der Array- Index mit der Zahl 0 beginnt.

Mehrdimensionale Arrays

Ein mehrdimensionales Array enthält mehr als einen Index. Ein zweidimensionales Array hat zwei Indizes, ein dreidimensionales Array drei und so weiter. Es gibt bezüglich der Anzahl der Dimensionen, die ein C-Array haben darf, keine Obergrenze. (Allerdings gibt es, wie wir später noch sehen werden, eine Grenze, was die Gesamtgröße des Arrays anbetrifft.)

Angenommen Sie wollen ein Programm schreiben, das Dame spielt. Das Spielbrett besteht aus 64 Quadraten, die in acht Reihen und acht Spalten angeordnet sind. Ihr Programm könnte das Brett wie folgt als ein zweidimensionales Array darstellen:

int dame[8][8];

Das resultierende Array weist 64 Elemente auf: dame[0][0], dame[0][1], dame[0][2],...,dame[7][6], dame[7][7]. Die Struktur dieses zweidimensionalen Arrays ist in Abbildung 7.3 zu sehen.

Abbildung 7.3:  Ein zweidimensionales Array mit einer Reihen/Spalten-Struktur.

Entsprechend kann man sich ein dreidimensionales Array als Würfel vorstellen. Arrays mit vier (und mehr) Dimensionen möchte ich lieber Ihrer Phantasie überlassen. Alle Arrays werden unabhängig von der Anzahl der Dimensionen hintereinander im Speicher abgelegt. Ausführlichere Informationen zu der Speicherung von Arrays finden Sie am Tag 14, »Zeiger für Fortgeschrittene«.

Array-Namen und -Deklarationen

Die Regeln für die Namensgebung von Arrays entsprechen denen für Variablennamen, die am Tag 2, »Die Komponenten eines C-Programms: Quellcode und Daten«, im Abschnitt »Daten speichern: Variablen und Konstanten« bereits aufgeführt wurden. Ein Arrayname muss einzigartig sein. Er darf nicht von einem anderen Array oder einem anderen Bezeichner (Variable, Konstante etc.) besetzt sein. Wie Ihnen wahrscheinlich aufgefallen sein dürfte, folgen die Array-Deklarationen der gleichen Form wie die Deklarationen normaler Variablen. Der einzige Unterschied besteht darin, dass die Anzahl der Elemente im Array in eckigen Klammern direkt auf den Array-Namen folgen muss.

Wenn Sie ein Array deklarieren, können Sie die Anzahl der Elemente mit einer Konstanten angeben (wie dies auch in den obigen Beispielen geschehen ist) oder mit einer symbolischen Konstante, die mit der #define-Direktiven erzeugt wurde. Demzufolge entspricht

#define MONATE 12
int array[MONATE];

der folgenden Anweisung:

int array[12];

Im Gegensatz zu vielen anderen Compilern erlaubt Ihnen der gcc, Arrays unter Verwendung von symbolischen Konstanten zu deklarieren, die mit dem Schlüsselwort const erzeugt wurden:

const int MONATE = 12;
int array[MONATE]; /* Gefährlich! */

Da diese Eigenheit nicht von allen Compilern unterstützt wird, sollten Sie Vorsicht walten lassen, wenn Sie Ihren Code auf einem anderen Compiler als dem gcc kompilieren wollen. Vielleicht weisen Sie den gcc mit der Option -pedantic an, Warnungen auszugeben, wenn Konstrukte verwendet werden, die nicht dem Standard entsprechen (sehen Sie dazu auch den Abschnitt zum gcc-Compiler am Tag 1, »Einführung in Linux und die Programmiersprache C«).

Listing 7.2 zeigt ein weiteres Programm, das ein eindimensionales Array verwendet. Dieses Programm verwendet ein Array, das zehn Noten speichert.

Listing 7.2: Speichert zehn Noten in einem Array.

1:   /* Beispielprogramm mit Array                            */
2: /* 10 Noten einlesen und den Durchschnittswert ermitteln */
3:
4: #include <stdio.h>
5:
6: #define MAX_NOTE 100
7: #define STUDENTEN 10
8:
9: int noten[STUDENTEN];
10:
11: int idx;
12: int gesamt = 0; /* für den Durchschnittswert */
13:
14: int main(void)
15: {
16: for( idx=0;idx< STUDENTEN;idx++)
17: {
18: printf( "Geben Sie die Note von Person %d ein: ", idx +1);
19: scanf( "%d", &noten[idx] );
20:
21: while ( noten[idx] > MAX_NOTE )
22: {
23: printf( "\nDie beste Note ist %d",
24 MAX_NOTE );
25: printf( "\nGeben Sie eine korrekte Note ein: " );
26: scanf( "%d", &noten[idx] );
27: }
28:
29: gesamt += noten[idx];
30: }
31:
32: printf( "\n\nDer Durchschnittswert beträgt %d\n",
( gesamt / STUDENTEN) );
33:
34: return (0);
35: }

Geben Sie die Note von Person 1 ein: 95
Geben Sie die Note von Person 2 ein: 100
Geben Sie die Note von Person 3 ein: 60
Geben Sie die Note von Person 4 ein: 105

Die beste Note ist 100
Geben Sie eine korrekte Note ein: 100
Geben Sie die Note von Person 5 ein: 25
Geben Sie die Note von Person 6 ein: 0
Geben Sie die Note von Person 7 ein: 85
Geben Sie die Note von Person 8 ein: 85
Geben Sie die Note von Person 9 ein: 95
Geben Sie die Note von Person 10 ein: 85

Der Durchschnittswert beträgt 73

Wie schon im vorangehenden Listing wird auch hier der Benutzer zuerst zur Eingabe aufgefordert. Er soll für zehn Personen die Noten eingeben. Aber anstatt diese Noten einfach auszugeben, wird diesmal der Durchschnitt gebildet.

Sie haben bereits gelernt, dass Arrays bei der Namensgebung den gleichen Regeln folgen wie normale Variablen. In Zeile 9 wird das Array für dieses Programm mit dem Namen noten deklariert. Sicherlich liegen Sie richtig, wenn Sie davon ausgehen, dass dieses Array Noten enthält. Die Zeilen 6 und 7 definieren zwei Konstanten, MAX_NOTE und STUDENTEN. Diese Konstanten können leicht geändert werden. Da STUDENTEN mit dem Wert 10 definiert wurde, wissen Sie, dass das Array noten zehn Elemente enthält. Dazu werden noch zwei weitere Variablen deklariert, idx und gesamt. Die Abkürzung von »Index«, idx, wird als Zähler und Array-Index verwendet. Die Gesamtsumme alle Noten wird in gesamt abgelegt.

Das Kernstück dieses Programms ist die for-Schleife in den Zeilen 16 bis 30. Die for- Schleife initialisiert idx mit 0, dem ersten Index im Array. Die Schleife wird so oft durchlaufen, wie idx kleiner als die Zahl der Studenten ist. Nach jedem Schleifendurchlauf wird idx um 1 inkrementiert. In jeder for-Schleife fordert das Programm den Anwender auf, die Note für eine Person einzugeben (Zeilen 18 und 19). Beachten Sie, dass in Zeile 18 idx um 1 heraufgesetzt wird, damit die Personen von 1 bis 10 und nicht von 0 bis 9 durchnummeriert werden. Da Arrays mit dem Index 0 beginnen, wird die erste Note in noten[0] abgelegt. Der Anwender könnte allerdings verwirrt werden, wenn um die Eingabe der Note für die Person 0 gebeten wird. Daher wird der Index um 1 erhöht und es erscheint die Aufforderung, die Note der Person 1 einzugeben.

Die Zeilen 21 bis 27 enthalten - eingebettet in der for-Schleife - eine while-Schleife. Diese überprüft die Eingabe, um sicherzustellen, dass die Note nicht höher als das vorgegebene Maximum, MAX_NOTE, ist. Anwender, die eine zu hohe Note eingegeben haben, werden aufgefordert, ihre Eingabe zu wiederholen. Sie sollten Programmdaten, wann immer möglich, überprüfen.

Zeile 29 addiert die eingegebene Note zu der Gesamtsumme gesamt. In Zeile 32 wird gesamt dazu verwendet, den Durchschnitt zu errechnen und auszugeben. (gesamt/ STUDENTEN).

Was Sie tun sollten

Was nicht

Verwenden Sie #define-Anweisungen, um Konstanten für die Array-Deklaration zu definieren. Sie können die Anzahl der Elemente im Array dann ohne Mühe ändern. Um beispielsweise in obigem Programm die Anzahl der Studenten zu ändern, müssen Sie nur die #define- Anweisung anpassen - Sie brauchen keine weiteren Änderungen im Programm vorzunehmen.

Vermeiden Sie mehrdimensionale Arrays mit mehr als drei Dimensionen. Denken Sie daran, dass mehrdimensionale Arrays sehr schnell sehr groß werden können.

Arrays initialisieren

Sie können ein Array bei seiner Deklaration ganz oder teilweise initialisieren. Setzen Sie hinter die Array-Deklaration ein Gleichheitszeichen und in geschweifte Klammern eine Liste der Werte, die durch Kommata getrennt werden müssen. Die aufgelisteten Werte werden der Reihenfolge nach den Array-Elementen ab dem Index 0 zugewiesen.

Betrachten Sie folgenden Code:

int array[4] = { 100, 200, 300, 400 };

In diesem Beispiel wird der Wert 100 dem Array-Element array[0], der Wert 200 dem Element array[1], der Wert 300 dem Element array[2] und der Wert 400 dem Element array[3] zugewiesen.

Wenn Sie nicht angeben, wie groß das Array sein soll, erzeugt der Compiler ein Array, das gerade groß genug ist, um die Werte aus der Initialisierung aufzunehmen. Deshalb würde die folgende Anweisung genau der obigen Array-Deklaration entsprechen:

int array[] = { 100, 200, 300, 400 };

Sie können auch weniger Werte initialisieren als das Array Elemente hat, wie im folgenden Beispiel gezeigt:

int array[10] = { 1, 2, 3 };

Wenn Sie ein Array-Element nicht explizit initialisieren, können Sie nicht sicher sein, welchen Wert es enthält, wenn das Programm ausgeführt wird. Wenn Sie zu viele Werte initialisieren (mehr als das Array Elemente enthält), gibt der Compiler eine Fehlermeldung aus.

Mehrdimensionale Arrays initialisieren

Auch mehrdimensionale Arrays können initialisiert werden. Die Liste der initialisierten Werte wird der Reihenfolge nach den Array-Elementen zugewiesen, wobei der letzte Array-Index zuerst geändert wird. So führt die folgende Anweisung

int array[4][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

zu folgenden Zuweisungen:

array[0][0] entspricht 1
array[0][1] entspricht 2
array[0][2] entspricht 3
array[1][0] entspricht 4
array[1][1] entspricht 5
array[1][2] entspricht 6
...
array[3][1] entspricht 11
array[3][2] entspricht 12

Bei der Initialisierung mehrdimensionaler Arrays können Sie Ihren Quellcode dadurch lesbarer machen, dass Sie mit zusätzlichen geschweiften Klammern die initialisierten Werte gruppieren und auf mehrere Zeilen verteilen. Die folgende Initialisierung entspricht der von oben:

int array[4][3] = { { 1, 2, 3 } , { 4, 5, 6 } ,
{ 7, 8, 9 } , { 10, 11, 12 } };

Denken Sie daran, die initialisierten Werte durch Kommata zu trennen - auch wenn dazwischen eine geschweifte Klammer steht. Auch sollten Sie sicherstellen, dass Sie geschweifte Klammern immer paarweise verwenden. Jeder öffnenden Klammer muss eine schließende folgen, oder der Compiler verliert den Überblick.

Betrachten wir im Folgenden ein Beispiel, das die Vorteile von Arrays demonstriert. Listing 7.3 erzeugt ein dreidimensionales Array mit 1000 Elementen und füllt es mit Zufallszahlen. Anschließend gibt das Programm die Array-Elemente auf dem Bildschirm aus. Stellen Sie sich einmal vor, wie viele Codezeilen Sie benötigen würden, wenn Sie die gleiche Aufgabe mit normalen Variablen bewältigen wollten.

Sie finden in diesem Programm eine neue Bibliotheksfunktion namens getchar(). Diese Funktion liest ein einziges Zeichen von der Tastatur ein. In Listing 7.3 dient getchar() dazu, das Programm so lange anzuhalten, bis der Anwender die Eingabetaste betätigt hat. Näheres zur Funktion getchar() erfahren Sie am Tag 13.

Listing 7.3: Erzeugt ein mehrdimensionales Array.

1:   /* Beispiel für die Verwendung eines mehrdimensionalen Arrays */
2:
3: #include <stdio.h>
4: #include <stdlib.h>
5: /* Deklaration eines dreidimensionalen Arrays mit 1000 Elementen */
6:
7: int zufall_array[10][10][10];
8: int a, b, c;
9:
10: int main(void)
11: {
12: /* Füllt das Array mit Zufallszahlen. Die Bibliotheksfunktion */
13: /* rand() liefert eine Zufallszahl zurück. Verwenden Sie eine */
14: /* for-Schleife für jeden Array-Index. */
15:
16: for (a = 0; a < 10; a++)
17: {
18: for (b = 0; b < 10; b++)
19: {
20: for (c = 0; c < 10; c++)
21: {
22: zufall_array[a][b][c] = rand();
23: }
24: }
25: }
26:
27: /* Anzeige der Array-Elemente in Zehner-Einheiten */
28:
29: for (a = 0; a < 10; a++)
30: {
31: for (b = 0; b < 10; b++)
32: {
33: for (c = 0; c < 10; c++)
34: {
35: printf("\nzufall_array[%d][%d][%d] = ", a, b, c);
36: printf("%d", zufall_array[a][b][c]);
37: }
38: printf("\n Weiter mit Eingabetaste, Verlassen mit STRG-C.");
39:
40: getchar();
41: }
42: }
43: return 0;
44: } /* Ende von main() */

zufall_array[0][0][0] = 346
zufall_array[0][0][1] = 130
zufall_array[0][0][2] = 10982
zufall_array[0][0][3] = 1090
zufall_array[0][0][4] = 11656
zufall_array[0][0][5] = 7117
zufall_array[0][0][6] = 17595
zufall_array[0][0][7] = 6415
zufall_array[0][0][8] = 22948
zufall_array[0][0][9] = 31126
Weiter mit Eingabetaste, Verlassen mit STRG-C.

zufall_array[0][1][0] = 9004
zufall_array[0][1][1] = 14558
zufall_array[0][1][2] = 3571
zufall_array[0][1][3] = 22879
zufall_array[0][1][4] = 18492
zufall_array[0][1][5] = 1360
zufall_array[0][1][6] = 5412
zufall_array[0][1][7] = 26721
zufall_array[0][1][8] = 22463
zufall_array[0][1][9] = 25047
Weiter mit Eingabetaste, Verlassen mit STRG-C.
... ...
zufall_array[9][8][0] = 6287
zufall_array[9][8][1] = 26957
zufall_array[9][8][2] = 1530
zufall_array[9][8][3] = 14171
zufall_array[9][8][4] = 6951
zufall_array[9][8][5] = 213
zufall_array[9][8][6] = 14003
zufall_array[9][8][7] = 29736
zufall_array[9][8][8] = 15028
zufall_array[9][8][9] = 18968
Weiter mit Eingabetaste, Verlassen mit STRG-C.

zufall_array[9][9][0] = 28559
zufall_array[9][9][1] = 5268
zufall_array[9][9][2] = 20182
zufall_array[9][9][3] = 3633
zufall_array[9][9][4] = 24779
zufall_array[9][9][5] = 3024
zufall_array[9][9][6] = 10853
zufall_array[9][9][7] = 28205
zufall_array[9][9][8] = 8930
zufall_array[9][9][9] = 2873
Weiter mit Eingabetaste, Verlassen mit STRG-C.

Am Tag 5 haben Sie ein Programm mit einer verschachtelten for-Anweisung kennen gelernt. Dieses Programm weist zwei verschachtelte for-Anweisungen auf. Bevor wir jedoch die for-Anweisungen näher betrachten, möchte ich Sie auf die Zeilen 7 und 8 aufmerksam machen, in denen vier Variablen deklariert werden. Die erste ist ein Array namens zufall_array, das die Zufallszahlen aufnehmen soll. zufall_array ist ein dreidimensionales Array vom Typ int mit 10 mal 10 mal 10 Elementen, das heißt 1000 Elementen vom Typ int. Stellen Sie sich mal vor, es gäbe keine Array und Sie müssten sich statt dessen 1000 unverwechselbare Variablennamen ausdenken! Zeile 8 deklariert drei Variablen (a, b und c), die zur Steuerung der for-Schleifen dienen.

Dieses Programm bindet in Zeile 4 die Header-Datei stdlib.h (für Standard Library = Standardbibliothek) ein. Sie wird benötigt, um den Prototyp für die Funktion rand() in Zeile 22 bereitzustellen.

Der größte Teil des Programms steht in zwei verschachtelten for-Anweisungsblöcken. Die erste befindet sich in den Zeilen 16 bis 25, die zweite in den Zeilen 29 bis 42. Beide weisen die gleiche Struktur auf. Sie entsprechen den Schleifen in Listing 5.2, gehen aber noch eine Ebene tiefer. Im ersten for-Block wird die Zeile 22 wiederholt ausgeführt. Diese Zeile weist den Rückgabewert der Funktion rand() einem Element des Arrays zufall_array zu. rand() ist eine Bibliotheksfunktion, die eine Zufallszahl zurückgibt.

Gehen wir im Listing schrittweise zurück: Der Zeile 20 lässt sich entnehmen, dass die Variable c die Werte von 0 bis 9 annehmen kann. Damit wird der letzte (ganz rechts gelegene) Index des Arrays zufall_array in einer Schleife durchlaufen. Zeile 18 iteriert über b, den mittleren Index des Zufalls-Arrays. Jede Änderung von b bewirkt Schleifendurchläufe durch alle c-Elemente. Zeile 16 inkrementiert die Variable a, die für den Schleifendurchlauf des ersten Index zuständig ist. Jedes Mal, wenn dieser Index geändert wird, werden alle zehn Werte von Index b durchlaufen, die wiederum jeweils einen Schleifendurchlauf durch alle zehn Werte von c bewirken. Mit dieser Schleife initialisieren Sie jeden Wert in zufall_array mit einer Zufallszahl.

Die Zeilen 29 bis 42 enthalten den zweiten verschachtelten for-Anweisungsblock. Diese Zeilen sind den vorherigen for-Anweisungen vergleichbar, sind jedoch dafür zuständig, dass die oben zugewiesenen Werte ausgegeben werden. Nachdem zehn Werte angezeigt wurden, wird mit Zeile 38 eine Meldung ausgegeben, dass für weitere Werte die Eingabetaste gedrückt werden muss. Zeile 40 überwacht mit Hilfe von getchar() die Tastatur. Wurde die Eingabetaste noch nicht betätigt, wartet getchar() bis der Anwender die Eingabetaste drückt. Führen Sie das Programm aus und beobachten Sie die angezeigten Werte.

Maximale Array-Größe

Die maximale Größe eines Arrays unter Linux ist nur durch die Größe des Ihnen zur Verfügung stehenden Speicherbereichs in Ihrem Computer beschränkt. Als Programmierer brauchen Sie sich mit den internen Abläufen nicht zu befassen; das Betriebssystem kümmert sich um alles, ohne dass Sie eingreifen müssen.

Die Größe eines Arrays in Bytes hängt von der Anzahl der darin befindlichen Elemente ab sowie von der Elementgröße. Die Elementgröße wiederum basiert auf dem Datentyp des Arrays und auf Ihrem Computer.

Datentyp des Element s

Elementgröße (Bytes)

int

4

short

2

long

4

float

4

double

8

Tabelle 7.1: Speicherbedarf der numerischen Datentypen für die meisten PCs.

Um den Speicherbedarf eines Arrays zu ermitteln, müssen Sie die Anzahl der Elemente im Array mit der Elementgröße multiplizieren. So benötigt zum Beispiel ein Array mit 500 Elementen vom Typ float einen Speicherplatz von 500 x 4 = 2000 Byte.

Sie können den Speicherplatz innerhalb eines Programms mit Hilfe des C-Operators sizeof() ermitteln. sizeof() ist ein unärer Operator und keine Funktion. Er übernimmt als Argument einen Variablennamen oder den Namen eines Datentyps und gibt die Größe des Arguments in Bytes zurück. Ein Beispiel zu sizeof() finden Sie in Listing 7.4.

Listing 7.4: Einsatz des sizeof()-Operators, um den Speicherbedarf eines Arrays zu ermitteln.

1 : /* Beispiel für den sizeof()-Operator */
2 : #include <stdio.h>
3 :
4 : /* Deklariert mehrere Arrays mit 100 Elementen */
5 :
6 : int intarray[100];
7 : long longarray[100];
8 : float floatarray[100];
9 : double doublearray[100];
10:
11: int main(void)
12: {
13: /* Zeigt die Größe der numerischen Datentypen an */
14:
15: printf("\nGröße von short = %d Bytes", (int) sizeof(short));
16: printf("\nGröße von int = %d Bytes", (int) sizeof(int));
17: printf("\nGröße von long = %d Bytes", (int) sizeof(long));
18: printf("\nGröße von float = %d Bytes", (int) sizeof(float));
19: printf("\nGröße von double = %d Bytes", (int) sizeof(double));
20:
21: /* Zeigt die Größe der vier Arrays an */
22:
23: printf("\nGröße von intarray = %d Bytes",(int) sizeof(intarray));
24: printf("\nGröße von longarray = %d Bytes",(int) sizeof(longarray));
25: printf("\nGröße von floatarray = %d Bytes",
26: (int) sizeof(floatarray));
27: printf("\nGröße von doublearray = %d Bytes\n",
28: (int) sizeof(doublearray));
29:
30: return 0;
31: }

Im Folgenden sehen Sie die Ausgabe eines 32-Bit-Linux-Rechners mit einem Intel- Pentium-Prozessor.

Größe von short = 2 Bytes
Größe von int = 4 Bytes
Größe von long = 4 Bytes
Größe von float = 4 Bytes
Größe von double = 8 Bytes
Größe von intarray = 400 Bytes
Größe von longarray = 400 Bytes
Größe von floatarray = 400 Bytes
Größe von doublearray = 800 Bytes

Ein 64-Bit-Linux-Rechner mit einem DEC/Compaq-Alpha-Prozessor gibt Folgendes aus:

Größe von short = 2 Bytes
Größe von int = 4 Bytes
Größe von long = 8 Bytes
Größe von float = 4 Bytes
Größe von double = 8 Bytes
Größe von intarray = 400 Bytes
Größe von longarray = 800 Bytes
Größe von floatarray = 400 Bytes
Größe von doublearray = 800 Bytes

Geben Sie den Quellcode aus dem Listing ein und kompilieren Sie das Programm, wie Sie es am Tag 1 gelernt haben. Wenn das Programm ausgeführt wird, zeigt es die Größe (in Bytes) der vier Arrays und der fünf numerischen Datentypen an.

Dies Programm ähnelt dem Programm groessevon.c von Tag 2. Dieses Listing hier verwendet jedoch sizeof(), um den Speicherbedarf der Arrays zu bestimmen. Die Zeilen 6, 7, 8 und 9 deklarieren vier Arrays von jeweils unterschiedlichem Typ. Die Zeilen 23 bis 28 geben die Größen der Arrays aus. Die Größe sollte gleich der Größe des Array-Typ mal der Anzahl der Elemente sein. Wenn zum Beispiel iNT 4 Byte groß ist, sollte intarray 4 x 100 oder 400 Byte groß sein. Führen Sie das Programm aus und überprüfen Sie die Werte. Wie Sie an der Ausgabe ablesen können, kann es auf unterschiedlichen Rechnern oder Betriebssystemen unterschiedlich große Datentypen geben.

Zusammenfassung

Die heutige Lektion führte die numerischen Arrays ein - eine leistungsstarke Möglichkeit zur Datenspeicherung, mit der Sie eine Reihe von Datenelementen gleichen Typs unter dem gleichen Namen zusammenfassen können. Die einzelnen Elemente in einem Array werden anhand eines Indexes hinter dem Array-Namen identifiziert. Programmieraufgaben, bei denen Daten mit immer wiederkehrenden Anweisungen bearbeitet werden, lassen die Speicherung in Arrays ratsam erscheinen.

Wie normale Variablen müssen auch Arrays deklariert werden, bevor sie verwendet werden können. Bei Bedarf können die Array-Elemente bei der Deklaration des Arrays initialisiert werden.

Fragen und Antworten

Frage:
Was passiert, wenn ich für ein Array einen Index verwende, der größer ist als die Zahl der Elemente im Array?

Antwort:
Wenn Sie einen Index verwenden, der mit der Array-Deklaration nicht übereinstimmt, wird sich das Programm wahrscheinlich trotzdem kompilieren und ausführen lassen. Ein solcher Fehler kann jedoch zu unvorhersehbaren Ergebnissen führen. Zudem sind solche Fehler meist nur sehr schwer zu finden. Lassen Sie deshalb bei der Initialisierung und dem Zugriff auf Ihre Array-Elemente größte Sorgfalt walten lassen.

Frage:
Was passiert, wenn ich ein Array verwende, ohne es zu initialisieren?

Antwort:
Dieser Fehler löst keinen Compilerfehler aus. Wenn Sie ein Array nicht initialisieren, können die Array-Elemente einen beliebigen Wert annehmen. Das Ergebnis kann unvorhersehbar sein. Sie sollten Variablen und Arrays immer initialisieren, so dass Sie genau wissen, was darin enthalten ist. Am Tag 11 lernen Sie die eine Ausnahme hierzu kennen. Doch solange sollten Sie lieber auf Nummer sicher gehen.

Frage:
Wie viele Dimensionen kann ein Array haben?

Antwort:
Wie Sie in der heutigen Lektion schon erfahren haben, können Sie so viele Dimensionen angeben, wie Sie wollen. Doch je mehr Dimensionen Sie hinzufügen, umso mehr Speicherplatz benötigen Sie. Sie sollten ein Array nur so groß wie nötig deklarieren, um keinen Speicherplatz zu vergeuden.

Frage:
Gibt es eine einfache Möglichkeit, ein ganzes Array auf einmal zu initialisieren?

Antwort:
Jedes Element eines Arrays muss initialisiert werden. Der sicherste Weg für C-Anfänger besteht darin, ein Array entweder, wie heute gezeigt, im Zuge der Deklaration oder mit Hilfe einer for-Anweisung zu initialisieren. Es gibt noch andere Möglichkeiten, ein Array zu initialisieren, doch gehen diese über den Rahmen dieses Buches hinaus.

Frage:
Kann ich zwei Arrays addieren (oder multiplizieren, dividieren oder subtrahieren)?

Antwort:
Arrays können nicht addiert werden. Alle Elemente müssen einzeln addiert werden. Übung 10 soll dies veranschaulichen.

Frage:
Warum ist es besser, ein Array statt einzelner Variablen zu verwenden?

Antwort:
Mit Arrays können Sie gleiche Werte unter einem einzigen Namen zusammenfassen. In Listing 7.3 wurden 1000 Werte gespeichert. Das Erzeugen von 1000 Variablennamen und der Initialisierung jeder einzelnen Variablen mit einer Zufallszahl hätte einen gewaltigen Tippaufwand erfordert. Durch die Verwendung eines Arrays wurde die Aufgabe einfach.

Frage:
Was mache ich, wenn ich nicht weiß, wie groß das Array werden muss, wenn ich das Programm schreibe?

Antwort:
Es gibt Funktionen in C, mit denen Sie en passant Speicher für Variablen und Arrays allokieren können. Zu diesen Funktionen kommen wir aber erst am Tag 14.

Workshop

Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, sowie Übungen, die Sie anregen sollen, das Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Die Lösungen zu den Fragen und den Übungen finden Sie in Anhang C.

Quiz

  1. Welche Datentypen von C kann man in einem Array verwenden?
  2. Wie lautet der Index des ersten Elements eines Arrays, das für zehn Elemente deklariert wurde?
  3. Wie lautet der Index des letzten Elements in einem eindimensionalen Array mit
    n Elementen?
  4. Was passiert, wenn Ihr Programm versucht, auf ein Array-Element zuzugreifen, dessen Index außerhalb des Gültigkeitsbereiches liegt?
  5. Wie deklarieren Sie ein mehrdimensionales Array?
  6. Ein Array wird mit der folgenden Anweisung deklariert. Wie viele Elemente enthält das Array insgesamt?
    int array[2][3][5][8];
  7. Wie lautet der Name des zehnten Elements in dem Array aus Frage 6?

Übungen

  1. Schreiben Sie eine C-Programmzeile, die drei eindimensionale Integer-Arrays namens eins, zwei und drei mit jeweils 1000 Elementen deklariert.
  2. Setzen Sie eine Anweisung auf, die ein Integer-Array mit zehn Elementen deklariert und alle Elemente mit 1 initialisiert.
  3. Setzen Sie für das folgende Array Code auf, der alle Array-Elemente mit dem Wert 88 initialisiert:
    int achtundachtzig[88];
  4. Setzen Sie für das folgende Array Code auf, der alle Array-Elemente mit dem Wert 0 initialisiert:
    int stuff[12][10];
  5. FEHLERSUCHE: Was ist falsch an folgendem Codefragment?
    int x, y;
    int array[10][3];
    int main(void)
    {
    for ( x = 0; x < 3; x++ )
    for ( y = 0; y < 10; y++ )
    array[x][y] = 0;
    return 0;
    }
  6. FEHLERSUCHE: Was ist an folgendem Code falsch?
    int array[10];
    int x = 1;

    int main(void)
    {
    for ( x = 1; x <= 10; x++ )
    array[x] = 99;
    .
    return 0;
    }
  7. Schreiben Sie ein Programm, das Zufallszahlen in ein zweidimensionales Array von 5 mal 4 Elementen ablegt. Geben Sie die Werte in Spalten auf dem Bildschirm aus. (Hinweis: Verwenden Sie die rand()-Funktion aus Listing 7.3.)
  8. Schreiben Sie Listing 7.3 so um, dass es ein eindimensionales Array vom Typ short verwendet. Geben Sie den Durchschnitt der 1000 Variablen aus, bevor Sie die einzelnen Werte ausgeben (Hinweis: Vergessen Sie nicht, nach der Ausgabe von zehn Werten jeweils eine Pause einzuplanen.)
  9. Schreiben Sie ein Programm, das ein Array mit zehn Elementen initialisiert. Jedes Element soll den Wert seines Index zugewiesen bekommen. Das Programm sollte dann jedes der zehn Elemente ausgeben.
  10. Ändern Sie das Programm aus Übung 9. Nach der Ausgabe der initialisierten Werte soll das Programm die Werte in ein neues Array kopieren und zu jedem Wert 10 addieren. Geben Sie dann die neuen Werte aus.
  11. Sie haben inzwischen eine Reihe von Besonderheiten des GNU-C-Compilers kennen gelernt, die nicht Teil des ANSI-C-Standards sind. Verwenden Sie Ihren GNU-Informations-Editor und lesen Sie mehr darüber im Abschnitt »C Extensions« der gcc-Informationsseiten.


vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


© Markt&Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH