37
Einführung in die Programmiersprache C 4.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig

Zeiger bei Matrizen

  • Upload
    kemp

  • View
    31

  • Download
    1

Embed Size (px)

DESCRIPTION

Einführung in die Programmiersprache C 4.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig. 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: - PowerPoint PPT Presentation

Citation preview

Page 1: Zeiger bei Matrizen

Einführung in die Programmiersprache C

4.Tag

Institut für Mathematische Optimierung -

Technische Universität Braunschweig

Page 2: Zeiger bei Matrizen

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

Page 3: Zeiger bei Matrizen

Zeiger bei Matrizen

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 4: Zeiger bei Matrizen

Andere OperationenSollen 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;

Page 5: Zeiger bei Matrizen

Lösung

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...

for...copy[i][j]=mat[i][j];

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 6: Zeiger bei Matrizen

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

Page 7: Zeiger bei Matrizen

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

Page 8: Zeiger bei Matrizen

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]. Stattscanf(" %d",&a[1]);kann man alsoscanf(" %d",a+1);schreiben, um den zweiten Wert des arrays zu ändern.

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 9: Zeiger bei Matrizen

ZeigerarithmetikKonsequenterweise 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;int a[]={1,2,3,4};for (i=0; a[i] != 4; i++) printf(" %d", a[i]);

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 10: Zeiger bei Matrizen

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

Page 11: Zeiger bei Matrizen

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

Page 12: Zeiger bei Matrizen

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

Page 13: Zeiger bei Matrizen

StrukturenObjekte verschiedenen Datentyps können zu einem neuenDatentyp 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

Page 14: Zeiger bei Matrizen

Aufbau einer Struktur

struct Name {

Deklaration1;Deklaration2;...DeklarationN;

};

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 15: Zeiger bei Matrizen

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

Page 16: Zeiger bei Matrizen

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

Page 17: Zeiger bei Matrizen

Strukturen und ZeigerEine 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

Page 18: Zeiger bei Matrizen

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

Page 19: Zeiger bei Matrizen

Strukturen als ParameterStrukturen 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

Page 20: Zeiger bei Matrizen

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

Page 21: Zeiger bei Matrizen

Strukturen als RückgabewertStrukturen 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

Page 22: Zeiger bei Matrizen

Eigene DatentypenMit 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

Page 23: Zeiger bei Matrizen

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

Page 24: Zeiger bei Matrizen

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

Page 25: Zeiger bei Matrizen

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

Page 26: Zeiger bei Matrizen

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

Page 27: Zeiger bei Matrizen

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

Page 28: Zeiger bei Matrizen

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

Page 29: Zeiger bei Matrizen

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;free(zu_loeschen);

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 30: Zeiger bei Matrizen

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

Page 31: Zeiger bei Matrizen

RekursionRuft 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;

}

Page 32: Zeiger bei Matrizen

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

Page 33: Zeiger bei Matrizen

Schlechtes Beispiel für eine Rekursion

unsigned int fakultaet(unsigned int n){if(n>0)return n*fakultaet(n-1); /* n!=n*(n-1)!*/elsereturn 1; /* 0!=1 */}

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 34: Zeiger bei Matrizen

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

Page 35: Zeiger bei Matrizen

Bäume

Analog zu Listenlassen sich auch baumartige Daten-strukturen erzeugen:

Institut für Mathematische Optimierung – Technische Universität Braunschweig

Page 36: Zeiger bei Matrizen

Traversierung von BäumenSollen 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);

}

Page 37: Zeiger bei Matrizen

Nochmal ohne globale Variableint 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);

if (h > maxwert) h = maxwert; }

}