Informatik 1 (251-0832-00) D-MAVT F2010 Kontrollanweisungen 1, ASCII Yves Brise 20100317 - Übungsstunde 3 Inhalt Ziele: • Prüfungsaufgabe • Festigung & Repetition • Kontrollstrukturen Bemerkung zu Übungsabgabe: Wenn möglich die Zeilenlänge in Dateien auf 80 beschränken. Lässt sich besser drucken. Yves Brise 20100317 - Übungsstunde 3 Prüfungsaufgabe Deklarieren sie a, b und c so, dass die nachfolgenden Anweisungen fehlerfrei kompilieren und nicht implizit konvertiert wird. i) a = 5; b = a < 3; c = ‘4’; ii) a = b || char(c-5) == ‘b’; Lösung: i) int a; bool b; char c; ii) bool a, b; int c; Yves Brise 20100317 - Übungsstunde 3 Deklarieren vs Definieren Deklaration Wir sagen dem Compiler, wie ein Objekt heisst. Es wird kein Speicher reserviert. Z.B.Variablendeklaration, Funktionsdeklaration, Klassendeklaration. int a; int my_function(double p); class my_agent; Definition Wir sagen dem Compiler, wie ein Objekt heisst, aber auch wie es implementiert ist (resp. was für einen Wert es hat). int a = 1; int my_function(double p) {...} class my_agent {...}; Yves Brise 20100317 - Übungsstunde 3 Typ, Wert und Effekt int a; a = 3; Die Zweite Anweisung hat den Typ int, den Wert 3 und den Effekt, dass der Variable a 3 zugewiesen wird. Typ int, Wert 2 und die Effekte, dass a neu den Wert 2 und b neu den Wert 1 hat. int a(1), b(0); a += ++b; std::cout << ”Hallo”; Typ std::ostream&, Wert ist eine Adresse, Effekt ist, dass “Hallo” auf den Ausgabestrom geschrieben wird. Typ int, Wert vermutlich 0, Effekt ist, dass die main Funktion ausgeführt wird... Yves Brise main(); 20100317 - Übungsstunde 3 Schnellübung Diskutieren Sie Typ, Wert und Effekt der folgenden Anweisungen. Lösung: Der Typ ist immer int. a) Wert 35 als rvalue, Effekt: a wird 5 und b wird 7 zugewiesen. b) Wert 5 als lvalue, Effekt: a und b wird beiden 5 zugewiesen. c) Wert 5 als lvalue, Effekt: a wird 5 zugewiesen. d) ungültig, da a*3 ein lvalue ist. e) undefiniert. int a(0), b(1); a) (a=5)*(b=7); b) a=(b=5); c) (a=b)=5; d) (a*3)=(b*5); e) (a=b)*(b=5); Yves Brise 20100317 - Übungsstunde 3 Sequenzen von + und Gruppierungsregel Wenn mehrere + oder - Zeichen aufeinander folgen, dann werden sie von links nach rechts zu Paaren zusammengefasst. Unter Umständen bleibt dann ganz rechts ein Zeichen übrig. ok Bsp. a+++b; a+(+(+b)), a+(++b), (a++)+b a++b; a+(+b), (a++)b ---a; -(-(-a), -(--a), --(-a) nok Yves Brise 20100317 - Übungsstunde 3 Schrittweise Auswertung Nicht nur das Endresultat zählt, sondern auch die Zwischenschritte! Vgl. short-circuit evaluation (auch unter dem Begriff lazy evaluation subsumiert). Bsp: !(9 % 2) || 9 % 3 !(1) || 9 % 3 !true || 9 % 3 Solange wir nicht wissen, was auf der linken Seite steht, rühren wir die rechte Seite nicht an. In Schritt 3 finden wir, dass die linke Seite false ist. Das heisst kein Kurzschluss. false || 9 % 3 false || 0 false || false false Alternativ: true || 9 % 3 true Yves Brise Kurzschluss! 20100317 - Übungsstunde 3 ASCII Yves Brise 20100317 - Übungsstunde 3 “Rechnen” mit ASCII Der Typ char ist nichts anderes als eine ganze Zahl mit kleinerem Wertebereich als int. char c = ’A’; for (int i = 0; i < 26; ++i) { std::cout << static_cast<char>(c + i); } Anderes Beispiel: Konvertieren zu Ziffern char c = ’9’; int a = c - ’0’; std::cout << a << ” has ASCII code ” << static_cast<int>(c); Yves Brise 20100317 - Übungsstunde 3 Konstanten 1. Möglichkeit #define PI 3.14159 Vorteil: Braucht keinen Speicher. Wird vom Präprozessor erledigt. Einfache Textersetzung. Nachteil: Berücksichtigt keine Gültigkeitsbereiche und bei komplizierteren Definitionen (Makros) kann es zu unerwünschten Nebeneffekten kommen (Vgl. Beispiel max aus der Vorlesung). Yves Brise 20100317 - Übungsstunde 3 Konstanten 2. Möglichkeit const double pi = 3.14159; Nachteil: Braucht Speicher Vorteil: Respektiert Gültigkeitsbereiche, d.h. keine Ersetzung an unerwünschten Stellen. Bessere Diagnostik, bei Fehlersuche. const int NUMBER = -42; int main() { int x = -NUMBER; } Yves Brise #define NUMBER -42 int main() { int x = -NUMBER; } 20100317 - Übungsstunde 3 Fehler Konstanten Const Richtline Immer wenn man eine Variable definiert, sollte man sich fragen, ob der Wert verändert werden soll. Falls nein, dann ist ein const zu setzen. Yves Brise 20100317 - Übungsstunde 3 if-then-else Anweisung if (condition) { ... } else { ... } Kurzform... Praktisch für Einzeiler. Bei einer einzlenen Anweisung kann der Block weggelassen werden. Meine Empfehlung: Klammern IMMER setzen. Vorteile: Lesbarkeit, Robustheit condition ? expr1 : expr2 std::cout << (a>0 ? ”Pos” : ”Neg”); Yves Brise 20100317 - Übungsstunde 3 Lösen quadratischer Gleichungen Aufgabe: Schreiben Sie ein Programm, welches drei Zahlen a, b und c einliest und anschliessend die reellen Lösungen der quadratischen Gleichung ax 2 + bx + c = 0 berechnet. √ −b ± b 2 − 4ac Zur Erinnerung: x1,2 = 2a Ausgabe: “Es gibt k Lösungen”, wobei k=0,1,2, gefolgt von den Lösungen. Oder “Es gibt unendlich viele Lösungen”. Hilfestellung: • Überprüfen Sie zuerst, ob a Null ist. Falls nicht, dann 2 überprüfen Sie, ob b − 4ac Null oder negativ ist. • Wurzelziehen mit std::sqrt(double) Yves Brise 20100317 - Übungsstunde 3 Lösen quadratischer Gleichungen double s1(0.0), s2(0.0); int n(0); if (a == 0.0) // linear case: bx + c = 0 if (b == 0.0) // trivial case: c = 0 if (c == 0.0) n = -1; // => infinitely else n = 0; // => no solution else { // bx + c = 0, b != 0 => s1 = -c/b; n = 1; } else { double d = b*b-4.0*a*c; if (d == 0.0) { // ax^2 + bx + c = 0, a != s1 = -b / (2.0*a); n = 1; } else { // ax^2 + bx + c = 0, a != s1 = (-b + std::sqrt(d)) / s2 = (-b - std::sqrt(d)) / n = 2; } } Siehe Datei solve_quad_eq.cpp. many solutions one solution 0, d==0 => one solution 0, d!=0 => two solutions (2.0*a); (2.0*a); Yves Brise Lösung dort ist noch ein wenig ausgereifter als die nebenstehende. Es werden Funktionen und der Typ complex<double> aus dem Namensraum std verwendet. Lösung hier noch unvollständig für reelle Zahlen. Es wird nicht geprüft, ob d<0. 20100317 - Übungsstunde 3 switch Anweisung • Anhand der Auswertung von switch (expr) { case <val1>: ... break; case <val2>: ... break; default: ... } expr wird entschieden, wohin gesprungen wird. • Von der Sprungstelle geht die Auswertung einfach sequentiell weiter, d.h. die cases werden ignoriert. • Die Anweisung break beendet die Ausführung des switch. Kann man auch bei do, for und while gebrauchen. Yves Brise 20100317 - Übungsstunde 3 Ziffern extrahieren In Aufgabe 5 müssen Sie die Ziffern einer ganzen Zahl extrahieren. Im Allgemeinen: int a(...); // Positive ganze Zahl kleiner als 2^31 int digits[10]; // Feld (Array) für die Ziffern int b(10); // Basis des Zahlensystems for (int i = 0; a > 0; ++i) { digits[i] = a % b; // letzte Stelle extrahieren a /= b; // letzte Stelle wegschmeissen } Am Ende stehen die Ziffern in digits[0], digits[1], ..., geordnet von der am wenigsten signifikanten zur am meisten signifikanten. Yves Brise 20100317 - Übungsstunde 3 Ziffern extrahieren Im Speziellen für Aufgabe 5. Wir wissen, dass wir nur Zahlen kleiner 100 betrachten, d.h. maximal 2 Stellen. int a(...); // Positive ganze Zahl kleiner als 100 int einer(0), zehner(0); einer = a % 10; zehner = a / 10; Genau das selbe Prinzip, aber für eine fixe Anzahl von Stellen. Yves Brise 20100317 - Übungsstunde 3 Tipps zu Serie 3 Aufgaben 1, 2: Machen Sie schrittweise Auswertung. Aufgaben 3: Erstens: 5 ist kein echter Teiler von 5. Zweitens: Die Bibliothek cmath enthält eine Funktion abs, um den Absolutwert zu berechnen. Aufgaben 4: Sehr ähnlich wie das Lösen quadratischer Gleichungen → Determinanten ausrechnen und Fälle unterscheiden. Aufgaben 5: Siehe Tipps auf dem Übungsblatt und das Extrahieren der Ziffern, das wir heute gesehen haben. Was nicht erwähnt ist, sind negative Zahlen. Überlegen Sie sich, was Sie in diesem Fall tun wollen. Yves Brise 20100317 - Übungsstunde 3