Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 5 Claudio Moraga; Gisbert Dittrich FBI Unido

Ähnliche Präsentationen


Präsentation zum Thema: "EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 5 Claudio Moraga; Gisbert Dittrich FBI Unido"—  Präsentation transkript:

1 EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 5 Claudio Moraga; Gisbert Dittrich FBI Unido moraga@cs.uni-dortmund.de

2 Kap 5: ZeigerVorl EINI-I" 2 20.11.2000 Gliederung Kapitel 5 Zeiger –Grundbegriffe –Zeiger und Felder –Beispiel: Zeichenketten –Funktionen als Parameter –Mehrdimensionale Felder

3 Kap 5: ZeigerVorl EINI-I" 3 20.11.2000 Variable hat: –Namen –Typ u.a. Wertebereich, aus dem Werte angenommen werden –Wert (aus dem Wertebereich oder "undefiniert") ist realisiert im Speicher durch: –Speicherplatz, der hat : Adresse Anmerkung: Nicht immer alle Angaben verfügbar !

4 Kap 5: ZeigerVorl EINI-I" 4 20.11.2000 Variable Anmerkungen: –Adresse: Eindeutiger Identifikator des Speicherplatzes –Größe des Speicherplatzes abhängig vom Typ der Variablen. –Bildliche Darstellungen: oder auch: Wert Adresse Name Typ nicht explizit angegeben ! Wert Adresse Name -99 B 123 Beispiel: Speicherplatz

5 Kap 5: ZeigerVorl EINI-I" 5 20.11.2000 Grundbegriffe Zeiger Neu: Adressen können jetzt Werte von Variablen sein !! (Typisiert!) Zeiger: –Vereinbarung: T *var ; –var ist Variablenname, der Adressen von Variablen vom Typ "T" annimmt. Typ int -99 B 1230 34567 var Beispiel:

6 Kap 5: ZeigerVorl EINI-I" 6 20.11.2000 Grundbegriffe Zeiger -99 B 1230 34567 var Beispiel: Gängige alternative Darstellung: -99 B 1230 34567 var Beispiel: -99 B 1230 var -99 B var -99 var -99 B 1230 var Beispiel:

7 Kap 5: ZeigerVorl EINI-I" 7 20.11.2000 Grundbegriffe Zeiger Sei var Variablenname: &var liefert die Adresse von var Sei wo Name eines Zeigers (Speicherreferenz), so liefert *wo die Variable, auf die wo zeigt. Referenzen sind typisiert: es wird angegeben, welcher Typ sich hinter einer Adresse verbirgt (z. B. Referenz auf einen Wert vom Typ int ).

8 Kap 5: ZeigerVorl EINI-I" 8 20.11.2000 Beispiele &k ist die Adresse der ganzen Zahl k, t ist als Zeiger auf eine Variable vom Typ float definiert, beinhaltet also eine Adresse adr einer derartigen Variablen *t = 17.14 speichert damit den Wert 17.14 unter dieser Adresse adr int k; float *t;

9 Kap 5: ZeigerVorl EINI-I" 9 20.11.2000 Beispiele Definiert seien int A=1, B=-99; Nach ZeigerA = &A hat ZeigerA also als Wert die Adresse der Variablen A : -99 B 1 A ZeigerA int *ZeigerA, *ZeigerB; D.h.: die Variablen ZeigerA und ZeigerB enthalten Adressen ganzer Zahlen. ZeigerBZeigerA

10 Kap 5: ZeigerVorl EINI-I" 10 20.11.2000 Beispiele (Forts.) -99 B A ZeigerA Nach *ZeigerA = B enthält der Speicherplatz, dessen Adresse ZeigerA ist, den Wert von B, also: -99 B 1 A ZeigerA Situation nach: B = B * B; 9801 B -99 A ZeigerA ZeigerB ZeigerB = &B; *ZeigerA = *ZeigerB; 9801 B A ZeigerA Es gilt *ZeigerA == 1

11 Kap 5: ZeigerVorl EINI-I" 11 20.11.2000 Merke *ZeigerA spricht den Speicherplatz an, auf den ZeigerA zeigt: weil ZeigerA eine Referenz ist, gibt *ZeigerA den Inhalt dieser Referenz an (man spricht von Dereferenzieren: von der Referenz/Adresse zum dadurch bez. Speicherplatz übergehen) &B auf der linken Seite einer Zuweisung ist illegal: die Adressen werden von Compiler oder vom Laufzeitsystem gesetzt, aber nicht vom Benutzer

12 Kap 5: ZeigerVorl EINI-I" 12 20.11.2000 Vertausche zwei Werte Was geschieht in Tausch ? void Tausch (int a, int b) { int temp; temp = a; a = b; b = temp; } Der Tausch bleibt lokal auf die Funktion beschränkt (wg. call by value) Beispiel

