1 / 35

EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I

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. Gliederung Kapitel 5. Zeiger Grundbegriffe Zeiger und Felder Beispiel: Zeichenketten Funktionen als Parameter

Download Presentation

EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Gliederung Kapitel 5 • Zeiger • Grundbegriffe • Zeiger und Felder • Beispiel: Zeichenketten • Funktionen als Parameter • Mehrdimensionale Felder

  3. 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. Adresse Wert Name -99 Adresse Wert 123 B Name Variable • Anmerkungen: • Adresse: Eindeutiger Identifikator des Speicherplatzes • Größe des Speicherplatzes abhängig vom Typ der Variablen. • Bildliche Darstellungen: oder auch: Speicherplatz Typ nicht explizit angegeben ! Beispiel:

  5. 34567 1230 var Beispiel: -99 1230 B 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

  6. Beispiel: 1230 1230 var 1230 var 34567 34567 1230 1230 var var var Beispiel: Beispiel: -99 -99 -99 -99 -99 -99 var 1230 1230 B B B B B Grundbegriffe Zeiger Gängige alternative Darstellung:

  7. Grundbegriffe Zeiger • SeivarVariablenname: &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. int k;float *t; Beispiele &kist die Adresse der ganzen Zahl k, tist alsZeiger auf eine Variable vom Typ floatdefiniert,beinhaltet also eine Adresseadreiner derartigen Variablen *t = 17.14speichert damit den Wert 17.14 unter dieser Adresse adr

  9. 1 -99 ZeigerA A B ZeigerB ZeigerA Beispiele • Definiert seien • int A=1, B=-99; • int *ZeigerA, *ZeigerB; • D.h.: die Variablen ZeigerA und ZeigerB • enthalten Adressen ganzer Zahlen. Nach ZeigerA = &A hat ZeigerA also als Wert die Adresse der Variablen A:

  10. -99 9801 -99 1 9801 -99 9801 -99 ZeigerA ZeigerA ZeigerA ZeigerA A A A A B B B B ZeigerB Beispiele (Forts.) Esgilt *ZeigerA == 1 Nach *ZeigerA = B enthält der Speicherplatz, dessen Adresse ZeigerA ist, den Wert von B, also: Situation nach: B = B * B; • ZeigerB = &B; • *ZeigerA = *ZeigerB;

  11. Merke • *ZeigerA spricht den Speicherplatz an, auf den ZeigerAzeigt: 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. Der Tausch bleibt lokal auf die Funktion beschränkt (wg. call by value) Beispiel Vertausche zwei Werte Was geschieht in Tausch? void Tausch (int a, int b) { int temp; temp = a; a = b; b = temp; }

  13. 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. p p p p q q q q 30 -121 30 -121 -121 -121 30 -121 temp temp temp temp 30 30 30 undef Beispiel (Bildchen) temp = *p; *p = *q; *q = temp; Dadurch ist sog. call by reference möglich

  15. // K5-P1: // Tauschen Adressen als Parameter // // Demonstriert Adressen als Parameter // #include <iostream.h> 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. 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. Felder und Zeiger • Sei deklariertint a[10], x, *pa; • Dann:pa = &a[0] setzt pa alsZeigerauf das ersteElement vona x = *pawürde alsoa[0]nachxkopieren.

  18. Felder und Zeiger • pa+1,..., pa+9 zeigen auf die Elemente a[1],...,a[9] • es gilt also *(pa+i) = a[i]füri = 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. 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. Felder und Zeiger void strcpy (char nach[ ], char von[ ]) {int i = 0;while ((nach[i] = von[i]) ! = '\0') i++;} Kopiert bekanntlich die Zeichenkette vonin die Zeichenkette nach. Die Zeichenketten werden als Felder dargestellt.

  21. 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. 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. Vergleich von Zeichenketten Sind a undb 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 gleichb ist, • strcmp(a, b) ist positiv, wenn a größer als b ist,

  24. Die Zeichenketten werden durchlaufen, solange sie identische Zeichen haben sonst wird die Differenz berechnet tritt dabei das Ende einer Kette auf, sind sie identisch 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;}

  25. Vergleich von Zeichenketten Version mit Feldernint 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. // K5-P2: Zeiger und Felder // // Demonstriert Zeiger und Felder // #include <iostream.h> 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. 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. Adr. v1 ... v1[9] v1[0] v1 ... Zur Erinnerung int v1[10]; int *z1; z1 = v1; z1 = z1+1; z1

  29. #include <iostream.h> 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. 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. Adr. Speicherbereich, wo das Programm der Funktion abgespeichert ist z char (*z)(char, char); Zeiger auf Funktionen; Namen von Funktionen BspFunktion Funktionsname char BspFunktion(char, char); // Funktionsprototyp // Zeiger auf Funktion gleicher Art // Übergabe der Adresse der Funktion z = BspFunktion; cout << (*z)(‘A‘, ‘B‘) << endl; // Funktionsaufruf über z

  32. #include<iostream.h> int max(int x, int y){ int min(int x, int y){ int k ; int k ; if (x > y) k = x; if (x < y) k = x; else k = y; else k = y; return k; } 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 <iostream.h> 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. 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. 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.

More Related