Variablen in C++ Einfache Variablen Strukturen Arrays und Zeichenketten Zeiger und Referenzen Parameter Dynamische Speicherverwaltung
Einfache Variablen Typen int, long, short, unsigned bool char float, double Besonderheit bool: 0 ist false, alles andere true while (index --) {...} schmiedecke 09 Inf2-1-Intro 2
Operationen Arithmetische und Boolesche Operationen wie in Java Besonderheit bool: Numerisch Inkrement und Dekrement viel benutzt: int a = 3; int b = ++a; // b und a habenden Wert 4 int c = a++; // c hat den Wert 4, a 5! Nützlich z.b. bei Stackoperationen: public void push(int val) { liste[current++] = val; } public int pop() { return liste[--current]; } schmiedecke 09 Inf2-1-Intro 3
Strukturierte Variablen Benannter Strukturtyp: struct Complex {double reell; double imag}; Complex cval; cval.rell = 0.0; cval.imag = -3.077; Unbenannter Strukturtyp: struct {int x; int y } point1, point2; point2.x = 0; schmiedecke 09 Inf2-1-Intro 4
Arrays Zunächst ganz einfach: int liste[100]; for (int i=0; i<100; i++) liste[i] = i; int codes[4] = { 22, 333, 4444, 5555 }; int zeroes[100] = {0}; int i=100; while (i) cout << codes[--i] << " "; schmiedecke 09 Inf2-1-Intro 5
iostream Die direkte Ein- und Ausgabe ist sehr komfortabel gelöst: Die Konsole ist mit zwei Stream-Variablen verbunden cin undcout Schreiben in den Ausgabestrom mit dem Operator << Lesen aus dem Eingabestrom in eine Variable mit >> Alle einfachen Typen und Texte werden direkt erkannt Die Operatoren sind verkettbar. cout << "Hallo " << "Welt!" << endl; int alter; cin >> alter; double gehalt; cin >> gehalt; schmiedecke 09 Inf2-1-Intro 6
include Die komfortable Eingabe ist in der Standardbibliothek iostream definert. Diese muss mit #include eingebunden werden. #include ist eine Präprozessoranweisung, die eine Kopieraktion bewirkt. Die Namen cin und cout sind im Namensraum std definiert. entweder, sie müssen voll qualifiziert notiert werden: std::cin und std::cout oder der Namensraum wird mit using bekanntgemacht. #include <iostream> using namespace std; schmiedecke 09 Inf2-1-Intro 7
Mehrdimensionale Arrays Von der Idee her wie in Java int matrix [8][16]; matrix[4][8] = 111; Aber in einem kompakten Speicherbereich abgelegt. Konvention: der rechteste Index läuft am schnellsten schmiedecke 09 Inf2-1-Intro 8
Wie viele Elemente im Array? #include <iostream> using namespace std; int main() { double c[13]; cout << "Speicherbedarf des Arrays: "; cout << sizeof(c) << endl; cout << "Speicherbedarf eines Elements: "; cout << sizeof(c[0]) << endl; cout << Anzahl der Elemente: "; cout << sizeof(c) / sizeof(c[0] << endl; } schmiedecke 09 Inf2-1-Intro 9
Bubblesort for (int i=max; i>0; i--) for (int j=0; j<i; j++) if (liste[j] > liste[j+1]) { int temp = liste[i]; liste[i] = liste[j]; liste[j] = temp; } for (int k=0; k<max; k++) cout << liste[k]; cout << endl; schmiedecke 09 Inf2-1-Intro 10
Zeichenketten char text[100]; // null-terminated, //d.h. 1 Zeichen länger als der Text. //'\0' bzw 0 ist Endezeichen, nicht '0'. char vorname[] = "silke"; int i=0; while (vorname[i]) cout << vorname[i++]; cin >> text; // länge beachten!!! schmiedecke 09 Inf2-1-Intro 11
Zeiger und Referenzen int PIN = 1001; int *pinverweis = &PIN; // Adresse PIN = 2002; // geändert cout << PIN << " "<< *pinverweis; *pinverweis = 3003; cout << PIN << " "<< *pinverweis; schmiedecke 09 Inf2-1-Intro 12
Arrayvariablen sind nur Zeiger! int liste[100]; liste hat den Typ int*! Zeiger auf liste[0] liste[4] ist gleichbedeutend mit *(liste+4). d.h. eine for-schleife kann lauten: int *listenzeiger = liste; for (int i=0; i<100; i++) cout << *(listenzeiger+i) << " "; schmiedecke 09 Inf2-1-Intro 13
Zeichenkettenvariablen sind Zeiger char text [] = "sechzehnhundertzwölf"; char *textzeiger = text; while (*textzeiger++) cout<<*textzeiger; schmiedecke 09 Inf2-1-Intro 14
Zeiger-Zugriff auf auf mehrdimensionale Arrays int matrix [2][3] = { {0,1,2}, {3,4,5} }; int matrix2[2][3] = { 0,1,2,3,4,5 }; cout << *(matrix+4) << endl; cout << matrix[4] << endl; d.h. [] ist nur ein Service des Compilers zur Zeigerberechnung. Weiterer Service: zeiger+zahl implizite Multiplikation mit der Elementgröße. schmiedecke 09 Inf2-1-Intro 15
Zeiger auf Zeiger?? Kommt häufiger vor, z.b... Array von Texten: char sprueche [100][200]; gleichbedeutend mit char **sprueche; der 1. buchstabe im 100.spruch sprueche[99][0] *(sprueche + 98*100) schmiedecke 09 Inf2-1-Intro 16
Wozu Zeiger? Veränderbare Parameter C++ unterscheidet Eingabe- und Ausgabeparameter Aliase Zwei Variablen können explizit auf denselben Eintrag verweisen Verkettungen für sinnvolle Anwendungen braucht man zusätzlich dynamische Speicherverwaltung kommt später schmiedecke 09 Inf2-1-Intro 17
Parameterübergabe: Call by Value Standardverfahren in Java Parameter sind lokale Variablen in der Funktion Bei Aufruf wird der Wert des Arguments dem Parameter zugewiesen. Eine "Rückzuweisung" an das Argument gibt es nicht. Veränderungen des Parameters werden nicht nach an die Aufrufstelle kommuniziert. schmiedecke 09 Inf2-1-Intro 18
Parameterübergabe: Call by Reference Der Parameter ist eine Zeigervariable Ihr wird ein Zeiger (eine Adresse) als Argument übergeben. Damit ist der Parameter ein Alias für das Argument Über den Parameter kann das Argument verändert werden Veränderungen des Parameters werden nach außen kommuniziert Zeigerparameter können als Ausgabeparameter verwendet werden. schmiedecke 09 Inf2-1-Intro 19
Beispiel Translate Point void translatepoint(int *x, int *y) { *x += deltax; *y += deltay; } struct Point { int x; int y }; Point A = { 12, 45 }; cout << A.x << " " << A.y << endl; translatepoint (&(A.x), &(A.y); cout << A.x << " " << A.y << endl; schmiedecke 09 Inf2-1-Intro 20
Beispiel Translate Point -2 struct Point { int x; int y }; void translatepoint(point *P) { (*P).x += deltax; (*P).y += deltay; } Point A = { 12, 45 }; cout << A.x << " " << A.y << endl; translatepoint (&A); cout << A.x << " " << A.y << endl; schmiedecke 09 Inf2-1-Intro 21
Referenz-Parameter Call by Name void translatepoint(point &alias) { alias.x += deltax; alias.y += deltay; } Point A = { 12, 45 }; cout << A.x << " " << A.y << endl; translatepoint (A); cout << A.x << " " << A.y << endl; Compiler macht Parameter zu direkten Aliasen der Argumente Argumente sind Variablen, nicht deren Adressen schmiedecke 09 Inf2-1-Intro 22
Referenz-Parameter Vor- und Nachteile + Bequem in der Anwendung + Adressen werden nicht sichtbar + Weniger Zeigerfehler - Aufruf nicht von Call-by-Value zu unterscheiden - Fehlerquelle bei Programmänderungen schmiedecke 09 Inf2-1-Intro 23
3 x swap void swap1(int x, int y) { int temp = x; x = y; y = temp; } void swap2 (int *x, int *y) { int temp = *x; *x = *y; *y = temp; } void swap3 (int &x, int &y) { int temp = x; x = y; y = temp; } int a = 5, b = 6; swap1(a, b); cout << "a="<<a<<endl; swap2(&a, &b); cout << "a="<<a<<endl; swap3(a, b); cout << "a="<<a<<endl; schmiedecke 09 Inf2-1-Intro 24
Zeigerparameter für große Werte Verwendung von Zeigerparametern: Ausgabeparameter große Werte (Vermeidung von Kopien) Bei Verwendung zur Kopienvermeindung: Schreibschutz: const const char *Textkonstante; // der Text kann nicht verändert werden char *const Textzeigerkonstante; // der Textzeiger kann nicht verändert werden const char *const Textbaustein; // konstanter Zeiger auf konstanten Text. schmiedecke 09 Inf2-1-Intro 25
Arrays als Parameter Ein Array ist ein Zeiger auf einen reservierten Speicherbereich daher sind Arrayparameter standardmäßig Call by Reference Ausgabeparamter Schreibschutz durch const: public char * split (const char *text); public int [] erstelleindex(const int liste[], int laenge); public void sortiere(int liste[], int laenge); schmiedecke 09 Inf2-1-Intro 26
Swap-Parameter in Bubblesort Aufruf ist swap(a[i], a[i+1]); Gleichbedeutend mit swap(*(a+i), *(a+i+1) ); also Zeigerparameter. Deklaration muss sein: void swap(int *x, int *y); schmiedecke 09 Inf2-1-Intro 27
Statische Speicherverwaltung Statische Deklaration: int x; struct {int x; int } pointa; int matrix [20][20]; bewirkt sofortige Platzreservierung im aktuellen Stackframe; Wird beim Verlassen des Blocks automatisch gelöscht. schmiedecke 09 Inf2-1-Intro 28
Dynamische Speicherverwaltung float *geldverweis = new float; int *PINspeicher = new int(24466); Point *punktverweis = new Point; int liste[] = new int[20]; Speicher muss explizit wieder frei gegeben werden! delete PINspeicher; PINspeicher = andererpinspeicher; delete liste; // das ganze Array wird freigegeben! schmiedecke 09 Inf2-1-Intro 29
Verkettete Liste struct Knoten { char *inhalt; }; Knoten *next; Knoten *anker = new Knoten, *ende = anker; int main() { } char *text = new char[100]; while (cin >> text) // bis Eingabe leerer Text { Knoten *neu = new Knoten; (*neu).inhalt = text; // oder neu->inhalt = text text = new char[100]; // Platz für neue Eingabe (*ende).next = neu; // oder ende->next = neu; } schmiedecke 09 Inf2-1-Intro 30
... das genügt an Stoff Nach der Pause gehen wir ein Programmierbeispiel durch.