Arrays und Strukturen - Fachbereich Informatik Hochschule Darmstadt

Werbung
Zusammengesetzte Datentypen -Arrays und Strukturen
Informatik für Elektrotechnik und Informationstechnik
Benedict Reuschling
[email protected]
Hochschule Darmstadt
Fachbereich Informatik
WS 2013/14
Zuletzt aktualisiert:
25.11.2013, 12:55 Uhr
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Überblick
1 Arrays
Mehrdimensionale Arrays
2 Strukturen
2 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Motivation
Bis jetzt hatten wir Variablen so kennengelernt, dass diese nur einen
Wert speichern können. Sobald ein neuer Wert zugewiesen wird,
überschreibt dieser den vorherigen Wert. Für viele Anwendungsfälle
genügt es, einen Wert pro Variable zu speichern. Was aber tun, wenn
mehrere Werte des gleichen Typs eingelesen werden sollen?
Beispielsweise sollen Messwerte (von einem Sensor) eingelesen und
berechnet werden.
int messwert1, int messwert2, int messwert3, ...
Es muss eine bessere Lösung geben als vorsorglich eine grosse Menge
von einzelnen Variablen zu initialisieren, von denen evtl. gar nicht alle
gebraucht werden (Verschwendung von Speicherressourcen).
3 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Arrays deklarieren
Um mehrere Elemente des gleichen Datentyps (z.B. int, void ist nicht
erlaubt) zusammenzufassen gibt es in C++ Arrays (Felder). Der Zugriff
auf die Elemente des Arrays erfolgt über einen Index (0, 1, 2, . . . ).
Arrays sind statische Objekte, was bedeutet, dass die Anzahl der
abzuspeichernden Elemente vorher vom Programmierer festgelegt sein
muss. Allgemein werden Arrays folgendermassen deklariert:
datentyp name[AnzahlElemente];
Beispiel:
double meinArray[5];
Graphische Darstellung:
0
Wert1
1
Wert2
2
Wert3
3
Wert4
4
Wert5
4 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Index des Arrays festlegen
Der Index und die Grösse des Arrays müssen konstante, ganzzahlige
Werte sein. Deshalb funktionieren die folgenden Initialisierungen nicht.
Falsch:
int i = 5;
int testArray[i]; // i ist keine Konstante
const double d = 12;
double doubleArray[d]; // Keine Fliesskommawerte als Array-Index
Stattdessen stellen die folgenden Zeilen eine korrekte Initialisierung
dar:
Richtig:
int intArray[100];
const int groesse = 12;
double doubleArray[groesse]; // Verwendung einer const-Variable
char charArray[groesse*2]; // Ergebnis ist ein konstanter Wert
5 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Arrays initialisieren
Werte lassen sich an Arrays auf unterschiedliche Arten zuweisen. Die
gängigste Methode ist, dahinter in geschweiften Klammern eine mit
Komma getrennte Liste von Werten anzugeben.
int lottotip[6] = {3, 5, 12, 23, 30, 42} // ohne Gewähr
Die nächste Möglichkeit ist, nicht alle Werte zu belegen. Dann wird der
Default-Wert des jeweiligen Datentyps benutzt. Bei Zahlen ist dies die 0.
int meineWerte[3] = {1, 2}; // letzter Wert wird mit 0 belegt
int arraymitNullen[5] = {0}; // Initialisierung aller Werte mit 0
Eine weitere Möglichkeit besteht darin, das Array die Grösse anhand der
zugewiesenen Werte ermitteln zu lassen. Dazu lässt man den Wert in
eckigen Klammern einfach weg.
double messwerte[] = {12.3, 17.8, 5.5}; // ein Array der Groesse 3
6 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Array-Werte auslesen über den Index
Um auf die Werte des Arrays zuzugreifen, muss eine genaue Angabe
dazu gemacht werden, welches das gewünschte Element sein soll. Dies
passiert über die Angabe des Index, wobei die Indizierung bei 0 und nicht
bei 1 beginnt. Ein Array der Grösse N lässt sich bis zu einem maximalen
Index von N-1 ansprechen.
float notenwerte[] = {1, 1.3, 1.7, 2, 2.3, 2.7, 3, 3.3, 3.7, 4, 5};
cout << "Beste Note: " << notenwerte[0]; // erstes Element ausgeben
int punkte[5] = {23, 8, 15, 20, 17};
cout << punkte[3]; // gibt 20 aus
Um alle Werte auszugeben, eignet sich eine for-Schleife mit
Verwendung des Index als Abbruchbedingung:
1
2
3
4
const int GROESSE =6;
int lottotip [ GROESSE ] = {3 , 5 , 12 , 23 , 30 , 42} // ohne Gewaehr
for ( int i = 0; i < GROESSE ; i ++)
cout << i + 1 << " . Tippzahl : " << lottotip [ i ] << endl ;
7 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Einzelne Werte des Arrays ändern
Einzelne Werte lassen sich über die Angabe des Index ändern.
1
2
3
4
5
6
7
8
9
const int GROESSE = 5;
int messwerte [ GROESSE ] = {3 , 2 , 1000 , 7 , 5};
for ( int i = 0; i < GROESSE ; i ++)
cout << i + 1 << " . Messwert : " << messwerte [ i ] << " , " ;
cout << endl ;
messwerte [2] = 8;
for ( int i = 0; i < GROESSE ; i ++)
cout << i + 1 << " . Messwert : " << messwerte [ i ] << " , " ;
Andere Arraywerte lassen sich ebenfalls verwenden:
1
2
int myarray [3] = {13 , 28 , 32};
myarray [1] = myarray [2] - myarray [0];
8 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Mögliche Fehlerquelle bei unerlaubtem Zugriff
bei Arrays findet keine Überprüfung daraufhin statt, ob auf einen
erlaubten Bereich zugegriffen wird oder nicht. Der Programmierer muss
selbst dafür sorgen, dass kein ungültiger Zugriff wie dieser entstehen:
1
2
3
4
5
6
7
8
9
# include < iostream >
using namespace std ;
int testArray [4] = {17 , 4 , 21 , 39};
int main () {
cout << testArray [4] << endl ;
return 0;
}
Ein anderer unerlaubter Zugriff ist der folgende:
1
2
int testArray2 [3] = {5 , 6 , 7};
cout << testArray2 [ -3];
9 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Mehrdimensionale Arrays
Überblick
1 Arrays
Mehrdimensionale Arrays
2 Strukturen
10 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Mehrdimensionale Arrays
Mehrdimensionale Arrays definieren
Bisher haben wir Arrays nur eindimensional betrachtet. Beispielsweise
für Messwerte, die ein Sensor 6x am Tag liefert.
double sensor[6];
Wert 1
Wert 2
Wert 3
Wert 4
Wert 5
Wert 6
Wie speichert am aber Messwerte von 4 dieser Sensoren, welche z.B. an
anderen Positionen angebracht sind oder zu anderen Zeiten messen?
Lösung: Mehrdimensionale Arrays, die einer Matrix oder Tabelle
gleichen.
double sensoren[4][6];
Jede Zeile stellt die Messwerte eines eigenen Sensors dar.
Sensor 1
Sensor 2
Sensor 3
Sensor 4
Wert 1
Wert 1
Wert 1
Wert 1
Wert 2
Wert 2
Wert 2
Wert 2
Wert 3
Wert 3
Wert 3
Wert 3
Wert 4
Wert 4
Wert 4
Wert 4
Wert 5
Wert 5
Wert 5
Wert 5
Wert 6
Wert 6
Wert 6
Wert 6
11 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Mehrdimensionale Arrays
Mehrdimensionale Arrays -- Initialisierung und Zugriff
bool platzreservierung_privatkino[5][3] = { false };
Reihe 1
Reihe 2
Reihe 3
Reihe 4
Reihe 5
false
false
false
false
false
false
false
false
false
false
false
false
false
false
false
platzreservierung_privatkino[1][2] = true; // Reservierung erfolgt
Reihe 1
Reihe 2
Reihe 3
Reihe 4
Reihe 5
false
false
false
false
false
false
false
false
false
false
false
true
false
false
false
12 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Arrays
Mehrdimensionale Arrays
Mehrdimensionale Arrays durchlaufen
Genauso wie eindimensionale Arrays mit einer for-Schleife durchlaufen
werden, so lassen sich mehrdimensionale Arrays mit zwei
verschachtelten for-Schleifen ausgeben.
1
2
3
4
5
6
7
8
9
10
const int AUSSEN_MAX = 5;
const int INNEN_MAX = 3;
int myarray [ AUSSEN_MAX ][ INNEN_MAX ] = { false };
myarray [2][1] = true ;
for ( int lauf_aussen =0; lauf_aussen < AUSSEN_MAX ; lauf_aussen ++) {
for ( int lauf_innen =0; lauf_innen < INNEN_MAX ; lauf_innen ++) {
cout << "[" << lauf_aussen << " ][ " << lauf_innen << " ]: "
<< myarray [ lauf_aussen ][ lauf_innen ] << " " ;
}
cout << endl ; // Zeilenumbruch
}
13 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Überblick
1 Arrays
Mehrdimensionale Arrays
2 Strukturen
14 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Motivation
Bisher haben wir einzelne Datentypen eines Typs verwendet, z.B. int x.
Durch Arrays können wir eine Menge des gleichen Datentyps
gesammelt ablegen, z.B. int temperaturen[24]. Die einzige
Einschränkung, die uns noch verbleibt ist diejenige, dass es sich dabei
immer um den gleichen Datentyp handeln muss.
Unterschiedliche Datentypen lassen sich nicht so ohne weiteres
gemeinsam verwenden, da der Compiler vorher nicht wissen kann,
welche Datentypen wie mit einander kombiniert werden sollen. Da dies
vom Programmierer von einer Problemstellung zur anderen jedesmal
neu festgelegt wird, würde es auch keinen Sinn ergeben, alle möglichen
Kombinationen in der Programmiersprache vorzuhalten. Stattdessen
ermöglicht es C++ dem Programmierer, eigene Datentypen flexibel zu
definieren und Daten unterschiedlichen Typs strukturiert
abzuspeichern. Daher kommt auch der Name struct (engl. für
Struktur).
15 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Eigene Strukturen definieren
Die allgemeine Form, um eine Struktur in C++-Programmen zu
definieren, ist die folgende:
struct strukturname {
struct strukturname {
memberdatentyp1 membername1;
memberdatentyp1 membername1;
memberdatentyp2 membername2;
memberdatentyp2 membername2;
...
...
memberdatentypN membernameN;
memberdatentypN membernameN;
} name(n);
};
Eine Datenstruktur ist eine Gruppe von Datenelementen (members), die
unter dem gleichen Objektnamen (strukturname) zusammengefasst
sind. Ein konkretes Element dieser Zusammenfassung wird unter
seinem Namen (objektname) angesprochen. Sobald eine Datenstruktur
definiert ist, kann diese nicht mehr um weitere Member erweitert
werden. Es lassen sich aber weitere Strukturelemente erzeugen.
Dadurch wird klar, dass die Angabe name nicht gleich bei der Deklaration
erfolgen muss, sondern optional ist.
16 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Erstes Beispiel zu struct
Wir wollen einen Datentyp erstellen, um Produkte in unserem
Programm abzuspeichern. Ein Produkt besitzt eine Bezeichnung
(string) und einen Preis (float).
1
2
3
4
5
# include < string >
struct produkt {
string bezeichnung ;
float preis ;
}; // Achten Sie auf das abschliessende Semikolon !
Ein neues Produkt kann im Programm nach der Deklaration der
Struktur so angelegt werden:
produkt mobiltelefon ;
Eine zweite Möglichkeit ist dies direkt bei der Deklaration zu tun:
1
2
3
4
5
# include < string >
struct produkt {
string bezeichnung ;
float preis ;
} mobiltelefon ;
Mehrere solcher Objekte lassen sich durch Komma getrennt erzeugen.
17 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Zugriff auf Memberdatentypen von struct
Um Zugriff auf die Memberdatentypen zu erhalten, wird der
Punkt-Operator (.) verwendet. Er trennt dabei das konkret angelegte
Objekt auf der linken Seite vom Memberdatentyp rechts davon.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# include < iostream >
# include < string >
using namespace std ;
int main () {
struct produkt {
string bezeichnung ;
float preis ;
} handy ;
produkt stuhl ; // ein weiteres Objekt anlegen
handy . bezeichnung = " Klingeling 2000 " ;
handy . preis = 100;
stuhl . bezeichnung = " Bequemsitzer 900 " ;
// Preis steht noch nicht fest
cout << handy . bezeichnung << " kostet " << handy . preis << endl ;
cout << stuhl . bezeichnung << " kostet " << stuhl . preis << endl ;
return 0;
}
18 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Einlesen von Struktur-Membervariablen
Das Einlesen von Strukturvariablen geschieht ebenfalls durch den
Punktoperatorzugriff.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# include < iostream >
# include < string >
using namespace std ;
int main () {
struct Auto {
string name ;
int tueren ;
} userauto ;
cout << " Bitte Bezeichnung fuer das Auto eingeben : " ;
cin >> userauto . name ;
cout << " Bitte die Anzahl der Tueren eingeben : " ;
cin >> userauto . tueren ;
cout << " Name des Autos : " << userauto . name << endl ;
cout << " Anzahl Tueren : " << userauto . tueren << endl ;
return 0;
}
19 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Strukturen verschachteln
Strukturen können nicht nur primitive Datentypen wie char, int, float,
usw. aufnehmen. Sie sind auch in der Lage, andere Strukturen als
Membervariablen zu akzeptieren, wodurch verschachtelte Strukturen
entstehen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# include < string >
struct person {
string vorname ;
string nachname ;
};
struct buch {
person autor ; // verwendet struct person als Membervariable
string titel ;
};
buch thriller ;
thriller . autor . vorname = " Susi " ; // Zugriff auf struct person
thriller . autor . nachname = " Sonnenschein " ;
thriller . titel = " Schockierende Programme in C ++ " ;
Der Zugriff erfolgt also durch eine Aneinanderreihung von
Punktoperatoren, bis zur gewünschten, darunterliegenden Struktur.
20 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Arrays von Strukturen anlegen
Strukturen lassen sich auch als Arrays anlegen, so dass jedes Element
des Feldes ein struct beinhaltet.
1
2
3
4
5
6
7
8
9
10
11
12
const int MAX = 11; // soviel Freunde sollt ihr sein ...
struct spieler {
int trikotnummer ;
string name ;
} mannschaft [ MAX ];
for ( int i =0; i < MAX ;i ++) {
cout << " Name des Spielers Nr . " << i +1 << " : " ;
cin >> spieler [i ]. name ;
mannschaft [i ]. trikotnummer = i +1;
}
Beim Zugriff muss zuerst die Array-Indexposition angegeben werden
und anschliessend kann wie gewohnt mit dem Punktoperator auf die
Membervariablen zugegriffen werden.
21 / 22
Zusammengesetzte Datentypen --Arrays und Strukturen
Strukturen
Nachteile von structs
Ein Nachteil von Strukturen ist, dass man separate Prüfungen
durchführen muss, um diese mit korrektem Inhalt zu füllen. Die
Struktur kümmert sich nicht von selbst darum, um diese Logik sich
muss der Programmierer selbst kümmern.
Ein weiterer Nachteil ist, dass Objekte zwar Eigenschaften in Form ihrer
Membervariablen besitzen, aber mit diesen keine Aktionen direkt zu
verknüpfen sind. So können beispielsweise Autos eine Farbe, eine
Motordrehzahl und eine Menge an Rändern besitzen. Aber Aktionen wie
fahren, tanken oder parken, die nur dieses Objekt durchführen kann,
sind damit nicht möglich.
Um diese Probleme zu lösen, wurden in C++ sogenannte Klassen und
Objekte eingeführt. Diese können sowohl Eigenschaften besitzen, als
auch Verhalten (Aktionen) durchführen. Da struct ein Sprachmittel ist,
das von C übernommen wurde, stellen Klassen und Objekte von ihrer
Funktionalität her mächtigere Sprachmittel dar. Trotzdem gibt es
durchaus viele Anwendungsbereiche für structs.
22 / 22
Herunterladen