Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Einführung in die Programmiersprache C/C++

Ähnliche Präsentationen


Präsentation zum Thema: "Einführung in die Programmiersprache C/C++"—  Präsentation transkript:

1 Einführung in die Programmiersprache C/C++
Seminar: "Einführung in C/C++" Einführung in die Programmiersprache C/C++ “Dienstag” Andreas Döring SS 2004

2 Typen – welche kennen wir schon?
Seminar: "Einführung in C/C++" Typen – welche kennen wir schon? 1. Einfache Typen: char, int, float, double, void, ... 2. Pointer: char *, int * *, void *, ... 3. Arrays: int [ ], float [ ] [ ], ...

3 typedef Mit typedef kann man Typbeschreibungen Namen geben:
Seminar: "Einführung in C/C++" typedef Mit typedef kann man Typbeschreibungen Namen geben: typedef int * IntPtr; IntPtr x;  x ist nun vom Typ int * typedef char (* T)[10]; T y; Mit typedef werden jedoch keine neuen Typen definiert: Im Beispiel oben sind IntPtr und int * der selbe Typ, nur anders geschrieben.

4 Aufzählungstypen (enums)
Seminar: "Einführung in C/C++" Aufzählungstypen (enums) Definiere neuen Typ durch Aufzählung der Werte, die eine Variable dieses Typs einnehmen kann: enum Farbe { blau, rot, gelb, orange, gruen }; Farbe x = gelb; std::cout << gruen; Man beachte das ; hinter der schließenden Klammer }. Die Werte des enums (blau, rot, gelb, orange, gruen) entsprechen Zahlen. Mit der letzten Zeile wird der Zahlenwert fuer gruen (4) ausgegeben.

5 enum-Werte sind Zahlen
Seminar: "Einführung in C/C++" enum-Werte sind Zahlen Die Werte eines enums werden bei der Definition zu Synonymen von (ganzen) Zahlen: enum Farbe { blau, rot, gelb }; Dann sind: blau == 0, rot == 1, gelb == 2. Die Werte kann man auch explizit angeben: enum Lieblingszahlen { Antwort = 42, Teufel = 666 }; Auch Mehrfachbelegungen der Werte sind erlaubt. Bsp: enum allesNull { ich = 0, du = 0, er = 0, sie = 0}; enums lassen sich prima für die Definition von Konstanten missbrauchen. Allerdings sind nur ganze Zahlen (auch negative) als Wert erlaubt.

6 Zur Erinnerung: Pointer
Seminar: "Einführung in C/C++" Zur Erinnerung: Pointer Zeiger sind Variablen, deren Inhalt auf andere Variablen verweist. int * X;  Zeiger auf eine int Variable float * Y;  Zeiger auf eine flaot Variable Mit Pointern werden wir uns im nächsten Kapitel noch eingehender beschäftigen.

7 Der address-of-Operator &
Seminar: "Einführung in C/C++" Der address-of-Operator & Pointer speichern Adressen von Variablen ab. int foo;  Variable foo int * bar = & foo;  & gibt Adresse von foo, die dann in bar gespeichert wird. Mit dem address-of-Operator & kann man die Adresse einer Variablen bestimmen. Der address-of-Operator ist ein unärer Operator. & als binärer Operator steht für bitweises UND. Man verwechsele den address-of-Operator auch nicht mit dem &, das bei der Definition von Referenzen (siehe unten) verwendet wird! Wenn eine Variable X vom Typ t ist, dann ist & X vom Typ t *.

8 Der indirection-Operator *
Seminar: "Einführung in C/C++" Der indirection-Operator * Das Gegenteil zum address-of-Operator & ist der indirection-Operator *: int foo = 37;  foo enthält 37. int * bar = & foo;  bar zeigt auf foo. int foo2 = * bar;  foo2 enthält auch 37. Mit dem indirection-Operator kann man den Inhalt einer Variablen bestimmen, wenn man deren Adresse hat. Der indirection-Operator * wird auch „Dereferenzierungs-Operator“ genannt. Er ist ein unärer Operator, als binärer Operator wird * für die Multiplikation verwendet. Man verwechsele den indirection-Operator nicht mit dem *, der bei der Deklaration/Definition von Pointervariablen verwendet wird! Wenn man sich Pointer als Pfeile vorstellt, dann bedeutet der *-Operator, dass man dem Pfeil folgt und sich das Ziel anschaut, auf das der Pfeil zeigt.

