EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 5 Claudio...
-
Upload
rudolf-mori -
Category
Documents
-
view
106 -
download
0
Transcript of EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 5 Claudio...
EINI-IEINI-IEinführung in die Informatik Einführung in die Informatik für Naturwissenschaftler und für Naturwissenschaftler und
Ingenieure IIngenieure I
Kapitel 5
Claudio Moraga; Gisbert Dittrich
FBI Unido
2
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Gliederung Kapitel 5Gliederung Kapitel 5
• Zeiger– Grundbegriffe– Zeiger und Felder– Beispiel: Zeichenketten– Funktionen als Parameter– Mehrdimensionale Felder
3
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
VariableVariable
• 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: Zeiger Vorl “EINI-I"
20.11.2000
VariableVariable
• Anmerkungen:– Adresse: Eindeutiger Identifikator des Speicherplatzes
– Größe des Speicherplatzes abhängig vom Typ der Variablen.
– Bildliche Darstellungen:
oder auch:
WertAdresse
Name Typ nicht explizit
angegeben !
WertAdresse
Name-99
B
123
Beispiel:
Speicherplatz
5
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Grundbegriffe ZeigerGrundbegriffe 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
-99B
12301230
34567var
Beispiel:
6
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Grundbegriffe ZeigerGrundbegriffe Zeiger
-99B
12301230
34567var
Beispiel:
Gängige alternative Darstellung:
-99B
12301230
34567var
Beispiel:
-99B
1230var -99B
var-99var-99
B
12301230var
Beispiel:
7
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Grundbegriffe ZeigerGrundbegriffe 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: Zeiger Vorl “EINI-I"
20.11.2000
BeispieleBeispiele
&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: Zeiger Vorl “EINI-I"
20.11.2000
BeispieleBeispiele
Definiert seienint A=1, B=-99;
Nach ZeigerA = &A hat ZeigerA also als Wert die Adresse der Variablen A:
-99B
1A
ZeigerA
int *ZeigerA, *ZeigerB;D.h.: die Variablen ZeigerA und ZeigerB enthalten Adressen ganzer Zahlen.
ZeigerB
ZeigerA
10
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Beispiele (Forts.)Beispiele (Forts.)
-99B
-99A
ZeigerA
Nach *ZeigerA = B enthält der Speicherplatz,dessen Adresse ZeigerA ist, den Wert von B, also:
-99B
1A
ZeigerA
Situation nach:B = B * B;
9801B
-99A
ZeigerA
ZeigerBZeigerB = &B;*ZeigerA = *ZeigerB;
9801B
9801A
ZeigerA
Es gilt *ZeigerA == 1
11
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
MerkeMerke
• *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: Zeiger Vorl “EINI-I"
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 Tauschbleibt lokal aufdie Funktion
beschränkt (wg.call by value)
BeispielBeispiel
13
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
BeispielBeispiel
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: Zeiger Vorl “EINI-I"
20.11.2000
Beispiel (Bildchen)Beispiel (Bildchen)
30p
-121q
undeftemp
temp = *p;
*p = *q;
Dadurch ist sog. call by reference möglich
*q = temp;
30p
-121q
30temp
-121p
-121q
30temp
-121p
30q
30temp
15
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
// 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
Kap 5: Zeiger Vorl “EINI-I"
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: Zeiger Vorl “EINI-I"
20.11.2000
Felder und ZeigerFelder und Zeiger
• Sei deklariertint 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: Zeiger Vorl “EINI-I"
20.11.2000
Felder und ZeigerFelder 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: Zeiger Vorl “EINI-I"
20.11.2000
Felder und ZeigerFelder 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: Zeiger Vorl “EINI-I"
20.11.2000
Felder und ZeigerFelder und Zeiger
void strcpy (char nach[ ], char von[ ]) {int i = 0;while ((nach[i] = von[i]) ! = '\0') i++;}
Kopiert bekanntlich die Zeichenkette von indie Zeichenkette nach.
Die Zeichenketten werden als Felder dargestellt.
21
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Felder und ZeigerFelder 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: Zeiger Vorl “EINI-I"
20.11.2000
Felder und ZeigerFelder 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: Zeiger Vorl “EINI-I"
20.11.2000
Vergleich von ZeichenkettenVergleich 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: Zeiger Vorl “EINI-I"
20.11.2000
Vergleich von ZeichenkettenVergleich 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, solangesie identische Zeichen haben
tritt dabei das Ende einerKette auf, sind sie identisch
sonst wird dieDifferenz berechnet
25
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Vergleich von ZeichenkettenVergleich 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: Zeiger Vorl “EINI-I"
20.11.2000
// 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
Kap 5: Zeiger Vorl “EINI-I"
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: Zeiger Vorl “EINI-I"
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: Zeiger Vorl “EINI-I"
20.11.2000
#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
Kap 5: Zeiger Vorl “EINI-I"
20.11.2000
Funktionen als ParameterFunktionen 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: Zeiger Vorl “EINI-I"
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: Zeiger Vorl “EINI-I"
20.11.2000
#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 maxelse if (c == '0') f = min; //Zuweisung von min
else break;cout << (*f)(a,b) << '\n';}}
// 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
Kap 5: Zeiger Vorl “EINI-I"
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: Zeiger Vorl “EINI-I"
20.11.2000
Mehrdimensionale FelderMehrdimensionale 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.