13 Kap 5: ZeigerVorl EINI-I" 13 20.11.2000 Beispiel Was geschieht in AdrTausch ? void AdrTausch(int *p, int *q) { int temp; temp = *p; *p = *q; *q = temp; } temp nimmt den Inhalt von * p auf Der Inhalt von * q wird als Inhalt von * p gespeichert Der Inhalt von * q ist der in temp gespeicherte Wert

14 Kap 5: ZeigerVorl EINI-I" 14 20.11.2000 Beispiel (Bildchen) 30 p -121 q undef temp temp = *p; *p = *q; Dadurch ist sog. call by reference möglich *q = temp; 30 p -121 q 30 temp -121 p q 30 temp -121 p 30 q temp

15 Kap 5: ZeigerVorl EINI-I" 15 20.11.2000 // K5-P1: // Tauschen Adressen als Parameter // // Demonstriert Adressen als Parameter // #include void Tausch (int, int); void AdrTausch(int *, int *); // Funktionsprototypen main() { void Tausch(int, int); void AdrTausch(int *, int *); int x = 30, y = -121; cout << "vor Tausch: x = " << x << ", y = " << y << endl; Tausch(x, y); cout << "nach Tausch: x = " << x << ", y = " << y << endl; cout << "oh! (klar: call by value)\n"; cout << "vor AdrTausch: x = " << x << ", y = " << y << endl; AdrTausch(&x, &y); cout << "nach AdrTausch: x = " << x << ", y = " << y << endl; }

16 Kap 5: ZeigerVorl EINI-I" 16 20.11.2000 void Tausch (int a, int b) { int temp; temp = a; a = b; b = temp; } void AdrTausch (int *p, int *q) { int temp; temp = *p; *p = *q; *q = temp; } Ausführen

17 Kap 5: ZeigerVorl EINI-I" 17 20.11.2000 Felder und Zeiger Sei deklariert int a[10], x, *pa; Dann: pa = &a[0] setzt pa als Zeiger auf das erste Element von a x = *pa würde also a[0] nach x kopieren.

18 Kap 5: ZeigerVorl EINI-I" 18 20.11.2000 Felder und Zeiger pa+1,..., pa+9 zeigen auf die Elemente a[1],...,a[9] –es gilt also *(pa+i) = a[i] für i = 0,..., 9 Allgemein: ist deklariert T *p;(p ist also ein Zeiger auf Elemente vom Typ T ), dann bezeichnet p+i das Element vom Typ T, das von p um i*sizeof(T) entfernt liegt.

19 Kap 5: ZeigerVorl EINI-I" 19 20.11.2000 Felder und Zeiger pa ist eine Zeiger-Variable, a ist ein Feld mit Elementen vom Typ int, also sind z. B. a=pa, a++ illegal. Bei Funktionsaufrufen werden Felder als aktuelle Parameter als Zeiger auf das jeweils erste Element interpretiert! Damit erklärt sich, daß Kopiere korrekt funktioniert.

20 Kap 5: ZeigerVorl EINI-I" 20 20.11.2000 Felder und Zeiger void strcpy (char nach[ ], char von[ ]) { int i = 0; while ((nach[i] = von[i]) ! = '\0') i++; } Kopiert bekanntlich die Zeichenkette von in die Zeichenkette nach. Die Zeichenketten werden als Felder dargestellt.

21 Kap 5: ZeigerVorl EINI-I" 21 20.11.2000 Felder und Zeiger void strcpy (char *s, *t) { while ((*s++ = *t++) ! = '\0' ); } *s++ dereferenziert s und schaltet die Adresse dann um sizeof(char) weiter [also zu lesen (*s)++ ].

22 Kap 5: ZeigerVorl EINI-I" 22 20.11.2000 Felder und Zeiger merke: ( *s++ = *t++) ! = '\0' liefert den Wert 0, falls das Ende der Zeichenkette t erreicht ist (dann soll ja auch die while -Schleife abbrechen) die eigentliche Arbeit findet in dieser Zuweisung statt, daher ist der Anweisungsblock in der while -Schleife leer.

23 Kap 5: ZeigerVorl EINI-I" 23 20.11.2000 Vergleich von Zeichenketten Sind a und b Zeichenketten, so soll der ganzzahlige Wert strcmp(a, b) den lexikographischen Vergleich von a und b ermöglichen. Es soll gelten: –strcmp(a, b) ist negativ, wenn a kleiner als b ist, –strcmp(a, b) ist Null, wenn a gleich b ist, –strcmp(a, b) ist positiv, wenn a größer als b ist,

24 Kap 5: ZeigerVorl EINI-I" 24 20.11.2000 Vergleich von Zeichenketten int strcmp (char *s, char *t) { int k = 1; for (;*s == *t; s++, t++) if (*s == '\0') k = 0; if (k > 0) k = (*s - *t); return k; } Die Zeichenketten werden durchlaufen, solange sie identische Zeichen haben tritt dabei das Ende einer Kette auf, sind sie identisch sonst wird die Differenz berechnet