9 * bar  foo X1 = foo;  X1 = „Inhalt“ von foo = 37.
Seminar: "Einführung in C/C++" * bar  foo int foo = 37; int * bar = & foo; X1 = foo;  X1 = „Inhalt“ von foo = 37. X2 = * bar;  X2 = „Inhalt“ von * bar = „Inhalt“ von foo = 37.

10 Nullpointer Ein Pointer kann auch eine 0 enthalten: int * bar = 0;
Seminar: "Einführung in C/C++" Nullpointer Ein Pointer kann auch eine 0 enthalten: int * bar = 0; int foo = *bar; //boeser Fehler! Der indirection-Operator geht davon aus, dass in der Pointer-Variablen die Adresse einer Variablen steht. Wird er auf einen Nullpointer angewendet, so gibt der indirection-Operator also eine Variable wieder, die angeblich an der Adresse 0 liegt. Der Speicher dort ist aber niemals zum Lesen freigegeben, versucht man das dennoch, so wird die Programmausführung abgeprochen. Ähnliches gilt natürlich auch für alle anderen Speicheradressen, hinter denen keine lesbaren Speicherbereiche liegen. Der Compiler hilft einem nicht dabei, diesen Fehler zu vermeiden. Man muss eben darauf aufpassen, dass auch etwas Sinnvolles in einem Pointer steht, bevor man auf ihn den indirection-Operator anwendet. Anmerkung: Trotzdem kann es sinnvoll sein, einen Nullpointer zu verwenden – soll ein Zeiger auf „nichts“ zeigen, kennzeichnet man dies, indem man eine 0 hineinschreibt.

11 Pointer auf Pointer Pointer können auch auf Pointer zeigen:
Seminar: "Einführung in C/C++" Pointer auf Pointer Pointer können auch auf Pointer zeigen: int foo = 5; int * bar = & foo; int * * bar2 = & bar; std::cout << * * bar2;  Ausgabe: 5 bar2 ist ein Pointer auf einen Pointer auf ein int. *bar2 ist ein Pointer auf ein int. **bar2 ist ein int. Das Spiel kann man beliebig weiter treiben. Wer Lust hat, kann sich durchaus einen int ******* bar8 definieren – ob das Sinn macht, muss man selbst entscheiden.

12 Pointer und Arrays Pointer zeigt auf Elemente eines Arrays:
Seminar: "Einführung in C/C++" Pointer und Arrays Pointer zeigt auf Elemente eines Arrays: int arr [3] = {2,3,5}; int * bar = arr;  bar zeigt auf das das erste Element von arr int foo = * bar;  setzt foo auf 2 Ein Array verhält sich so, als wäre es ein Pointer auf sein erstes Element. Abgesehen von der Definition/Deklaration unterscheiden sich Array-Variablen in ihrer Verwendung kaum von Pointer-Variablen. Aber man beachte: Arrays SIND keine Pointer. Die Definition von Arrays und Pointern unterscheidet sich beträchtlich voneinander: Bei Arrays der Länge n wird ein Speicherbereich für das Feld von n Variablen reserviert, Pointer brauchen lediglich Platz für die Speicherung einer Speicheradresse (bei PCs gewöhnlich 4 bytes).

13 Der subscript-Operator [ ]
Seminar: "Einführung in C/C++" Der subscript-Operator [ ] Mit [ ] kann man auf die einzelnen Elemente eines Arrays zugreifen: int arr [3] = {2,3,5}; int foo = arr [2];  setzt foo auf 5 Der Index des ersten Elements eines Arrays ist 0. Der subscript-Operator [ ] ist ein suffix-Operator. Man verwechsele ihn nicht mit den [ ], die bei der Definition/Deklaration von Arrays verwendet werden. Man beachte, dass C/C++ von sich aus keinerlei Checks übernimmt, ob sich der Index auch innerhalb des „erlaubten“ Bereiches befindet. Bsp: int arr[3] = {2, 3, 5}; int foo = arr [34]; //boeser Fehler Der subscript-Operator kommt sogar klaglos mit negativen Indices klar: int foo = arr [-3]; //nochmal boeser Fehler Durch zu große oder kleine Indices wird unter Umständen auf einen nicht freigegebener Speicherbereich zugegriffen, was zum Abbruch des Programmes führt. Oder es wird eigener Speicher unkontrolliert überschrieben, was zum Absturz des Programmes führen kann.

