ein Kapitel zurück                                           ein Kapitel weiter

Bisher haben wir die speicherorientierten Strukturelemente auf einfache Datentypen beschränkt. Bei den Aufgaben hatten wir lediglich Ganze (char,int,long) oder Fließkommazahlen (float, double, long double) zur Verfügung. Jetzt und etwas später kommen wir zu den zusammengesetzten Datenstrukturen in C.

Mit Arrays haben sie die Möglichkeit ein geordnete Folge von Werten eines bestimmten Typs zu speichern und bearbeiten. Wenn sie jetzt ein Buch über C zur Hand haben und im Inhaltsverzeichnis über Arrays nichts finden können sie ja mal unter den Worten Vektor, Felder oder Reihungen(!) schauen.

Syntax :


int i[5];
char x[100];
float c[5000];


Erklärung : Durch z.B. der Variablen 'int i[5]' werden 5 Variablen im Array 'a' vom Typ 'int' definiert. Oder mit 'char x[100]' wird ein Array 'x' von 100 Elementen des Types 'char' definiert. Sehen wir uns mal 'int i[5]' genauer an....



Dies hier soll das Array 'i' mit 5 Elementen darstellen dessen Inhalt (Wert) noch nicht bekannt ist (Die Zahlen 1-5 sind nur Symbolisch).

Merke: Die Größe eines Arrays muss zum Zeitpunkt der Übersetzung bekannt sein. Ein sogenanntes 'dynamisches Array' ist eigentlich nicht für die Sprache C vorhergesehen !!!


Aber was heißt heutzutage schon muss? Ich werde Ihnen in einem Kapitel das zu einem späteren Zeitpunkt kommt zeigen das man es doch 'DYNAMISCH' machen kann.

So jetzt muss ich Ihnen erst mal noch Arrays viel genauer erklären bevor wir zu solchen Maßnahmen greifen.

Wie sieh der Abbildung zu 'int i[5]' sehen konnten haben wir damit 5 Arrays vom Typ 'int' definiert. Das heißt automatisch auch das auch Speicherplatz für 5 'int' - Werte definiert haben. Bei 4 Byte für eine 'int' Variable (je nach System) wären das 20 Bytes. Folglich verbratet ein Array 'double a[2000]' 16000 Bytes. Bei alten MSDOS - C Compilern kann es da schon mal zu Schwierigkeiten kommen, da der Speicher auf 64KB beschränkt ist. Aber auch hier gibt es wieder ein paar Tricks, die hier eigentlich jetzt nicht wichtig sind. Aber bei modernen 32 Bit Compilern wie z.B. der GNU-C kann 128MB Speicher plus 128MB virtuellem Speicher aufnehmen, brauchen sie sich keine Gedanken mehr darüber machen.

Jetzt wird es Zeit für ein kleines Programm bei dem gezeigt werden soll wie sie auf die einzelnen Felder zugreifen können.

/*Download:array1.c*/
#include <stdio.h>

int main()
{
int a[5]; /*Array mit 5 int Elementen*/

/*Wertzuweisungen an den einzelnen Arrays*/

a[0] = 5;
a[1] = 100;
a[2] = 66;
a[3] = 77;
a[4] = 1500;

/*Ausgabe der einzelnen Arrays*/

printf("Array a[0]= %d\n",a[0]);
printf("Array a[3]= %d\n",a[3]);
printf("Array a[4]= %d\n",a[4]);

return 0;
}

Hier haben wir jetzt allen 5 Feldern einen Wert mit Hilfe eines Index ( 'a[Index]' ) übergeben. Jetzt werden sie sich sicherlich fragen wo der der Index '[5]' ist. Nun für unseren Computer ist die Zahl 0 auch ein Wert. Und unser PC fängt somit mit 0 zum zählen an.



Sie sehen hier ja auch 5 Zahlen:0, 1, 2, 3, 4. Würden sie jetzt bei unserem Programm hinzufügen ....

int a[5] = 111;
printf("a[5] = %d\n",a[5]);


...werden sie den Compiler meckern hören oder schlimmsten wird Ihr PC sich mal wieder aufhängen. Den es sind nun mal 5 Adressen vom Typ 'int' reserviert worden. Schlimmer wird es wenn sie das ganze bei einer for-Schleife machen und denn Indexbereich überschreiten und sie einen Compiler besitzen der das zulässt. Schlimm deshalb weil ihnen Ihr Compiler überhaupt nichts dazu sagt. Er übernimmt irgendeinen Wert aus den unendlichen Weite des Speichers und die Werte mit denen sie dann Weiterarbeiten sind ....... unbrauchbar. Hier ein Beispiel eines solchen leider oft gemachten Fehler...