25 Kap 5: ZeigerVorl EINI-I" 25 20.11.2000 Vergleich von Zeichenketten Version mit Feldern int strcmp (char s[], char t[]) { int i = 0, k = 1; while (s[i] == t[i]) if (s[i++] == '\0') k = 0; if (k > 0) k =(s[i] - t[i]); return k; } Felder und Zeiger

26 Kap 5: ZeigerVorl EINI-I" 26 20.11.2000 // K5-P2: Zeiger und Felder // // Demonstriert Zeiger und Felder // #include main(){ int v1[10]; int i; // Feld v1 initialisieren cout << "ursprüngliches Feld v1:\n"; for (i=0;i<10;i++) { v1[i] = 100 + i; cout << v1[i] << " "; }

27 Kap 5: ZeigerVorl EINI-I" 27 20.11.2000 cout << "\n\n" << "kopiertes Feld z1:\n"; // kopieren und Ausgabe ueber Zeiger int *z1; z1 = v1; for (i=0;i<10;i++){ cout << *z1 << " "; z1=z1+1; } cout << '\n'; } Ausführen

28 Kap 5: ZeigerVorl EINI-I" 28 20.11.2000 v1... int v1[10]; int *z1; z1 z1 = v1; Zur Erinnerung v1... Adr. v1[0] v1[9] z1 = z1+1;

29 Kap 5: ZeigerVorl EINI-I" 29 20.11.2000 #include main(){ int v1[10]; int i; cout << "ursprüngliches Feld v1:\n"; for (i=0;i<10;i++) { v1[i] = 100 + i; cout << v1[i] << " "; } cout << "\n\n" << "kopiertes Feld z1:\n"; int *z1; z1 = v1; for (i=0;i<10;i++){ cout << *z1 << " "; z1=z1+1; } cout << '\n'; } // Feldname als Zeiger

30 Kap 5: ZeigerVorl EINI-I" 30 20.11.2000 Funktionen als Parameter In C++ nicht direkt möglich. Wohl aber: Übergabe eines Zeigers auf eine Funktion Zeiger auf Funktionen Beachte: int (*f)() im Vergleich zu int *f(): int (*f)(): Zeiger auf eine Funktion ohne Argumente mit Rückgabe Wert int int *f(): Funktion ohne Argument, die einen Zeiger auf int zurückgibt

31 Kap 5: ZeigerVorl EINI-I" 31 20.11.2000 Zeiger auf Funktionen; Namen von Funktionen Funktionsname Speicherbereich, wo das Programm der Funktion abgespeichert ist Adr. BspFunktion char BspFunktion(char, char); // Funktionsprototyp char (*z)(char, char); z z = BspFunktion; cout << (*z)(A, B) << endl; // Funktionsaufruf über z // Übergabe der Adresse der Funktion // Zeiger auf Funktion gleicher Art

32 Kap 5: ZeigerVorl EINI-I" 32 20.11.2000 #include int max(int x, int y){ int min(int x, int y){ int k ; if (x > y) k = x; if (x < y) k = x; else k = y; return k; } main ( ) { int a = 1936, b = 6391; int (*f)(int, int); //Zeiger auf Funktion while(1) { char c; cout <<"(max = 1),(min = 0),(abbruch = sonst)?\n"; cin >> c; if (c == '1') f = max; //Zuweisung von max else if (c == '0') f = min; //Zuweisung von min else break; cout << (*f)(a,b) << '\n';}}

33 // Zeiger auf Funktionen // // Demonstriert Zeiger auf Funktionen // #include int sum1(int); int sum2(int); int Summiere(int (*f)(int)); main() { cout << "\terste Summe: " << Summiere(sum1) << "\n\n"; cout << "\tzweite Summe: " << Summiere(sum2) << endl; } // Funktionsprototypen

34 Kap 5: ZeigerVorl EINI-I" 34 20.11.2000 int sum1(int n) { int i, s = 0; for(i = 0; i < n; i++) s = s + 1; return s; } int sum2(int n) { int i, s = 0; for(i = 0; i < n; i++) s = s - 2; return s; } int Summiere(int (*f)(int)) { int lauf, sum=0; for (lauf = 0; lauf < 7; lauf++) { cout << "(*f)(" << lauf << ") = " << (*f)(lauf) << endl; sum = sum + (*f)(lauf); } return sum; } Ausführen

35 Kap 5: ZeigerVorl EINI-I" 35 20.11.2000 Mehrdimensionale Felder In C++ sind mehrdimensionale Felder möglich (Details später). Beispiel: int matrix [3][7] –beschreibt eine Matrix mit drei Zeilen und sieben Spalten, deren Elemente vom Typ int sind, –Beachte: int matrix [3][7] beschreibt 7 Elemente vom Typ int matrix [3]. –int matrix [3, 7] ist in C++ syntaktisch nicht legal.


Herunterladen ppt "EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 5 Claudio Moraga; Gisbert Dittrich FBI Unido"

Ähnliche Präsentationen


Google-Anzeigen