14 Seminar: "Einführung in C/C++"
0 + 2 = 8 Indirection-Operator * und Subcript-Operator [ ] sind miteinander verwandt: foo = arr[2];  foo = *(arr + 2); Beides funktioniert auch mit Pointern. Aber Achtung: int * bar = 0;  bar enthält 0 bar = bar + 2;  bar wird um 2 int weiter gesetzt, und enthält nun also eine 8! Die Änderung der Adresse in einem Pointer nach Addieren oder Subtrahieren einer Zahl hängt davon ab, wie viel Speicher der Typ benötigt, auf den der Pointer zeigt. Ints brauchen 4 bytes, also wird bei jeder Erhöhung des Pointers um 1 dessen Inhalt um 4 vergrößert. Bei einem Pointer auf short int wären es 2, bei einem Pointer auf doube wären es 8, usw.

15 C-Strings C-Strings sind Arrays von chars: char s1 [] = "hallo";
Seminar: "Einführung in C/C++" C-Strings C-Strings sind Arrays von chars: char s1 [] = "hallo"; s1[1] = 'e';  s1 == "hello" Vorsicht: char * s2 = "hallo"; s2[1] = 'e';  Fehler! Grund: s2 zeigt zwar auf einen Speicherbereich, in dem "hallo" steht, dieser ist aber gewöhnlich nicht schreibbar. Aus s2 kann jedoch problemlos gelesen werden. Bsp: char * s2 = "hallo"; char c = s2[1]; // c == 'a'

16 Mehrdimensionale Arrays
Seminar: "Einführung in C/C++" Mehrdimensionale Arrays Mehrdimensionale Arrays werden einfach als „Arrays von Arrays“ realisiert. Bsp.: int arr2 [3][6]; ist ein Array von 3 Arrays von 6 ints. Der Zugriff erfolgt z.B. mit mehreren [ ]: arr2[1][4] = 17; Auf diese Weise können Arrays fast beliebiger Dimension erzeugt werden. Die Felder liegen alle hintereinander in einem zusammenhängenden Speicherblock. Auch eine Initialisierung ist möglich. Beispiel für 2 Dimensionen: int arr2 [2][3] = { {1, 2, 3}, {4, 5, 6} }; Die Variablen liegen nun tatsächlich in der gleichen Reihenfolge wie hier aufgeschrieben im Speicher.

17 Der sizeof()-Operator
Seminar: "Einführung in C/C++" Der sizeof()-Operator Der Operator sizeof() gibt den Speicherbedarf einer Variablen (in Bytes) an: int i; int j = sizeof(i);  j == 4 Dies funktioniert auch für komplexere Typen: short s[10];  sizeof(s) == 20 char * p;  sizeof(p) == 1 bool b;  sizeof(b) == 1

18 Arrays variabler Länge?
Seminar: "Einführung in C/C++" Arrays variabler Länge? ... versuchen wir mal was: int size; cin >> size; int arr [size];  Fehler beim Compilieren Die Dimensionsangaben bei der Definition von Arrays muss eine zur Compilezeit bekannte Konstante sein! Der Gnu-C++-Compiler allerdings lässt den oben beschriebenen Code durchgehen. Das ist allerdings nicht Standardkonform und sollte deswegen vermieden werden.

19 Seminar: "Einführung in C/C++"
Der new - Operator Mit dem new-Operator kann man zur Laufzeit Speicher für Variablen reservieren. Bsp.: int size; cin >> size; int * arr = new int [size]; new liefert einen Pointer auf den reservierten Speicher zurück. arr zeigt nun auf das erste Element eines Arrays von int mit size Elementen. Mit new kann man auch einzelne Variablen erzeugen. Bsp.: double * d = new double;

20 Zu jedem new gehört ein delete!
Seminar: "Einführung in C/C++" Zu jedem new gehört ein delete! Ein mit dem new-Operator reservierter Speicherbereich muss mit dem delete-Operator wieder freigegeben werden: int * arr = new int [100]; // ... // verwende arr delete arr; Delete braucht als Argument einen Pointer, der exakt auf den Anfang des mit new reservierten Speicherbereiches zeigt. Es gibt außerdem einen Operator delete [], der bei arrays von Objekten verwendet werden muss – aber nur dort! memory leak

