EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 6 Claudio Moraga; Gisbert Dittrich FBI Unido [email protected] Vorl “EINI-I" Kap 6: Strukturen Gliederung Kapitel 6: Strukturen Vereinbarung für Zeichen auf char Zusammengesetzte Strukturen: struct Beispiel Buchdaten (einfach) Vereinbarung Zugriff u.a. unter Verwendung von Zeigern Verwendung Beispiel Buchdaten (komplexer) Karteikarte KarteLesen Aufruf Namensraum 22.11.2000 2 Vorl “EINI-I" Kap 6: Strukturen Vereinbarung für Zeichen auf char char Kette[]; // Deklaration einer Zeichenkette // unbestimmter Länge. Kette // ist gleichzeitig ein Zeiger zur // ersten Komponente des Feldes. char Kette[]= “Text“; // Definition einer // Zeichenkette mit dem Initialinhalt “Text“ Kurze Schreibweise (Vereinbarung): char * Kette = “Text“; 22.11.2000 3 Vorl “EINI-I" Kap 6: Strukturen Vereinbarung für Zeichen auf char Einige Autoren interpretieren die kurze Schreibweise wie folgt: „Der Datentyp für eine Zeichenkette ist char *, der einen Zeiger auf den Beginn der Zeichenfolge beschreibt, über den auf die Zeichenkette zugegriffen wird. Bei der Ausgabe einer Zeichenkette weißt der zu cout gehörende Ausgabeoperator <<, dass char * nicht als Zeiger, sondern als mit \0 terminierter Zeichenfolge aufzufassen ist.“ 22.11.2000 4 Vorl “EINI-I" Kap 6: Strukturen #include<iostream.h> void main ( ) { char feldname[ ]= "Frohe Weihnachten!"; char * zeigername; zeigername = &feldname[0]; cout << << cout << << cout << << "\n *zeigername = " *zeigername << endl; "\n uebernaechstes Symbol = " *(zeigername + 2) << endl; "\n zeigername = " zeigername << endl; 1 22.11.2000 5 Vorl “EINI-I" Kap 6: Strukturen // Nun nur die Abgekürtzte Definition: char * zeiger_alleine = "Guten Rutsch!"; cout << << cout << << cout << << cout << "\n *zeiger_alleine = " *zeiger_alleine << endl; "\n uebernaechstes Symbol = " *(zeiger_alleine + 2) << endl; "\n zeiger_alleine = " zeiger_alleine << endl; endl; 2 } 22.11.2000 Ausführen 6 Vorl “EINI-I" Kap 6: Strukturen Zusammengesetzte Strukturen Möchte die Daten von Büchern verwalten (Daten eines Buchs sollen logisch zusammengefügt werden). jahr (int) seiten BuchDaten (int) preis (float) 7 Vorl “EINI-I" Kap 6: Strukturen struct • Vereinbarung durch – Angabe der einzelnen Komponenten – mit Namen und Typ: Name der struct struct BuchDaten { int jahr, seiten; Typ der Komponenten float preis; }; Name der Komponenten 8 Vorl “EINI-I" Kap 6: Strukturen Anmerkungen zu struct • Name der Struktur ist zugleich Typname. – damit können Variable und Konstanten deklariert werden: BuchDaten meineDaten; Danach hat die Variable meineDaten den Typ BuchDaten • Zugriff auf die Komponenten (jahr, seiten, preis) durch Qualifikation: meineDaten.jahr 9 Vorl “EINI-I" Kap 6: Strukturen Anmerkungen zu struct • Beispiel (Zuweisung über Komponenten) meineDaten.jahr = GanzeZahlLesen("Jahr: "); meineDaten.seiten = GanzeZahlLesen("Seiten: "); meineDaten.preis = ReelleZahlLesen("Preis: "); • Andere Möglichkeit durch Zuweisung einer vollständigen struct (vom Typ BuchDaten) meineDaten = dieseDaten • Über Verwendung von Zeigern (analog) 10 Vorl “EINI-I" Kap 6: Strukturen Anmerkungen zu struct Zuweisung unter Verwendung von Zeigern: Z.B.: Gib die Adresse eines Elements von BuchDaten an, schreibe die eingelesenen Daten "an die entsprechende Adresse“ : BuchDaten meineDaten LiesBuchDaten (&meineDaten); Die Funktion LiesBuchDaten ist so definiert: 11 Vorl “EINI-I" Kap 6: Strukturen Anmerkungen struct Funktion LiesBuchDaten Signatur benutzter Funktionen Zeiger auf Typ BuchDaten int GanzeZahlLesen (char *); float ReelleZahlLesen (char *); void LiesBuchDaten (BuchDaten *bd) { bd->jahr = GanzeZahlLesen ("Jahr: "); bd->seiten = GanzeZahlLesen ("Seiten: "); bd->preis = ReelleZahlLesen ("Preis: "); } Zuweisung an Komponenten bd->jahr steht für (*bd).jahr 12 Vorl “EINI-I" Kap 6: Strukturen Anmerkungen struct • Also: – in der Funktionsdefinition wird als formaler Parameter verwendet • Zeiger auf Element vom Typ BuchDaten. – im Rumpf der Definition Zugriff durch Dereferenzieren • Beispiel: Die Komponente jahr wird angesprochen als (*bd).jahr, abgekürzt als bd->jahr – Aufruf : • Im Beispiel: mit konkreter Adresse &meineDaten LiesBuchDaten(&meineDaten) 13 Vorl “EINI-I" Kap 6: Strukturen Anmerkungen struct • Vereinbarung konstanter structs durch Angabe der Werte: const BuchDaten dieseDaten = {1997,234,14.70}; 14 Vorl “EINI-I" Kap 6: Strukturen Anmerkungen zu {..} • Allgemein: – Wertangaben bei der Definition zur gleichzeitigen Initialisierung mehrerer Werte können in geschweiften Klammern {..} angegeben werden. Weiteres Beispiel: char s[4] = {'a', 'b', 'c', ‘\0'}; (wirkt wie die Zeichenkette s="abc") 15 Vorl “EINI-I" Kap 6: Strukturen Beispiel Karteikarte für ein Buch soll enthalten: Verfasser Titel Verlag Zeichenkette, Länge autorMax Zeichenkette, Länge titelMax Zeichenkette, Länge verlagMax Buchdaten Typ BuchDaten 16 Vorl “EINI-I" Kap 6: Strukturen Beispiel const int autorMax = 75, titelMax = 100, verlagMax = 128; struct karteikarte { char autor [autorMax]; char titel [titelMax]; char verlag [verlagMax]; BuchDaten dieDaten; }; • Direkte Umsetzung der angegebenen Spezifikation für die Daten. • Strukturen können selbst Strukturen enthalten 17 Vorl “EINI-I" Kap 6: Strukturen Buchdatei void AngabeLesen (char *, char *, int); void LiesBuchDaten(Buchdaten *); void KarteLesen(int i, karteikarte * k){ cout << "Buch Nr. :" << (i + 1) << endl; AngabeLesen("Autor: ", k->autor, autorMax); AngabeLesen("Titel: ", k->titel, titelMax); AngabeLesen("Verlag : ", k->verlag, verlagMax); LiesBuchDaten (&(k->dieDaten)); } 18 Vorl “EINI-I" Kap 6: Strukturen KarteLesen/Buchdatei Der Aufruf KarteLesen (17, &ka) liest die Karte Nr. 17 ein und speichert sie unter der Adresse &ka (wobei vereinbart ist Karteikarte ka) Programm: KKarte als struct 19 Vorl “EINI-I" // // // // // Kap 6: Strukturen K6-P1 KKarte als Struct demonstriert structs Bei Behandlung von "Randfällen" nicht robust. Fehlerhaft !? #include <iostream.h> #include <stdio.h> const char ZeilenEnde = '\n', Null = '\0'; const int autorMax = 75, titelMax = 100, verlagMax = 128; struct BuchDaten { int jahr, seiten; float preis; } 1 22.11.2000 20 Vorl “EINI-I" Kap 6: Strukturen struct karteikarte { char autor[autorMax]; char titel[titelMax]; char verlag[verlagMax]; BuchDaten dieDaten; }; //Funktionsprototypen int GanzeZahlLesen(char *); float ReelleZahlLesen(char *); void LiesBuchDaten (BuchDaten *); void AngabeLesen(char *, char *, int); void KarteLesen(int, karteikarte *); void AutorAusgeben(karteikarte *); void TitelAusgeben(karteikarte *); const int n=2; 2 22.11.2000 21 Vorl “EINI-I" Kap 6: Strukturen main() { // const int n=2; karteikarte kartei[n],*zk; int i; cout << "Eingabe der Kartei-Karten:\n"; for (int i=0;i<n;i++) KarteLesen(i, &kartei[i]); zk = kartei; cout << "\nAusgabe der Autoren:\n"; for (i=0;i<n;i++) { AutorAusgeben(zk); TitelAusgeben(zk++); } cout << '\n' << "Fertig!" << endl; } 22.11.2000 3 22 Vorl “EINI-I" Kap 6: Strukturen void AngabeLesen(char * prompt, char * angabe, int maxWert){ int i = 0; cout << prompt << "(Zeichenkette)\t"; for (i = 0; (angabe[i] = getchar()) != ZeilenEnde && i < maxWert; i++); if (i <= maxWert) angabe[i] = Null; } void LiesBuchDaten (BuchDaten *bd) { bd->jahr = GanzeZahlLesen ("Jahr: "); bd->seiten = GanzeZahlLesen ("Seiten: "); bd->preis = ReelleZahlLesen ("Preis: "); } void KarteLesen(int i, karteikarte * k){ cout << “\nBuch Nr. :" << (i + 1) << endl; AngabeLesen("Autor: ", k->autor, autorMax); AngabeLesen("Titel: ", k->titel, titelMax); AngabeLesen("Verlag : ", k->verlag, verlagMax); LiesBuchDaten (&(k->dieDaten)); } 22.11.2000 4 23 Vorl “EINI-I" Kap 6: Strukturen int GanzeZahlLesen(char * prompt) { int i; cout << prompt << "(ganze Zahl)\t"; cin >> i; return i; } float ReelleZahlLesen(char * s) { float fl; cout << s << "(reelle Zahl)\t"; cin >> fl; return fl; } 22.11.2000 5 24 Vorl “EINI-I" Kap 6: Strukturen void AutorAusgeben(karteikarte * k){ cout << "Autor : " << k->autor << '\n'; } void TitelAusgeben(karteikarte * k){ cout << "Titel : " << k->titel << '\n'; } 6 Ausführen 22.11.2000 25 Vorl “EINI-I" Kap 6: Strukturen KarteLesen/Buchdatei Jedes struct hat seinen eigenen Namensraum struct eins { unabhängig int x; voneinander char *t; } struct zwei { float x; int t; } 26