410 likes | 550 Views
Einführung in die Programmiersprache C 3.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig. Globale Variablen. Bisher:
E N D
Einführung in die Programmiersprache C3.TagInstitut für Mathematische Optimierung -Technische Universität Braunschweig
Globale Variablen • Bisher: Verwendung lokaler Variablen. Diese sind nur in der Funktion bekannt, in der sie deklariert wurden und können auch nur innerhalb dieser Funktion verändert werden. • Globale Variablen werden vor Beginn des Hauptprogramms und nach den Funktionendeklarationen deklariert und sind ab diesem Punkt im Quelltext bekannt. Sie können von jeder Funktion geändert werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Globale Variablen • Die Verwendung globaler Variablen sollte man, wenn möglich, vermeiden, da durch sie ungewollte Seiteneffekte entstehen können. • Existieren lokale und globale Variablen gleichen Namens, dann gilt das Prinzip „lokal vor global “, die Funktion greift also auf „ihre“ Variable zurück und ignoriert die globale. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel 1.Teil #include<stdio.h> voidchange_var(void); intvar; intmain(void) { var=1; change_var(); printf("var=%d\n",var); return 0; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel 2.Teil voidchange_var(void) { var++; } Ausgabe: var=2 Institut für Mathematische Optimierung – Technische Universität Braunschweig
Statische Variablen Eine weitere Variante sind lokal definierte, statische Variablen. In einer Funktion als static definiert, sind sie nur dort bekannt, behalten aber ihren Wert bis zum nächsten Aufruf der Funktion. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel 1.Teil #include<stdio.h> voidzaehler(void); intmain(void) { zaehler(); zaehler(); return 0; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel 2.Teil voidzaehler(void) { staticint aufrufe=0; aufrufe++; printf("Bisher %d Funktionsaufrufe.\n",aufrufe); } Institut für Mathematische Optimierung – Technische Universität Braunschweig
Aufbau eines Programms • Präpozessorbefehle/Header (z.B. #include<stdio.h>) • Funktionendeklarationen (über Funktionenprototypen) • Deklarationen globaler Variablen • Main-Funktion • Andere Funktionen Institut für Mathematische Optimierung – Technische Universität Braunschweig
(eindimensionale) Felder (Arrays) • Eindimensionale Felder sind Vektoren von Variablen des gleichen Datentyps. Ein eindimensionales Feld wird deklariert mit: datentypname[groesse]; • Beispiel: intvektor[9]; deklariert einen 9-elementiger Vektor von Integer-Werten. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Initialisierung von Arrays • Wie die herkömmlichen Variablen kann man auch Felder bei der Deklaration initialisieren. Wird für alle Elemente ein Startwert gegeben, dann braucht die Größe des eindimensionalen Feldes nicht angegeben zu werden: double vektor[]={1.3, 2.9, 3.123}; int ganz[37]={1,2}; char Beispiel1[]={’T’,’o’,’l’,’l’}; char Beispiel2[]="Toll„; Institut für Mathematische Optimierung – Technische Universität Braunschweig
Initialisierung von Arrays • Eine spätere Initialisierung (also nach der Deklaration) ist auf diese Art und Weise nicht mehr möglich! Institut für Mathematische Optimierung – Technische Universität Braunschweig
Zuweisung nach der Deklaration • Um den einzelnen Elementen des Arrays einen Wert zuzuweisen, muss jedes Element einzeln angesprochen werden. vektor [0]=1.3; vektor[1]=2.9; vektor[2]=3.123; • Hier sieht man auch, dass der Index des Feldes nicht bei 1, sondern bei 0 beginnt. Bei Nichtbeachtung führt das zu unangenehmen Fehlern! Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beipiel: Übergeben von arrays 1.Teil #include<stdio.h> double mw(int *, int); intmain(void) { intarray[]={2,4,5}; double mittelwert=0.0; mittelwert=mw(array,3); printf("Mittelwert: %f ",mittelwert); return 0; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beipiel: Übergeben von arrays 2.Teil double mw(int *feld, intelemente) { double tmp=0.0; int i; for(i=0;i<elemente;i++) tmp+=feld[i]; /*tmp=tmp+feld[i]; */ tmp/=elemente; /*tmp=tmp/elemente; */ returntmp; } Eindimensionale Arrays sind grundsätzlich vom Typ * (zweidimensionale vom Typ **)! Institut für Mathematische Optimierung – Technische Universität Braunschweig
Der ?-Operator • Die Anweisung (A1) ? (A2) : (A3) hat den Wert A2, falls A1 wahr ist und den Wert A3 wenn A1 falsch ist. • Beispiele: maxval = (maxval<feld[i]) ? feld[i] : maxval; maxval bekommt Wert von feld[i] falls Wert größer int min(inta,int b) { return (a<b) ? a : b; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
Aufgabe Schreiben Sie ein Programm, das über den ?-Operator den maximalen Wert eines arrays bestimmt. Das array sei hierbei wie folgt zu deklarieren und initialisieren: intarray[]={3,77,12,99}; Institut für Mathematische Optimierung – Technische Universität Braunschweig
Mehrdimensionale Felder Neben eindimensionalen Feldern, können auch mehrdimensionale Felder implementiert werden. Im zweidimensionalen Fall kann man auf diese Weise eine Matrix darstellen: double matrix[2][2]={1.0,2.1,3.1,4.9} sieht in Matrix-Schreibweise so aus: 1.0 2.1 3.1 4.9 Institut für Mathematische Optimierung – Technische Universität Braunschweig
Zugriff auf Elemente • Die einzelnen Elemente können dann z.B. mit matrix[0][1] angesprochen werden. Der erste Index steht dabei für die Zeile, der zweite für die Spalte. • Hier ist auch darauf zu achten, dass man nicht über die Dimensionen der Matrix hinausläuft. Das Element rechts unten einer 3x3-Matrix ist nicht das Element matrix[3][3], sondernmatrix[2][2]! Institut für Mathematische Optimierung – Technische Universität Braunschweig
Zeiger • Ein Zeiger ist eine Variable, die die Adresse (d.h. die Position im Speicher) eines anderen Objektes, wie zum Beispiel einer zweiten Variable, enthält. Deklaration: datentyp *name; • datentyp ist hierbei der Datentyp der Variable, auf die der Zeiger zeigt. Der Stern * gehört nicht zum Namen des Zeigers, sondern signalisiert nur, dass es sich um einen solchen handelt. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Der Adress-Operator • Der Adress-Operator & liefert die Adresse der Variablen, vor der er steht. int *p,q; q=99; p=&q; • Hier enthält der Zeiger p die Adresse der Variablen q. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Der Inhaltsoperator Um auf den Inhalt zuzugreifen, auf den ein Zeiger zeigt, verwendet man den Inhaltsoperator * int *p,q; q=99; p=&q; printf("Adresse:%p\n",p); printf("Wert:%d\n",*p); printf("Adresse:%p\n",&q); printf("Wert:%d\n",q); Institut für Mathematische Optimierung – Technische Universität Braunschweig
Zeiger als Funktionsparameter • Zeiger können als Funktionsparameter benutzt werden, dadurch kann eine Funktion den Wert einer Variable „nach außen“ ändern. Die Übergabe eines Zeigers auf eine Variable nennt man call-by-referenceim Gegensatzzucall-by-value. Ein Funktionsprototyp dieser Art: double funktion(int, int *); • Der Funktion muss nun als zweiter Parameter ein Zeiger auf eine Integer-Variable übergeben werden (bzw. eine Speicheradresse, wo eine Variable vom Typ Integer gespeichert ist). Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel int *p,q=99; p=&q; funktion(q,p); /*Integer, Zeiger */ funktion(q,&q); /*Integer, Adresse Integer */ funktion(*p,p); /*Inhalt Zeiger, Zeiger */ funktion(*p,&q); /*Inhalt Zeiger, Adresse Int*/ • Hinweis: Bei einer Funktion mit Zeigerübergabe kann derInhalt auf den der Zeiger zeigt verändert werden, allerdings nicht der Zeiger (d.h. die Speicheradresse) selbst! Institut für Mathematische Optimierung – Technische Universität Braunschweig
Aufgabe Schreiben Sie ein Programm, bei dem in der main-Funktion eine Variable zahl vom Typ double deklariert und mit einem Wert von 1.7 initialisiert wird. Darauf soll in der main eine Funktion erhoeheaufgerufen werden, der ein Zeiger auf die Variable zahl übergeben wird (call-by-reference). zahl soll in der Funktion erhoehe um 1 erhöht werden und nach dem Aufruf der Funktion in der main ausgegeben werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Kommandozeilenargumente • Beim Programmaufruf ist es möglich, dem Programm noch einige Argumente zu übergeben. Dafür muss die main()-Funktion angepasst werden: intmain(intargc, char *argv[]) { Anweisungen } • Dabei ist argc die Anzahl der Argumente beim Programmaufruf inklusive des Programmnamens und argv ein Array von Zeigern auf den Anfang von Strings (Worten) aus der Kommandozeile. Mittels argv[0] usw. können die einzelnen Argumente verwendet werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel Programmaufruf: programm argument1 argument2 … #include <stdio.h> intmain(intargc, char **argv) { int i; printf("Ich heisse: %s\nDie Argumente sind:\n",argv[0]); for (i = 1; i < argc; i++) printf("(%i) %s\n",i,argv[i]); return 0; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
Filepointer Dateien werden mittels Filepointer angesprochen, die von der Funktion fopen() erzeugt werden. Der Funktion wird neben dem Dateinamen auch der Öffnungsmodus (s.u.) übergeben. Wenn die Datei nicht mehr verwendet wird, muss sie mit Hilfe der Funktion fclose geschlossen werden. FILE *fp; fp=fopen("dateiname","r"); ... fclose(fp); Falls die Datei nicht geöffnet werden kann, wird ein spezieller Wert, der NULL-Zeiger zurückgegeben. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Der fopen-Modus Öffnen von Dateien mit unterschiedlichen Modi: Institut für Mathematische Optimierung – Technische Universität Braunschweig
Schreiben und Lesen von Dateien Zum Schreiben und Lesen von Dateien benutzt man die Funktionen fprintf() und fscanf(), die im Unterschied zu printf() und scanf() als erstes Argument zusätzlich einen Filepointer erwarten. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel intmain(intargc,char **argv) { FILE *datei; int zahl1,zahl2=10; datei=fopen(argv[1],"r+"); if(datei==NULL) printf("Kann Datei %s nicht oeffnen!\n",argv[1]); else { fscanf(datei,"%d",&zahl1); printf("Erste Zahl in der Datei %s lautet: %d",argv[1],zahl1); fprintf(datei,"\t%d",zahl2); fclose(datei); …
Dynamische Speicherreservierung • Bisher: Größe der Felder vor Programmstart festgelegt. • Jetzt: Größe der Felder erst während des Programmablaufs bekannt • Problem: Keine Speicherreservierung wie bisher möglich Institut für Mathematische Optimierung – Technische Universität Braunschweig
So nicht! · · · intzeilen,spalten; printf("Zeilenanzahl"); scanf("%d",&zeilen); printf("Spaltenanzahl"); scanf("%d",&spalten); double matrix[zeilen][spalten]; · · · Problem: Statische Felder verlangen feste Wertzuweisung und keine Variablen! Institut für Mathematische Optimierung – Technische Universität Braunschweig
Die Funktion malloc() Um während des Programmablaufs Speicherplatz zu reservieren, verwendet man die Funktion void *malloc(intsize); Sie reserviert einen zusammenhängenden Speicherbereich von size Bytes und gibt einen Zeiger darauf zurück. Falls der Speicher nicht ausreicht, wird NULL zurückgegeben. Der Ausdruck sizeof(type) steht für die Größe einer Variable vom Typ type in Bytes und sollte zum Bestimmen der Größe benutzt werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel • Für einen Array mit 10 double-Variablen wird Speicher wie folgt bereitgestellt: #include<stdlib.h> double *array; array=(double*)malloc(10*sizeof(double)); • Der Typecast (double*) ist aus syntaktischen Gründen zwingend erforderlich. Die einzelnen Arrayelemente können dann wiederum mit array[0] usw. angesprochen werden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Die Funktion calloc() • Die Funktion calloc() erfüllt im Prinzip die gleiche Aufgabe wie die Funktion malloc(). Allerdings unterscheidet sie sich in der Art des Aufrufes: double *array; array=(double*)calloc(10,sizeof(double)); • Außerdem wird der Speicherbereich mit dem Wert 0 vorinitialisiert. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Speicherfreigabe Um nicht mehr benötigten Speicher wieder freizugeben, verwendet man die Funktion free. In unserem Beispiel wird der Speicher für das Array mit dem Befehl: free(array); wieder freigegeben. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Speicherreservierung für Matrizen So erzeugt man dynamisch eine Matrix: Es wird ein Zeiger auf einen Zeiger auf einen double deklariert: Dieser Zeiger zeigt auf ein Array von Zeigern, das wiederum soviele Zeiger enthält, wie die Matrix Zeilen hat. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Quellcode (Teil 1) ... double **mat; int j; mat = (double**) malloc(n*sizeof(double*)); ... Die Variable mat ist hier ein Zeiger auf eine Zeigervariable. Deshalb stehen vor dem mat auch zwei Sterne. Speicherplatz wird dann für das Array von Zeigern auf double-Variablen angefordert (Speicherplatz für n Zeiger vom Typ double*). Institut für Mathematische Optimierung – Technische Universität Braunschweig
Speicherreservierung für Matrizen Im zweiten Schritt wird jedem Zeiger des Arrays ein Speicherbereich für die Matrixelemente zugewiesen: Der Zugriff auf die einzelnen Elemente kann dann wiederum durch mat[i][j] erfolgen. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Quellcode (Teil 2) ... for (j=0; j<n; j++){ mat[j]= (double*)calloc(m,sizeof(double)); } ... Hier wird für jede Zeile j Speicherplatz für je m double-Variablen bereitgestellt. Institut für Mathematische Optimierung – Technische Universität Braunschweig