21 Themawechsel: lokale Variablen
Seminar: "Einführung in C/C++" Themawechsel: lokale Variablen Wiederholung: Gültigkeit von Deklarationen Regel 2: »Eine Deklaration, die innerhalb eines { } -Blockes steht, gilt auch nur lokal innerhalb dieses Blockes.«

22 Beispiel für eine lokale Variable
Seminar: "Einführung in C/C++" Beispiel für eine lokale Variable int X = 12; int readNumber() { int X;  neues X! std::cin >> X; return X; } int Y = readNumber(); std::cout << X;  Ausgabe: 12

23 Lokale Variablen sterben jung
Seminar: "Einführung in C/C++" Lokale Variablen sterben jung int * getPrimArray() { int arr[] = {2, 3, 5, 7}; return arr;  Problem! } int * prims = getPrimArray(); Variable arr wird nach Ende der Funktion getPrimArray() zerstört. Das Problem kann dadurch behoben werden, dass man arr zu einer static-Variablen macht, wie im folgenden beschrieben wird. Eine viel bessere Lösung wäre aber vermutlich, arr einfach mit new zu erzeugen.

24 Lebensdauer von Variablen
Seminar: "Einführung in C/C++" Lebensdauer von Variablen 1. Static-Variablen: Die Variable „lebt“ so lange wie das Programm läuft. 2. Auto-Variablen: Die Variable „lebt“ so lange, bis der die Definition umgebene { }-Block verlassen wird. 3. Heap-Variablen: Die Variable „lebt“ so lange, bis sie mit delete zerstört wird.

25 Das Schlüsselwort static
Seminar: "Einführung in C/C++" Das Schlüsselwort static Mit static kann man eine lokale Variable von einer Auto- zu einer Static-Variablen machen. Bsp.: void ichZaehleMit() { static int count = 0; ++count; std::cout << "Aufruf " << count << "."; } Die Variable counter ist lokal, d.h. sie ist nur innerhalb der Funktion ichZaehleMit() bekannt, und sie ist statisch, d.h. sie wird nicht bei jedem Funktionsaufruf neu erzeugt und weggeworfen, sondern einmal beim Start des Programmes angelegt und initialisiert. Sie „lebt“ bis zum Ende des Programmes.

26 Rückgabe in Argumenten
Seminar: "Einführung in C/C++" Rückgabe in Argumenten Beispiel für eine Funktion mit mehr als einem Rückgabewert: void nimmZwei(int * X, int * Y) { std::cin >> *X; std::cin >> *Y; } int A, B; nimmZwei(&A, &B);

27 Alternative zu Pointern
Seminar: "Einführung in C/C++" Alternative zu Pointern Das gleiche Beispiel, aber diesmal mit Referenzen: void nimmZwei(int & X, int & Y) { std::cin >> X; std::cin >> Y; } int A, B; nimmZwei(A, B);

28 Seminar: "Einführung in C/C++"
Referenzen Technisch gesehen sind Referenzen Pointer – sie tun aber so, als wären sie keine. Pointer Referenzen int X; int X; int * ptr = & X; int & ref = X; *ptr = 12; ref = 12; Vorsicht: Man verwechsele nicht das & in der Definition/Deklaration einer Referenz mit dem address-of-Operator! Durch die Initialisierung wird festgeschrieben, auf welche Variable eine Referenz zeigt. Das kann später so einfach nicht mehr verändert werden. Referenzen müssen immer initialisiert werden – oder sie sind formale Parameter bei Funktionen, dann werden sie bei jedem Funktionsaufruf ja auch initialisiert. Bsp: int & X; //Fehler! Nicht initialisiert!

29 1. Quiz: Referenzen „umbiegen“.
Seminar: "Einführung in C/C++" 1. Quiz: Referenzen „umbiegen“. Frage: Was gibt dieses Programm aus? int X = 5; int Y = 8; int & Z = X; Z = Y; std::cout << X; Antwort: „8“. Durch die Zeile Z=Y; wird nicht etwa die Referenzvariable Z umgesetzt, so dass sie auf Y zeigt, sondern der Inhalt von Y wird in das Ziel von Z (also X) geschrieben.

