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:
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 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]]
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«.
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«.
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];
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", ¬en[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", ¬en[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
).
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.
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 };
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.
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.
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.
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.
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.
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.
n
Elementen?
int array[2][3][5][8];
eins
, zwei
und drei
mit jeweils 1000 Elementen deklariert.
1
initialisiert.
88
initialisiert:
int achtundachtzig[88];
0
initialisiert:
int stuff[12][10];
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;
}
int array[10];
int x = 1;
int main(void)
{
for ( x = 1; x <= 10; x++ )
array[x] = 99;
.
return 0;
}
rand()
-Funktion aus Listing 7.3.)
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.)