Annehmende Schleife do while Schleife mit nachfolgender Bedingungsprüfung: annehmende Schleife B S Mit B wird eine Bedingung (logischer Ausdruck) bezeichnet, S ist ein Strukturblock. Zuerst wird S ausgeführt, danach wird B getestet. Ergibt dieser Test false, so wird der nächste Strukturblock verarbeitet. Liefert der Test true, so wird der vorliegende Strukturblock S erneut ausgeführt. C++ Syntax: //Anweisungen aus S while (B); Unterschied zur annehmenden Schleife: S wird mindestens einmal ausgeführt! Empfehlung: Nur anwenden in begründeten Ausnahmefällen, z.b. wiederholte Benutzereingabe Beispiel 1 int Counter::accumulate() { int nextval; value = 0; nextval = get_int("gib Ganzzahl>0"); value += nextval; while ( nextval >0 ); return value-=nextval; value; Schleifenvariable Rückgabewert initialisieren "Nutzleistung" Vom Benutzer eingegebene positive Zahlen sollen aufsummiert werden. Schleifenvariable Richtung Ziel verändern sentinel: nextval<0 Achtung: Sentinelwert wird auch addiert! Was nun? 26.05.2010 66
Annehmende Schleife do while Beispiel 2 void Counter::countdown() { if( value==0 ) throw std::runtime_error(); cout << value << endl; --value; while (value ); cout << 0 << endl; assert (value == 0 ); 1. Wichtig: Zuerst die Zusicherungen. Daraus ergeben sich die notwendigen lokalen Variablen! 2. Algorithmus schreiben und Prüfbedingung festlegen. 3. Prüfen des Algorithmus mit Extremwerten: wert = 1 ok wert > 1 ; z.b wert = 2 ok Frage: Ist das übersetzungsfähig? Compilermeldung: 'c': nichtdeklarierter Bezeichner do { char c; cin >> c; while ( c!= '*' ); Begründung: Speicherklasse von c ist "auto", d.h. c ist lokale Variable im Strukturblock S c ist nur im Strukturblock S definert! Gültigkeitsbereich von c endet mit '' char c = ' '; Diese Schleife while ( c!= '*' ){ endet nie! char c; cin >> c; cout << c; 26.05.2010 67
Schleife mit fester Wiederholungsanzahl - for Eigentlich überflüssig, aber von Programmierern gern benutzt SV initialisieren Solange Bedingung B wahr ( 0) ist S SV verändern Richtung Ziel Beispiel: Quadratzahltabelle C++ Syntax for ( SVinit; B; SVincrement) S; S ist äquivalent zu SVinit while (B) { S SVincrement for ( int i = 1; i <= 3; i++ ) cout << i << i*i << endl; 1 2 4 SV Initialisierung! C++: Gültigkeitsbereich von i ist nur die for-anweisung. d.h. for( int i=0; i<10; ++i ) { i = 0; quittiert der C++ Compiler mit Fehlermeldung: 'i': nichtdeklarierter Bezeichner 3 Ausgabe 1 1 2 4 3 9 26.05.2010 68
Einfache Beispiele für for - Anweisung a ) Dekrementieren der SV in Schritten von 1 for ( int i = 5 ; i >= 1 ; i-- ) { cout << i << ' '; Ausgabe: 5 4 3 2 1 b ) Inkrementieren der SV in Schritten > 1 for ( int i = 7 ; i <= 35 ; i +=7 ) { cout << i << ' '; Ausgabe: 7 14 21 28 35 c ) Dekrementieren der SV in Schritten > 1 for ( int i = 10 ; i >= 2 ; i -=2 ) { cout << i << ' '; Ausgabe: 10 8 6 4 2 26.05.2010 69
Schleife mit fester Wiederholungsanzahl - for Beispiel: countdown void Counter::countdown() { assert ( value > 0 ); for ( ; value ; --value ) cout << value << endl; 1. Wichtig: Zuerst die Zusicherungen. Daraus ergeben sich die notwendigen lokalen Variablen! 2. Algorithmus schreiben und Prüfbedingung festlegen. assert (value == 0 ); 3. Prüfen des Algorithmus mit Extremwerten und ggf. Prüfbedingung/Algorithmus korrigieren : value = 1 value > 1 ; z.b value = 2 Jeder der 3 Ausdrücke in for-anweisung kann weggelassen werden: Beispiel for ( ; ; ) cout << "Wird nie fertig" besser for ( ; true ; ) S 26.05.2010 70
Schleife mit fester Wiederholungsanzahl - for Beispiel: GGT zweier Ganzzahlen mit for Hausaufgabe Lösung mit Pseudocode Vorbedingung? Nachbedingung? Schleifenvariable ggt mit Minimum beider Zahlen initialisieren Prüfen, ob beide Zahlen ohne Rest durch ggt teilbar sind Falls ja, Schleife verlassen und mit nächster Anweisung fortfahren Falls nein, ggt um eins vermindern 26.05.2010 71
Der Komma-Operator meist in for-anweisung verwendet erlaubt dort mehrere Ausdrücke, wo syntaktisch nur 1 Ausdruck stehen darf hat den niedrigsten Vorrang wertet von links nach rechts aus Gesamtausdruck hat den Wert des ganz rechts stehenden Ausdrucks Beispiel 1 int i, j, summe(0); for ( i = 100, j=1; j < i; i--, j++ ) summe += i + j; cout << summe; Was leistet diese Anwendung? Beispiel 2 int i,j; int z = ( i=20, j=2*i); Welche Werte werden zugewiesen? Warum muss hier geklammert werden? 26.05.2010 72
Kontrollstruktur Mehrfache Auswahl mit switch case A w 1 w 2 w n S 1 S 2 S n In den beiden Diagrammen steht A für einen Ausdruck, der stets einen der (ganzzahligen) Werte w 1, w 2,... ergibt. Der unter dem entsprechenden w i stehende Strukturblock S i wird ausgeführt. A w 1 w 2 sonst S 1 S 2 S C++ kann das nur bedingt: switch ( A ) { case w1: S1; break; case w2: S2; break; case wn: Sn; break; default: S; break; Optional; muss nicht letzte Marke sein. Es gibt folgende Variante, bei der der Strukturblock S unter 'sonst' aufgeführt wird, falls A nicht einen der w i ergibt: muss ganzzahliger Ergebnis-Typ sein break verzweigt hinter das Ende der switch- Anweisung optional Beispiel: Menüsteuerung char Option cout << "Moegliche Optionen: a/b/x\n" "Gib Option: "; cin >> Option; switch (Option) { case 'a': S1(); case 'b': S2(); case 'x': cout << "Programmende"; default: cout << "Option gibt es nicht!"; while (Option!= 'x'); 26.05.2010 73
Ziffern, Zwischenraum und andere Zeichen zählen void main () { char c; int whitespace(0), number(0), other(0); c = cin.get(); switch (c) { case ' ': case '\n': case '\t': whitespace++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': number++; break; default: other++; break; while ( c!= EOF ); --other; cout << "\ndie Eingabe enthielt" << endl << number << " Ziffern" << endl << whitespace << " Zwischenraumzeichen " << "und" << endl << other << " andere Zeichen." << endl; In C++ können Zeichen in jedem Ganzzahltyp gespeichert werden, da sie intern als 1-byte-Ganzzahlen dargestellt werden. Liest genau ein Zeichen von Tastatur ein. Notwendig, weil cin Zwischenraumzeichen entfernt. Sentinel ist EOF (iostream) "End of File"; Wert = -1; Eingabe plattformabhängig (Windows: ctrl-z). EOF muß am Zeilenanfang stehen. sonst wird es von cin ingnoriert und der Eingabepuffer gelöscht Das newline-zeichen am Ende jeder Eingabe darf nicht mitgezählt werden. 26.05.2010 74