/*Download:array2.c*/
#include <stdio.h>

int main()
{
int test[10];
int i;

/*Achtung das Programm kann den Computer abstürzen lassen*/

for(i=0; i<=10; i++)
test[i]=i;

for(i=0; i<=10; i++)
printf("%d, ",test[i]);

return 0;
}

Das Programm eigentlich macht nichts anderes das es unser array 'test[10]' mit 11(!) Werten initialisiert (1.for - Schleife) und dann die 11(!) Werte auf dem Bildschirm ausgibt (2.for - Schleife). Haben sie den Fehler schon gefunden? Falls sie jetzt den Code schon mal wieder voreilig getestet haben und der Computer jetzt hängt werden sie wohl auf mich fluchen aber ich habe sie ja gewarnt!!! Der Fehler ist für Anfänger eigentlich auch gar nicht so leicht zu finden, da wir ja in der Schule gelernt haben von 1-10 zu zählen, aber ich habe etwas weiter oben erwähnt das der Computer von 0 anfängt zu zählen! Unser Fehler liegt in der for - Schleife.....

for(i=0; i<=10; i++)

...da unsere for - Schleife von 0-10 durchläuft und das sind 11 Zahlen (0,1,2,3,4,5,6,7,8,9,10). Wenn sie unser Programm jetzt ausführen wollen ohne das irgendwelches Murks passiert brauchen sie nur das '=' - Zeichen aus beiden for - Schleifen entfernen.....

for(i=0; i<10; i++)  //ohne '=' - Zeichen richtig

Also passen sie bei Array immer auf das sie den Wertbereich den sie in eckige Klammern stehen haben niemals Über.-bzw Unterschreiten.

Bei unserem Programm oben haben sie auch bereits gesehen wie auf unsere Array zugreifen können um einen Wert zu übergeben....

for(i=0; i<10; i++)
    test[i]=i;


Sie sehen hier das sie nicht immer Dezimalzahlen in das Indexfeld '[]' schreiben müssen. In unserem Fall ist es die Variable 'i' die ja vom Typ 'int' ist und somit auch eine Dezimalstelle enthält und von der for-Schleife bei jedem Durchlauf um 1 erhöht wird. Hier ein kurzer Ablauf des Programms...