30 Seminar: "Einführung in C/C++"
2. Quiz: ein kurzes Array Frage: Was ist der Unterschied zwischen folgenden Variablen? int Var1 = 5; int Var2 [] = {5}; In beiden Fällen wird genau eine Variable vom Typ int erzeugt. Wenn ich aber auf den Wert von Var1 zugreifen will kann ich Var1 = 12; schreiben, bei Var2 brauche ich einen indirection-Operator (*Var2 = 12;) oder einen subscript-Operator (Var2[0] = 12;).

31 Seminar: "Einführung in C/C++"
3. Quiz: Lauter Zeichen! Was bedeuten die einzelnen markierten Zeichen in folgendem Code? int X [] = { 1, 2, 3 }; int Y = X[1] & X[2]; int & Z = X[0]; int * A = & Z; Z = Z * * X; [ ] in der Variablendefinition: Definition eines Arrays. [ ] in einem Ausdruck: subscript-Operator. & als binärer Operator: bitweises UND. & in einer Variablendefinition: Definition einer Referenz. * in einer Variablendefinition: Definition eines Pointers. & als unärer Operator: address-of-Operator- * als binärer Operator: Multiplikation * als unärer Operator: indirection-Operator

32 (Notizseite) Seminar: "Einführung in C/C++" Aufgaben zum Dienstag:
Schreiben Sie eine Funktion, die einen CString umdreht, so dass z.B. "Hamster" zu "retsmaH" wird. (Dabei dürfen Sie natürlich keine Funktion aus den Standardbibliotheken verwenden, die genau das bereits tun.) 7. Aufgabe: Schreiben Sie ein Programm, das eine (vorher nicht festgelegte) Anzahl von Strings von std::cin einliest und diese anschließend lexikalisch sortiert wieder ausgibt. 8. Aufgabe: Es gibt Nullpointer, aber angeblich keine „Nullreferenzen“. Versuchen Sie, mit geschickten cast-Operationen eine Referenzvariable vom Typ int & doch dazu zu bringen, auf die Adresse 0 zu verweisen. Gelingt es Ihnen auch, mit Hilfe von cast-Operationen eine einmal initialisierte Referenz auf eine andere int-Variable umzubiegen? 9. Aufgabe: Die Edit-Distanz dist(A, B) zwischen zwei Strings A und B ist definiert als die minimale Anzahl von Änderungen, die man an einem der Strings vornehmen muss, um ihn in den anderen String zu verwandeln. Als „Änderung“ stehen dabei folgende Operationen zur Verfügung: 1. Ein einzelnes Zeichen an einer beliebigen Stelle in den String einfügen, 2. ein beliebiges einzelnes Zeichen aus dem String löschen, 3. ein beliebiges Zeichen des Strings in ein andere Zeichen verwandeln. Diese Edit-Distanz kann ziemlich effizient unter Einsatz von dynamischem Programmieren berechnet werden: Statt nur dist(A, B) zu ermitteln, berechnen wir die Edit-Distanz dist(A‘, B‘) aller Paare A‘ und B‘, wobei A‘ ein Präfix von A ist (d.h. A fängt mit A‘ an) und B‘ ein Präfix von B ist. Wenn A‘ genau i Zeichen lang ist und B‘ genau j Zeichen, dann speichern wie dist(A‘, B‘) in einer (zweidimensionalen) Matrix M an der Stelle M(i, j), d.h. in der i-ten Zeile und der j-ten Spalte. Im Einzelnen sieht der Algorithmus dann so aus: Initialisierung: M(0, 0) = 0 M(i, 0) = i, für i > 0 M(0, j) = j, für j > 0 Rekursion: M(i, j) = min( M(i - 1, j – 1) + d(i, j), M(i-1, j) + 1, M(i, j-1) + 1) für i > 0 und j > 0 Dabei ist d(i, j) = 0, wenn das i-te Zeichen von A gleich dem j-ten Zeichen von B ist, sonst ist d(i, j) = 1. Schreiben Sie ein Programm, das zwei Strings einliest und die Edit-Distanz der beiden Strings berechnet. Denken Sie auch an den Wettbewerb „Selbstreproduzierender Code“! (Notizseite)


Herunterladen ppt "Einführung in die Programmiersprache C/C++"

Ähnliche Präsentationen


Google-Anzeigen