Kapitel 5 Programmierkurs Birgit Engels, Anna Schulze ZAIK Universität zu Köln Kontrollstrukturen Die if-anweisung Die switch-anweisung Die for-schleife Die while-schleife Die do-schleife WS 7/8 /55 Kontrollstrukturen Arten von Kontrollstrukturen Bis jetzt wurden in jedem Programm alle Befehle nacheinander einmal ausgeführt: Das Programm machte (bis auf unterschiedliche Eingabewerte) immer das gleiche. Sogenannte Kontrollstrukturen sind besondere Anweisungen, die es einem Programm ermöglichen, sich unterschiedlich zu verhalten oder Befehlsabfolgen mehrfach auszuführen. Bedingte Ausführung if/if... else-anweisung switch-anweisung (Bedingte) Mehrfachausführung for-schleife while-schleife do... while-schleife 3/55 4
5. Die if-anweisung if ( < Bedingung > ) < Anweisung > oder if ( < Bedingung > ) < Anweisung > else < Anweisung > < Bedingung > ist ein Wert {true, false}, eine Variable vom Typ boolean oder ein boolscher Ausdruck, der zu einem solchen Wert ausgewertet wird. Anweisung ist eine einzelne Anweisung oder ein Block von Anweisungen. Im ersten Fall wird die Anweisung nur ausgeführt, wenn die Bedingung den Wert true hat. Im zweiten Fall wird die Anweisung ausgeführt, wenn die Bedingung den Wert true hat. Andernfalls wird Anweisung ausgeführt. Beispiel für if: IfElse.java 3. boolean b=true, d=false; 4. int a=, c=; 5. if (b) b=false; 6. if (!b) System.out.println( b=false ); 7. if (a>c) System.out.println( a>c ); 8. else System.out.println( a<c oder a=c ); 9. if (a==c) System.out.println( a=c );. if (b=d) System.out.println( b=d );. } b=false a<c oder a=c a=c 5/55 6 Beispiel für if: IfElse.java 3. boolean b=true, d=false; 4. int a=, c=; 5. if (b) b=false; 6. if (!b) System.out.println( b=false ); 7. if (a>c) System.out.println( a>c ); 8. else System.out.println( a<c oder a=c ); 9. if (a==c) System.out.println( a=c );. if (b=d) System.out.println( b=d );. } b=false a<c oder a=c a=c Bedingung liefert Wert true: Anweisung wird ausgefürt. Beispiel für if: IfElse.java 3. boolean b=true, d=false; 4. int a=, c=; 5. if (b) b=false; 6. if (!b) System.out.println( b=false ); gefürt. 7. if (a>c) System.out.println( a>c ); 8. else System.out.println( a<c oder a=c ); 9. if (a==c) System.out.println( a=c );. if (b=d) System.out.println( b=d );. } b=false a<c oder a=c a=c Auswertung von a>b liefert Wer false: Anweisung wird nicht aus Statt dessen wir die else-anweisung ausgefürt. 7/55 8
Beispiel für if: IfElse.java 3. boolean b=true, d=false; 4. int a=, c=; 5. if (b) b=false; 6. if (!b) System.out.println( b=false ); 7. if (a>c) System.out.println( a>c ); 8. else System.out.println( a<c oder a=c ); 9. if (a==c) System.out.println( a=c );. if (b=d) System.out.println( b=d );. } b=false a<c oder a=c a=c Fehler: Anstelle einer Bedingung eine Zuweisung. Geht nur bei boolschen Werten, da Wert der Zuweisung geliefert wird. Wert ist false: Anweisung wird nicht ausgefürt. Beispiel für if: BlockIfElse.java 3. int a=3, b=4, min, max; 4. if (a<b) { 5. min=a; 6. max=b; } 7. else { 8. min=b; 9. max=a; }. System.out.println( min= +min+ max= +max);. } min= 3 max= 4 9/55 Beispiel für if: BlockIfElse.java Häufige Fehler bei if 3. int a=3, b=4, min, max; 4. if (a<b) { 5. min=a; 6. max=b; } 7. else { 8. min=b; 9. max=a; } Zuweisungen von min und max wird. System.out.println( min= +min+ max= +max); durch Block zu einer Anweisung. Innerhalb solcher Blöcke können auch. } weitere if-anweisungen auftreten. min= 3 max= 4 if (a<b) { min=a; max=b; } else min=b; max=a; if (a<b); min=a; Kein Block im else-teil : Als else-anweisung gilt nur min=b;: max=a; wird immer ausgeführt (vgl. NoBlockIfElse.java). Abschluss nach if-bedingung mit ;: leere if-anweisung und min=a; wird immer ausgeführt. /55
Beispiel 3 für if: MoreIfElse.java Beispiel 3 für if: MoreIfElse.java 3. int a=, b=; 4. if (a<b) System.out.println( a<b ); 5. else if (a>b) System.out.println( a>b ); 6. else System.out.println( a=b ); 7. } a<b 3. int a=, b=; 4. if (a<b) System.out.println( a<b ); 5. else if (a>b) System.out.println( a>b ); 6. else System.out.println( a=b ); Verschachtelte if- Anweisung mit 7. } else if: Z.B. als Fallunterscheidung. a<b 3/55 4 Fallunterscheidungen mit else if char c= x ; int ascii; if (c== a ) ascii=97; else if (c== b ) ascii=98;... else if (c== z ) ascii=; else ascii=; Fallunterscheidungen mit else if sind bei vielen Fällen unkomfortabel und enthalten den Overhead der Vergleichsbedingung. Für solche Anwendungen verwendet man daher die switch- Anweisung. 5. Die switch-anweisung switch (< Ausdruck >) { case < Wert > : < Anweisung >; break; case < Wert > : < Anweisung >; break;... default : < Anweisung >; break; } < Ausdruck >: arithmetischer Ausdruck oder einzelne Variable. < Wert >: Wert, den < Ausdruck > annehmen kann. < Anweisung >: einzelne Anweisungen Block von Anweisungen. Die Anweisungen hinter default werden ausgeführt, falls < Ausdruck > keinen der < Wert >e annimt. 5/55 6
switch vs. else if Beispiel für switch: AsciiSwitch.java Die Zeile case < Wert > : < Anweisung >; break; einer switch-anweisung entspricht in etwa der Zeile: (else) if (< Ausdruck >==< Wert >) < Anweisung >; einer else if-anweisung. Die Zeile default : < Anweisung >; break; einer switch-anweisung entspricht der letzten Zeile: else < Anweisung >; // einer else if-anweisung. Nur im default-fall darf break; weggelassen werden. 3. char c= e ; 4. int ascii; 5. switch (c) { 6. case a : ascii=97; break; 7. case b : ascii=98; break; 8.... 9. case z : ascii=; break;. default: ascii=; break;. }. System.out.println(ascii); 3. } 7/55 8 Beispiel für switch: AsciiSwitch.java 3. char c= e ; 4. int ascii; 5. switch (c) { 6. case a : ascii=97; break; 7. case b : ascii=98; break; 8.... 9. case z : ascii=; break;. default: ascii=; break;. }. System.out.println(ascii); Wichtig: Erst break; schliesst einen 3. } case ab. Ohne break; werden weitere Anweisungen ausgeführt! Beispiel für switch: AsciiSwitch.java..... switch (c) { 3. case a : ascii=97; break; 4.... 5. case e : ascii=; 6. case f : ascii=; break; 7.... 8. case z : ascii=; break; 9. default: ascii=; break;. }.... 9/55
Beispiel für switch: AsciiSwitch.java Bemerkung zu break..... switch (c) { 3. case a : ascii=97; break; 4.... 5. case e : ascii=; 6. case f : ascii=; break; 7.... 8. case z : ascii=; break; 9. default: ascii=; break;. }.... Vergessenes break;: Nächste Anweisungen ausgeführt - Falscher Wert! Es kann natürlich auch sinnvoll sein, einen Fall einer switch-anweisung nicht mit break; abzuschliessen. Z.B.: Wenn in Fällen die gleiche Anweisung folgen soll oder im ersten Fall nur zusätzliche Anweisungen zuvor auszuführen sind. Da ein weggelassenes break nur der Bequemlichkeit dient, ein vergessenes aber zu Fehlern führt, sollte generell jedes case mit einem break; abgeschlossen werden. /55 5.3 Die for-schleife for (< Initialbefehl >; < Schleifenbedingung >; < Iteration > ) < Schleifenanweisung >; < Initialbefehl >: Einmalig durchgeführte Anweisung. Meist Deklaration+Initialisierung der Iterationsvariablen (Schleifenindex). < Schleifenbedingung >: Bedingung, die für die nächste Ausführung der < Schleifenanweisung > erfüllt sein muss. < Iteration >: Hochzählen des Schleifenindex. < Schleifenanweisung >: Einzelne Anweisung oder Block von Anweisungen. Verwendung der for-schleife Die for-schleife wird meist verwendet, um eine Folge von Anweisungen (Block) mehrfach auszuführen. Die Zahl der Ausführungen ist dabei oft vorher klar (feste Zahl oder begrenzt durch Wert einer Variablen). Daher werden for-schleifen auch Zählschleifen genannt. Dabei werden immer folgende Schritte ausgeführt:. Initiatbefehl wird einmal ausgeführt.. Bedingung wird geprüft: Falls true: Anweisungen werden ausgeführt. Falls false: Schleife wird beendet. 3. Iteration wird ausgeführt. 4. Weiter bei. Häufigste Art der Verwendung: for( int i=; i<xyz; i++) {tuwas;} 3/55 4
Beispiel für for-schleife (ForIter.java) Beispiel für for-schleife (ForIter.java) 4. for ( int i=; i<anzahl; i++) 4. for ( int i=; i<anzahl; i++) Der Anfangsbefehl wird genau einmal ausgeführt. i erhält einmalig den Wert. 5/55 6 Beispiel für for-schleife (ForIter.java) Beispiel für for-schleife (ForIter.java) 4. for ( int i=; i<anzahl; i++) Die Bedingung i<anzahl wird geprüft. Füri= undanzahl=3 wird der Wert true zurückgegeben. 4. for ( int i=; i<anzahl; i++) Also wird der Anweisungsblock wird ausgeführt. Es wird auf dem Bildschirm ausgegeben. 7/55 8
Beispiel für for-schleife (ForIter.java) Beispiel für for-schleife (ForIter.java) 4. for ( int i=; i<anzahl; i++) Der Iterationsbefehl i++ wird ausgeführt. i hat nun den Wert. 4. for ( int i=; i<anzahl; i++) Die Bedingung i<anzahl wird geprüft. Für i= und i= wird wieder der Wert true zurückgegeben. 9/55 3 Beispiel für for-schleife (ForIter.java) Beispiel für for-schleife (ForIter.java) 4. for ( int i=; i<anzahl; i++) Der Anweisungsblock wird ausgeführt. Es wird und auf dem Bildschirm ausgegeben 4. for ( int i=; i<anzahl; i++) Der Iterationsbefehl i++ wird ausgeführt. i hat nun den Wert 3. 3/55 3
Beispiel für for-schleife (ForIter.java) Fehlerquellen: 4. for ( int i=; i<anzahl; i++) Die Bedingung i<anzahl wird geprüft. Füri=3 undanzahl=3 wird der Wert false zurückgegeben. Die Schleife wird beendet. Die Schleifenanweisung kann (wie bei if) auch (versehentlich) die leere Anweisung sein: for( int i=; i<xyz; i++); {tuwas;} Hier wird tuwas; nur einmal, nach der Schleife ausgeführt. Ist die Fortsetzungsbedingung am Anfang falsch, so wird die Schleifenanweisung nie ausgeführt: int xyz=; for( int i=; i<xyz; i++) {tuwas;} Hier wird tuwas; wegen i<xyz = false nie ausgeführt. Die Anzahl der Schleifendurchläufe wird oft falsch bestimmt, insbesondere durch folgende Unterschiede: int i=; int i=; i<xyz; i<=xyz; 33/55 34 Sonderfälle Bisher wurde Schleifenindex im Anfangsbefehl deklariert und war nur in der Schleife bekannt. Deklaration ist auch vor der Schleife möglich. Man kann dann auch nach Ende der Schleife darauf zugreifen: int i; for(i=; i<n; i++) {tuwas;} System.out.println(i); Die Iteration wird einmal nach jeder Schleifenanweisung ausgeführt. Nach Ende der Schleife hat der Index den Wert, für den die Fortsetzungsbedingung erstmals falsch war. Obiges Programmfragment liefert also die folgende Ausgabe: Achtung: Für Bedingung i<=, ergibt sich die Ausgabe! Allgemeine Fälle for-schleifen können natürlich geschachtelt werden: for(int i=; i<n; i++) { for(int j=; j<m; j++) { System.out.println(i*j); } } Bei einzelnen Anweisungen oder einem Anweisungsblock in nur der innersten Schleife, kann die Schreibweise verkürzt werden: for(int i=; i<n; i++) for(int j=; j<m; j++) System.out.println(i*j); Bei geschachtelten Schleifen auf unterschiedliche Schleifenindizes achten! 35/55 36
Beispiel für for-schleife (ForFakul.java) Beispiel für for-schleife (ForFakul.java) 3. int f=; 4. for (int i=5; i>; i--) 5. f*=i; 6. System.out.println(f); 7. } 3. int f=; 4. for (int i=5; i>; i--) 5. f*=i; 6. System.out.println(f); 7. } Die Variable i kann auch dekrementiert, statt inkrementiert werden! 37/55 38 Beispiel für for-schleife (ForFakul.java) Unbestimmte Schleifen 3. int f=; 4. for (int i=5; i>; i--) 5. f*=i; 6. System.out.println(f); 7. } Dann muss die Variable i nach unten begrenzt werden! Einzelne Elemente der for-klammer können leer bleiben. Es funktioniert auch: for( ; ; ) {tuwas;} Dabei ist eine leere Bedingung immer wahr, d.h. hier wird tuwas; unendlich oft ausgeführt. Trotz leerer Bedingung können die Schleifendurchläufe gezählt werden: for(int i=; ; i++ ) {tuwas;} 39/55 4
Verlassen unbestimmter Schleifen break und continue Unbestimmte Schleifen können auf Arten verlassen werden:. Es tritt eine Ausnahme (Exception) auf (später).. Die Schleife wird abhängig von einer Bedingung mit break verlassen: for(int i=; ; i++ ) { if (i>) break; } Beide Arten eine unbestimmte Schleife zu verlassen sind sehr unschön, da sie zu unübersichtlichen, schwer zu verifizierenden Programmen führen. Daher sollten unbestimmte Schleifen immer vermieden werden. Dies ist (manchmal aufwendiger, aber) immer möglich! Eine Programmiersprache ist mit break nicht mächtiger als ohne! Mit break wird eine Schleife komplett abgebrochen, falls die vorhergehende Bedingung erfüllt ist. Eventuell soll nur ein bestimmter Fall übersprungen werden, für den die Schleife nicht durchgeführt werden soll. Einmaliges überspringen des restlichen Schleifenkörpers gelingt mit: if (i==) continue; Ist die Bedingung erfüllt springt das Programm direkt zum Ende des Durchlaufs und startet die Schleife mit dem nächsten Durchlauf. 4/55 4 Beispiel für continue 5.4 Die while-schleife for(int i=; i< ; i++ ) { if (i==) continue; System.out.println(i); } Dieses Programmfragment gibt alle Werte von bis 9 aus, ausser der. Das gleiche ist aber leicht ohne continue möglich: for(int i=; i< ; i++ ) { if (i!=) System.out.println(i); } while (< Schleifenbedingung >) < Schleifenanweisung >; < Schleifenbedingung >: Bedingung, die für die nächste Ausführung der < Schleifenanweisung > erfüllt sein muss. < Schleifenanweisung >: Einzelne Anweisung oder Block von Anweisungen, die ausgeführt werden, falls < Schleifenbedingung > true liefert. 43/55 44
Verwendung der while-schleife Beispiel für while-schleife (WhileDo.java) Im Gegesatz zur for-schleife steht bei der while-schleife die Schleifenbedingung, nicht die Anzahl der Schleifendurchläufe eher im Vordergrund. Um die Anzahl zu ermitteln, muss man selbst einen Zählindex verwalten. Die Schleifenbedingung ist ein eher komplexerer boolescher Ausdruck. Es werden immer folgende Schritte ausgeführt:. Bedingung wird geprüft: Falls true: Anweisungen werden ausgeführt. Falls false: Schleife wird beendet.. Weiter bei. 3. int zahl=64, i=; 4. while (zahl>) 5. { 6. zahl/=; 7. if (zahl>) i++; 8. } 9. System.out.println(i);. } 6 45/55 46 Beispiel für while-schleife (WhileDo.java) Beispiel für while-schleife (WhileDo.java) 3. int zahl=64, i=; 4. while (zahl>) 5. { 6. zahl/=; 7. if (zahl>) i++; 8. } 9. System.out.println(i);. } Die Bedingung zahl> wird geprüft. 6 Für zahl=64 wird der Wert true zurückgegeben. 3. int zahl=64, i=; 4. while (zahl>) 5. { 6. zahl/=; 7. if (zahl>) i++; 8. } 9. System.out.println(i);. } Der Anweisungsblock wird ausgeführt. 6 zahl wird ihre ganzzahlige Hälfte zugewiesen; da diese > ist, wird i inkremeniert. 47/55 48
Beispiel für while-schleife (WhileDo.java) Beispiel für while-schleife (WhileDo.java) 3. int zahl=64, i=; 4. while (zahl>) 5. { 6. zahl/=; 7. if (zahl>) i++; 8. } 9. System.out.println(i);. } Die Bedingung wird erneut 6 (nun mit zahl=3) geprüft, usw... 3. int zahl=64, i=; 4. while (zahl>) 5. { 6. zahl/=; 7. if (zahl>) i++; 8. } 9. System.out.println(i);. } Es wird der Exponent der grössten enthaltenen Zweierpotenz 6 ausgegeben. 49/55 5 Sonderfälle for vs. while Eine leere Bedingung, ist bei while-schleifen anders als bei for-schleifen standardmässig nicht vorgesehen (erzeugt Kompilierfehler). Eine Endlosschleife mittels while wird mit true als Bedingung erreicht: while (true) < Schleifenanweisung >; Es gelten die gleichen Möglichkeiten zum verlassen einer solchen Endlosschleife mit while wie mit for: Exceptions break; Auch hier kann continue; zum Überspringen einer Ausführung verwendet werden. while-schleifen können verschachelt werden (Blöcke bilden!). Die while-schleife und for-schleife sind äquivalent, es gilt: for(start; Bedingung; Änderung) Anweisung; entspricht: Start; while (Bedingung) { Anweisung; Änderung; } 5/55 5
Bemerkung 5.5 Die do-schleife Wie in den Beispielen gesehen, werden die Bedingungen bei for-schleife und while-schleife vor dem Durchlauf geprüft. Manchmal ist es wünschenswert, mindestens einen Durchlauf zu erlauben, bevor die Bedingung zum ersten Mal überprüft wird. Daher : do-schleife. do < Schleifenanweisung > while (< Schleifenbedingung >); < Schleifenanweisung >: Einzelne Anweisung oder Block von Anweisungen, die ausgeführt werden. < Schleifenbedingung >: Bedingung, die für die nächste Ausführung der < Schleifenanweisung > erfüllt sein muss. In do-schleife entspricht der while-schleife die allen Eigenschaften ausser dem Zeitpunkt der Bedingungsüberprüfung. 53/55 54 Beispiel für do-schleife (DoWhile.java) 3. int zahl=64, i=; 4. do 5. { 6. if (zahl>) zahl/=; 7. i++; 8. } 9. while (zahl>). System.out.println(i);. } 6 55/55