i=0;
i<10; (wahr)
test[0]=0; (Wert von test[0] = 0)
i++; (i=1)
i<10; (wahr)
test[1]=1; (Wert von test[1] = 1)
i++; (i=2)
i<10 (wahr)
test[2]=2; (Wert von test[2] = 2)
......
......
i=3,4,5,6,7,8,9..
......
......
test[9]=9; (Wert von test[9] = 9)
i++; (i=10)
i<10; (unwahr -


Danach läuft es ähnlich bei der nächsten for - Schleife ab bei der unsere Zahlen mit...

for(i=0; i<10; i++)
     printf("%d, ",test[i]);


..ausgegeben werden. Auch hier dient wieder die Variable 'int i' als Index.

Mit unserem jetzigen Verständnis ist leider noch nicht möglich 2 Array direkt miteinander zu vergleichen wie zum Beispiel.....

int feld1[100],feld2[100];

for(i=0; i<100; i++)
{
   feld1[i]=i;
   feld2[i]=i;
}
if(feld1==feld2)
.....................


Diesen Feldvergleich würde immer ungleich sein obwohl der Inhalt unserer Werte gleich ist. Aber es gibt doch eine Möglichkeit zwei Arrays zu vergleichen ohne das Wissen was wir noch benötigen. Erst das Programm dazu.....

/*Download:array3.c*/
#include <stdio.h>
#include <string.h>

int main()
{
int Inhalt1[10],Inhalt2[10];
int i;

for(i=0; i<10; i++)
{
Inhalt1[i]=i;
Inhalt2[i]=i;
}

if(memcmp(Inhalt1,Inhalt2,sizeof(Inhalt1))== 0)
printf("Die beiden Arrays sind gleich !\n");
else
printf("Die beiden Arrays sind nicht gleich !\n");

return 0;
}

Zum Vergleich unserer beiden Arrays benutzen wir die Funktion 'memcmp' die in der Headerdatei '#include <string.h

Sie könne Arrays auch anders Initialisieren. Nämlich "manuell" wie bei den Variablen, die Werte müssen dabei zwischen geschweiften Klammern stehen...


int blubb[5] = {1,2,4,5,9};

Hiermit kommt es zu folgenden Werten....

blubb[0]=1;
blubb[1]=2;
blubb[2]=4;
blubb[3]=5;
blubb[4]=9;


Ein besonderer Vorteil ist es auch wenn man ein großes Array hat und man alle Werte erst mal mit 0 initialisieren muss. Anstatt eine ein for - Schleife wie...

int bigarray[1000];
for(i=0; i<1000; i++)
    bigarray[i]=i;


...kann man einfacher und kürzer machen mit...

int bigarray[1000]={0};

Das heißt jetzt wir haben hier das Array mit dem Index [0] also 'bigarray[0]' direkt mit 0 initialisiert und die restlichen 999 die nicht direkt initialisiert wurden sind automatisch ebenfalls 0. Ok ich gebe es zu das war jetzt verwirrend. Noch ein Beispiel....

double inhalt[100] = {2.4, 2.8, 9.45, 10.99};

Hiermit haben wir initialisiert.....

inhalt [0]=2.4
inhalt [1]=2.8
inhalt [2]=9.45
inhalt [3]=10.99
inhalt [4]=0
inhalt [5]=0
inhalt [6]=0
.............
.............
.............
inhalt[997]=0
inhalt[998]=0
inhalt[999]=0


Jetzt dürften sie verstehen was ich meine. Ab 'inhalt[4]' - 'inhalt[999]' sind alle Werte automatisch mit 0 initialisiert. Leider ist es aber nicht möglich den Inhalt der Array mit einem konstanten Wert außer 0 zu initialisieren.

Bevor wir weitermachen muss ich Ihnen noch schnell den Bezug der Initialisierungen von Arrays erklären. Hierzu ein Programm mit drei uninitialisierten int-Arrays....

/*Download:array4.c*/
#include <stdio.h>

int wert_global[5];

int main()
{
static int wert_static[5];
int wert_auto[5];
int i;

for(i=0; i<5; i++)
printf("%d:\t%10d\t%10d\t%10d\n",
i,wert_global[i],wert_static[i],wert_auto[i]);
return 0;
}

Die Ausgabe......

0:          0          0    -1073743848
1:          0          0    1073796368
2:          0          0    1073798384
3:          0          0    1075012248
4:          0          0    1075101484


Wenn sie das Programm ausführen werden sie bei der Ausgabe erkennen können, das das Globale und das mit static deklarierte Array 0 ausgeben. Nur unser automatisches Array wert_auto gibt einen undefinierten Wert zurück. Also können sie davon ausgehen, dass globale und mit static deklarierten Arrays immer automatisch mit 0 initialisiert werden.

Das ganze ändert sich, wie sie oben schon gelernt haben, wenn wir unsere Automatic-Variable mit mindestens einem Wert initialisieren....

/*Download:array5.c*/
#include <stdio.h>

int wert_global[5];

int main()
{
static int wert_static[5];
int wert_auto[5] = { 0};
int i;

for(i=0; i<5; i++)
printf("%d: %10d %10d %10d\n",
i,wert_global[i],wert_static[i],wert_auto[i]);

return 0;
}

Wir haben nur die Zeile...

int wert_auto[5] = {0};

..verändert und wert_auto[0] mit dem Wert 0 initialisiert. Die erneute Ausgabe des Programms wird nun mit lauter Nullen ausgeführt.

Eine häufige Frage lautet, wie kann man den Index (Anzahl der Elemente) eines Arrays herausfinden?
Sie haben ja schon den sizeof - Operator kennen gelernt, mit dem es möglich ist die Grösse eines Datentypes in Bytes zu bestimmen. Nehmen wir als Beispiel folgendes Array....

int zahlen[] = { 3,6,3,5,6,3,8,9,4,2,7,8,9,1,2,4,5};

Nun wollen wir den sizof-Operator dazu verwenden...

/*Download:bytear.c*/
#include <stdio.h>

int main()
{
int zahlen[] = {3,6,3,5,6,3,8,9,4,2,7,8,9,1,2,4,5};

printf("Anzahl der Elemente : %d\n",sizeof(zahlen));

return 0;
}

Bei Ausführung des Programms bekommen sie jetzt als Ergebniss bei 16bit-Systemen 34 und bei 32bit-Systemen 68 zurück. Das kann nicht ganz stimmen sagen sie jetzt. Der Wert 34 bzw. 68 stellt die Größe in Bytes unseres Arrays da. Um nun die Anzahl der Elemente zu bestimmen, müssen wir nur die Größe in Bytes geteilt durch die Größe des Datentypes rechnen und....

/*Download:indexar.c*/
#include <stdio.h>

int main()
{
int zahlen[] = {3,6,3,5,6,3,8,9,4,2,7,8,9,1,2,4,5};

printf("Anzahl der Elemente : %d\n",sizeof(zahlen)/sizeof(int));

return 0;
}

...jetzt bekommen sie als Ergebniss 17 Elemente zurück.

Häufig verwendet und oft gesehen ist die Bezeichnung des Index eines Arrays......

/*Download:indexar2.c*/
#include <stdio.h>
#define SIZE 10

int main()
{
int zahlen[SIZE] = {0};

printf("Anzahl der Elemente : %d\n",sizeof(zahlen)/sizeof(int));

return 0;
}

...was sich in längeren Programmen beim Ändern der Größe von SIZE vereinfacht.

Jetzt mal zu einem etwas umfangreicheren Beispiel was wir mit unseren Arrays machen können. Unser folgendes Programm soll eine Statistik auswerten. Und zwar die Statistik zwischen 2 Fußballmannschaften. Das Tor und das Punkteverhältnis der letzten 5 Spiele die Sie gegeneinander Angetreten sind......

/*Download:array6.c*/
#include <stdio.h>
/*Billanz aus 5 Spielen*/
#define SPIELE 5

/*Globale Variablen*/
int Bayern[SPIELE]={0};
int Borussia[SPIELE]={0};

static int count=0; /*Indexzaehler*/

/*Funktion zum zaehlen der Punkte*/
void punkte(int bm[], int bd[])
{
if(bm[count]>bd[count])
{
bm[count]=3; /*3Punkte für Bayern*/
bd[count]=0;
}
else if(bm[count]<bd[count])
{
bd[count]=3; /*3Punkte für Borussia*/
bm[count]=0;
}

else if(bm[count]==bd[count])
{
bm[count]=1; /*1Punkt für jeden - Unentschieden*/
bd[count]=1;
}
}

int main()
{
int tor1,tor2;
int tmptor1=0,tmptor2=0;
int i;

while(count!=SPIELE)
{
printf("%d. Spiel : Bayern - Borrusia\n",count+1);
printf("Tor(e) Bayern : ");
scanf("%d",&tor1);
Bayern[count]=tor1;
printf("Tor(e) Borussia : ");
scanf("%d",&tor2);
Borussia[count]=tor2;

tmptor1+=tor1; /*Tore zaehlen Bayern*/
tmptor2+=tor2; /*Tore zaehlen Borussia*/

punkte(Bayern,Borussia); /*Werte an Funktion punkte()*/
count++; /*Indexzaehler um 1 erhöhen*/
}

tor1=0; /*Inhalt von tor1 & tor2 auf 0 setzen*/
tor2=0;

for(i=0; i<SPIELE; i++) /*Gesamtpunkte aller Spiele*/
{
tor1+=Bayern[i];
tor2+=Borussia[i];
}

printf("\t\tBayern - Borussia\n");
printf("Punkte :\t %d - %d\n",tor1,tor2);
printf("Tore :\t %d - %d\n",tmptor1,tmptor2);

return 0;
}

Nun eine kurze Erklärung dazu...

int Bayern[SPIELE]={0};
int Borussia[SPIELE]={0};


Hiermit initialisieren unsere 5 Arrays mit dem Wert 0. Warum 5 Arrays. Die haben wir mit unserer Präprozessoranweisung '#define SPIELE 5' initialisiert. Sehr wichtig ist in diesem Programm die Globale Variable..

static int count=0;

Sie ist über unser ganzes Programm für alle Funktionen sichtbar. In unserer while - Schleife in dem Hauptprogramm werden sie aufgefordert das Endergebnis des Spieles einzugeben. Der Wert wird dann an unser Array mittels....

Bayern[count]=tor1;
.........................
Borussia[count]=tor2;


übergeben. Das heißt jetzt, nehmen wir an das Ergebnis wahr 2-1 für Bayern, dass unsere Arrays mit dem Index 0, da dies ja unser 1. Durchlauf ist und count den Wert 0 hat, folgende Werte bekommen....

Bayern[0]=2;
Borussia[0]=1;


Diese beiden Werte übergeben wir an unsere Funktion 'void punkte(......)' mittels...

punkte(Bayern,Borussia);

.....oder besser gesagt wir übergeben hier das ganze Array an unsere Funktion 'punkte()'. Dort überprüfen wir mittels 'if-else' - Anweisungen welcher der beiden Werten höher ist. Wir übergeben zwar das ganze Array an unsere Funktion, uns aber interessiert nur das aktuellen Ergebnis das wir mittels unseren Index '[count]' erhalten. In unserem Beispiel ist folgende Bedienung wahr......

if(bm[count]
   {
     bm[count]=3;   //3Punkte für Bayern
     bd[count]=0;
   }


Somit bekommen unsere Arrays folgende Werte.......

bm[0]=3    //Steht für Bayern
bd[0]=0    //Steht für Borussia


Wenn Borussia siegen sollte geht eben in unserer Funktion 'punkte()' zur nächsten Abfrage und die Werte der beiden Arrays sind halt genau andersrum. Die letzte 'else-if'- Anweisung steht für ein Unentschiednen und jede Mannschaft bekommt einen Punkt. Danach geht es wieder zurück in unsere 'main()' - Funktion genauer in unsere 'while' -Schleife. Und dort wird mittels......

count++;

unser Indexzähler um 1 erhöht und wir kommen zur nächsten Abrage (Spiel) der Werte für....

Bayern[1]=...... und Borussia[1]=......

Wir geben solange Ergebnisse ein bis unser.....

while(count!=SPIELE)

unwahrheitsgemäß abbricht. Anschließend berechnen wir mit unserer for - Schleife die Gesamtpunktzahl von jedem Team und geben sie dann auf dem Bildschirm aus. Bei unserer Funktion punkte() haben sie jetzt gesehen das es doch möglich ist Arrays zu vergleichen mit Hilfe des Indexes '[]'. Noch mal schriftlich.....

if(bm==bd)    //So ist es FALSCH

if(bm[0]==bd[0])    //So ist es RICHTIG


Es gibt noch eine weiter Möglichkeit auf den Inhalt eines Arrays zuzugreifen. Hier ein Programmbeispiel dazu.....

/*Download:array7.c*/
#include <stdio.h>
#define MAX 5

/*Demonstration zum Zugriff auf Array mit dem Index*/

int x[MAX]; /*Globales Array*/

int main()
{
int i;

for(i=0; i<MAX; i++)
{
printf("%d. Wert : ",i+1);
scanf("%d",&x[i]);
}

/*Ausgabe*/
i=0;
printf("%d, ",x[i]); /*1.Zahl x[0]*/
printf("%d, ",x[i+4]); /*5.Zahl x[4]*/
i=3;
printf("%d, ",x[i-3]); /*1.Zahl x[0] da x[3-3] */
printf("%d, ",x[i-1]); /*3.Zahl x[2]*/
printf("%d, ",x[2+1]); /*4.Zahl x[3]*/
printf("%d, ",x[2*2]); /*5.Zahl x[4]*/
printf("%d, ",x[6/3]); /*3.Zahl x[2]*/
printf("%d, ",x[100/2-50]); /*1.Zahl x[0]*/
printf("\n");

/*Inkrementieren*/
i=0;
while(i<MAX)
printf("%d, ",x[i++]);

printf("\n");

/*Dekrementieren*/
i=MAX-1; /*Achtung auf das -1 !Nicht vergessen!*/
while(i>=0)
printf("%d, ",x[i--]);

return 0;
}

Sie sehen das es auch möglich ist in dem Indexfeld des Arrays, Berechnungen auszuführen, Inkrementieren und Dekrementieren. Natürlich macht es keine Sinn auf eine Index mittels...

array[100-50/2]

zuzugreifen. Dies dient lediglich zum besseren Verständnis zur Behandlung unseres Indexes. Denn wenn sie das Verstehen wird Ihnen das Thema Array auch nicht mehr schwer fallen.

Das Einlesen von Array mit scanf funktioniert ebenfalls mit Hilfe des Index. Beispiel....

int x[10];
scanf("%d",&x[0]);   //Eingabe des 1 Wertes im Array


Sie merken schon das die Themen langsam schwieriger werden. Erwarten sie nicht von heute auf morgen Erleuchtung. Vor allem wichtig ist. Nicht aufgeben und den Quellcode genau studieren.

Aufgabe 1
Schreiben sie ein Programm das sie Aufordert Zahlen in ein Array der Größe ihrer Wahl einzugeben und diese dann der Größe nach sortiert.

Aufgabe 2
Schreiben sie unser Fußballprogramm von oben so um, bzw. schreiben sie es so damit wie gewohnt nach der Eingabe der Tore abfragt von welchem Spiel sie das Ergebnis wissen wollen.

Hier geht's zu den Lösungen!

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf