Präsentation herunterladen
Veröffentlicht von:Hanke Ehrenberg Geändert vor über 10 Jahren
1
Einführung in die Programmiersprache C 4
Einführung in die Programmiersprache C 4.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig
2
Zeiger bei Matrizen Es kann nötig sein, eine Matrix zu kopieren, um bei Veränderungen noch auf die Originaldaten zurückgreifen zu können. Das geht nicht so: double **mat,**copy; ... copy=mat; Hier werden nicht die Inhalte der Matrix kopiert, sondern nur der Zeiger auf den Beginn des Speicherbereichs. Veränderungen von Einträgen von mat führen auch zur Veränderung der Einträge von copy. Institut für Mathematische Optimierung – Technische Universität Braunschweig
3
Zeiger bei Matrizen Institut für Mathematische Optimierung – Technische Universität Braunschweig
4
Andere Operationen Sollen hingegen zwei Matrizen oder Zeilen von Matrizen getauscht werden, so können auch nur die Zeiger getauscht werden: double **mat; **copy, **temp1, *temp2; ... temp1 = mat; mat = copy; copy = temp1; temp2 = mat[17]; mat[17] = mat[43]; mat[43] = temp2;
5
Lösung double **mat, **copy; mat=alloc_matrix(zeilen,spalten);
Die Inhalte müssen elementweise kopiert werden. Dabei müssen die Matrixdimensionen jeweils gleich sein und Speicher für beide Matrizen besorgt werden: double **mat, **copy; mat=alloc_matrix(zeilen,spalten); copy=alloc_matrix(zeilen,spalten); for... copy[i][j]=mat[i][j]; Institut für Mathematische Optimierung – Technische Universität Braunschweig
6
Speicher für Matrizen freigeben
Der für Matrizen besorgte Speicher muss iterativ wieder freigegeben werden: void freeintmatrix(int **matrix, int zeile) { int i; for(i=0;i<zeile;i++) free(matrix[i]); free(matrix); } Institut für Mathematische Optimierung – Technische Universität Braunschweig
7
Aufgabe Schreiben Sie zwei Funktionen, die dynamisch Speicher reservieren und diesen zurückgeben. Eine Funktion soll dabei Speicher für ein eindimensionales Feld (array) freigeben und die andere Speicher für ein mehrdimensionales Feld (Typ Matrix). Implementieren Sie außerdem eine Funktion, die den für mehrdimensionale Felder besorgten Speicher wieder freigibt. Überlegen Sie hierbei welche Parameter Sie den Funktionen übergeben müssen. Institut für Mathematische Optimierung – Technische Universität Braunschweig
8
Zeigerarithmetik Eine weitere Möglichkeit mit Zeigern zu arbeiten ist die Zeigerarithmetik. Zur Verdeutlichung hier ein kleines Beispiel. Bei dem Feld: int a[]={1,2,3}; zeigt a auf a[0] und a+1 zeigt auf a[1]. Statt scanf(" %d",&a[1]); kann man also scanf(" %d",a+1); schreiben, um den zweiten Wert des arrays zu ändern. Institut für Mathematische Optimierung – Technische Universität Braunschweig
9
Zeigerarithmetik Konsequenterweise gibt es auch a++, ++a, a-- und --a. Die Anweisungen: int *p; int a[]={1,2,3,4}; for (p=a; *p != 4; p++) printf(" %d", *p); sind äquivalent zu: int i; for (i=0; a[i] != 4; i++) printf(" %d", a[i]); Institut für Mathematische Optimierung – Technische Universität Braunschweig
10
Zeigerarithmetik bei Matrizen
Bei Matrizen sieht das noch etwas komplizierter aus: double **mat; mat=alloc_matrix(2,2); mat[0][0]=1.0; mat[0][1]=2.0; mat[1][0]=3.0; mat[1][1]=4.0; Institut für Mathematische Optimierung – Technische Universität Braunschweig
11
Zeigerarithmetik bei Matrizen
printf("mat[0][0] = %f\n",mat[0][0]); printf("mat[1][1] = %f\n",mat[1][1]); printf("**mat = %f\n",**mat); printf("*(*mat+1) = %f\n",*(*mat+1)); printf("*(*(mat+1) ) = %f\n",*(*(mat+1))); printf("*(*(mat+1)+1) = %f\n",*(*(mat+1)+1)); Institut für Mathematische Optimierung – Technische Universität Braunschweig
12
Aufgabe Schreiben Sie eine 3x3 Matrix sukzessive mit den Werten 1,2,3,… voll. D.h. Zeile 1 enthält die Einträge 1,2,3, Zeile 2 die Einträge 4,5,6 und Zeile 3 die Einträge 7,8,9. Geben Sie darauf per Zeigerarithmetik die komplette Matrix am Bildschirm aus. Institut für Mathematische Optimierung – Technische Universität Braunschweig
13
Strukturen Objekte verschiedenen Datentyps können zu einem neuen Datentyp kombiniert werden. Beispiel: struct student { char[100] vorname; char[100] nachname; int matrikelnummer; char[100] studienfach; }; Definiert den Datentyp struct student. Institut für Mathematische Optimierung – Technische Universität Braunschweig
14
Aufbau einer Struktur struct Name { Deklaration1; Deklaration2; ... DeklarationN; }; Institut für Mathematische Optimierung – Technische Universität Braunschweig
15
Zugriff auf Strukturelemente
/* Definition von "Koordinaten": */ struct Koordinaten { double x; double y; double z; }; /* Deklaration einer Variable dieses Typs: */ struct Koordinaten p; p.x=3.0; p.y=p.x; /* Zugriff auf die Elemente: */ p.z=0; Institut für Mathematische Optimierung – Technische Universität Braunschweig
16
Zuweisungen und Vergleiche
Man kann Strukturen als Ganzes zuweisen, aber Vergleiche sind nicht als Ganzes erlaubt. struct Koordinaten p1, p2; p1 = p2; /* Zuweisung */ if (p1==p2) ... /* <-- Fehler */ Die if-Bedingung ist in dieser Form nicht erlaubt, sondern es müssten alle Komponenten der Struktur gesondert auf Gleichheit überprüft werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
17
Strukturen und Zeiger Eine Struktur darf sich nicht selbst als Element enthalten, aber sie darf einen Zeiger auf eine Variable vom Typ der eigenen Struktur enthalten. struct knoten { int wert; struct knoten *naechster; }; Die Struktur knoten enthält einen Zeiger auf eine Struktur vom Typ knoten. Darüberhinaus können in jeder Struktur andere Strukturen verwendet werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
18
Zugriff auf Strukturzeigerinhalte
Auf die einzelnen Datenelemente einer Struktur zuzugreifen, deren Adresse man durch eine Zeigervariable kennt, kann auf verschiedene Arten geschehen: struct knoten *p; (*p).wert=0; /* 1. Art */ p[0].wert=0; /* 2. Art */ p->wert=0; /* 3. Art */ Institut für Mathematische Optimierung – Technische Universität Braunschweig
19
Strukturen als Parameter
Strukturen können als Parameter verwendet werden: struct knoten { int wert; struct knoten *naechster; }; void ausgabewert(struct knoten p) printf("%i\n",p.wert); } Dabei werden sie als Kopie übergeben (call-by-value). Institut für Mathematische Optimierung – Technische Universität Braunschweig
20
Besser … struct knoten *p; p->wert=0; // p[0].wert=0; oder (*p).wert=0; ausgabewert(p); void ausgabewert(struct knoten *p) { printf("%i\n",p->wert); } Verwendung von einem Zeiger (call-by-reference). Institut für Mathematische Optimierung – Technische Universität Braunschweig
21
Strukturen als Rückgabewert
Strukturen können auch als Rückgabewert verwendet werden: struct knoten { int wert; struct knoten *naechster; }; struct knoten generate() struct knoten result; ... return result; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
22
Eigene Datentypen Mit dem Schlüsselwort typedef kann man Datentypen mit einem eigenen Namen versehen. Mit: struct knoten_s { int wert; struct knoten_s *naechster; }; typedef struct knoten_s knoten; kann man eine Variable vom Typ struct knoten_s jetzt durch knoten p; deklarieren und das mitunter lästige struct weglassen. Institut für Mathematische Optimierung – Technische Universität Braunschweig
23
Verkürzte Schreibweise
Verkürzte Schreibweise durch Kombination der Deklarationen: typedef struct knoten_s { int wert; struct knoten_s *naechster; } knoten; Andere Anwendungsbeispiele für typedef: typedef unsigned int uint; typedef double real; /* typedef float real; */ (leichter Wechsel zwischen float und double) Institut für Mathematische Optimierung – Technische Universität Braunschweig
24
Einfach verkettete Listen
Mit Hilfe von Strukturen lassen sich Listen erzeugen. Jedes Element (Knoten) der Liste hat einen Zeiger auf seinen Nachfolger. Das erste Element wird Kopf genannt, das letzte Element hat NULL als Nachfolger: Institut für Mathematische Optimierung – Technische Universität Braunschweig
25
Elemente einfügen Um ein neues Element nach einem Listenelement einzufügen, müssen die Nachfolgezeiger geändert werden: Institut für Mathematische Optimierung – Technische Universität Braunschweig
26
Elemente einfügen Die Anweisungen dazu sind: knoten *kopf, *vorgaenger, *neuer_knoten; neuer_knoten->naechster=vorgaenger->naechster; vorgaenger->naechster=neuer_knoten; Institut für Mathematische Optimierung – Technische Universität Braunschweig
27
Elemente am Kopf einfügen
Folgende Anweisungen hängen ein neues Element am Kopf an die Liste an: knoten *kopf, *neuer_knoten; neuer_knoten->naechster = kopf; kopf = neuer_knoten; Institut für Mathematische Optimierung – Technische Universität Braunschweig
28
Elemente entfernen Beim Entfernen eines Elementes muss wiederum der Zeiger des Vorgängerelementes geändert werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
29
Elemente entfernen Die Anweisungen dazu sind: knoten *kopf, *vorgaenger, *zu_loeschen; vorgaenger->naechster = zu_loeschen->naechster; free(zu_loeschen); oder beim Entfernen des ersten Elements: kopf = zu_loeschen->naechster; Institut für Mathematische Optimierung – Technische Universität Braunschweig
30
Durchlaufen einer Liste
Listen können z.B. mittels For-Schleife durchlaufen werden: knoten *p; int max_wert; ... max_wert = head->wert; for (p=head; p!=NULL; p=p->naechster) { if (p->wert > max_wert) max_wert = p->wert; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
31
Rekursion Ruft eine Funktion sich selbst auf, so wird das Rekursion genannt. Diese muss immer eine Abbruchbedingung haben. Beispiel: #include <stdio.h> void printnumbers(int a) { printf("%d ",a); if (a > 0) printnumbers(a-1); } int main() printnumbers(10); return 0;
32
Schlechtes Beispiel für eine Rekursion
Berechnung der Fakultät einer Zahl: unsigned int fakultaet(unsigned int); int main() { printf("%u\n",fakultaet(5)); return 0; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
33
Schlechtes Beispiel für eine Rekursion
unsigned int fakultaet(unsigned int n) { if(n>0) return n*fakultaet(n-1); /* n!=n*(n-1)!*/ else return 1; /* 0!=1 */ } Institut für Mathematische Optimierung – Technische Universität Braunschweig
34
Besser: Iterative Lösung
int main() { int n=5,i,fakultaet=1; for(i=2;i<=n;i++) fakultaet*=i; /* fakultaet=fakultaet*i; */ printf("%d\n",fakultaet); return 0; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
35
Bäume Analog zu Listen lassen sich auch baumartige Daten- strukturen erzeugen: Institut für Mathematische Optimierung – Technische Universität Braunschweig
36
Traversierung von Bäumen
Sollen alle Knoten eines Baumes abgearbeitet werden, wird oft Rekursion verwendet. Beispiel: double maxwert; // globale Variable void traverse(knoten* r) { if (r->wert > maxwert) maxwert = r->wert; if (r->rechts!=NULL) traverse(r->rechts); if (r->links!=NULL) traverse(r->links); }
37
Nochmal ohne globale Variable
int traverse(knoten* r) { double h; double maxwert; maxwert = r->wert; if (r->rechts!=NULL) { h = traverse(r->rechts); if (h > maxwert) h = maxwert; } if (r->links!=NULL) { h = traverse(r->links); }
Ähnliche Präsentationen
© 2024 SlidePlayer.org Inc.
All rights reserved.