252-0027 Einführung indie Programmierung 2.5“if”-Anweisungen 2.6Nochmals Schleifen:“while”Loops 2.YOutput ThomasR.Gross DepartmentInformatik ETHZürich Uebersicht § 2.2Typen undVariable § Deklaration vonVariablen § 2.3Schleifen (Loops) § 2.3.1“for”Loops § 2.3.2Verschachtelte Schleifen § 2.4Methoden mit Parametern § 2.5“if”-Anweisungen § 2.6Nochmals Schleifen § “while”Loops § 2.XInput § 2.YOutput 2 Faktorisierung für if/else Anweisungen § Example: if (a == 1) { System.out.println(a); x = 3; b = b + x; } else if (a == 2) { System.out.println(a); x = 6; y = y + 10; b = b + x; } else { // a == 3 System.out.println(a); x = 9; b = b + x; } System.out.println(a); x = 3 * a; if (a == 2) { y = y + 10; } b = b + x; Boolesche Ausdrücke if (((x>0) && (y>0)) && (z > 0)) { // block 1 } // more code if (((x>0) && (y>0)) && (z >= 0)) { // block 2 } § Wasist andiesem CodeBeispiel schlecht? 4 Boolesche Ausdrücke if (((x>0) && (y>0)) && (z > 0)) { // block 1 } // more code if (((x>0) && (y>0)) && (z >= 0)) { // block 2 } § Wasist andiesem CodeBeispiel schlecht? § (x>0) && (y>0) mehrfach berechnet 5 Typ boolean § Boolesche Werte können inVariablen desTyps boolean gespeichert werden. § boolean ist ein Basistyp (primitivetype) § Parameterübergabe: § DerTyp boolean kennt nur zwei Werte:wahr (true)und falsch (false). § boolean quadrant1; § Oderboolean quadrant1 = true; deklarieren boolesche Variable. Typ boolean § Boolesche Werte können inVariablen desTyps boolean gespeichert werden. § boolean ist ein Basistyp (primitivetype) § Parameterübergabe:valuesemantics § DerTyp boolean kennt nur zwei Werte:wahr (true)und falsch (false). § boolean quadrant1; § Oderboolean quadrant1 = true; deklarieren boolesche Variable. Typ boolean § Ein Vergleich ("test")ist ein boolescher Ausdruck (ein Ausdruck derein boolean Ergebnis hat). § Ergebnis kann ineiner VariabledesTyps boolean gespeichert werden § Boolesche Variablekönnen mit denbooleschen Operatoren kombiniert werden. Boolesche Ausdrücke mit boolean Variablen boolean quadrant1 = (x>0) && (y>0); if (quadrant1 && (z > 0)) { // block 1 }; // more code if (quadrant1 && (z >= 0)) { // block 2 } § Annahme:keine Aenderung vonx,y …. 11 Typ boolean Beispiele boolean isJugendlicher = (alter < 18); boolean wohntInZuerich = (plz >= 8000) && (plz < 8100); // nur fuer volljaehrige aus Zuerich if (isJugendlicher || !wohntInZuerich) { System.out.println("Kein Zutritt!"); } Hinweise § Manchmal sieht mansolchen Code(testob eine VariabledenWerttrue hat): if (isPrime == true) { // schlecht ... } § Dasist nicht nötig undredundant.Besser : if (isPrime) { ... } // gut Hinweise § Auch nicht besser ist derTestfür false: if (isPrime == false) { // schlecht if (!isPrime) { // gut Bedingte ("short-circuit")Auswertung § Für && und|| müssen nicht immer beide Operanden ausgewertet werden,umdasErgebnis zu ermitteln § Javabeendet dieAuswertung eines booleschen Ausdrucks sobald dasErgebnis feststeht. § Ausdrücke werden vonlinksnach rechts,gemäss Präzedenz ausgewertet § && stoppt sobald ein Teil(ausdruck)false ist § || stoppt sobald ein Teil(ausdruck) true ist Bedingte ("short-circuit")Auswertung § Javabeendet dieAuswertung eines booleschen Ausdrucks sobald dasErgebnis feststeht. § Ausdrücke werden vonlinksnach rechts,gemäss Präzedenz ausgewertet § && stoppt sobald ein Teil(ausdruck)false ist § || stoppt sobald ein Teil(ausdruck) true ist § Diese ArtderAuswertung heisst bedingte Auswertung § Folgende Teilausdrücke werden abhängig vonzuerst ausgewerteten Ausdrücken (nicht)evaluiert Auswertung desTests § Wir wollen nur Quotienten (für a,b)grösser als 0drucken: Scanner console = new Scanner(System.in); System.out.print("Eingabe zweier Zahlen: "); int a = console.nextInt(); int b = console.nextInt(); System.out.println(a + " / " + b + " = " + a/b); ... Auswertung desTests § Viele "if"Statementsmachen denCodeunlesbar Scanner console = new Scanner(System.in); System.out.print("Eingabe zwei Zahlen: "); int a = console.nextInt(); int b = console.nextInt(); if ( b!=0) { if ( a/b>0 ) { System.out.println(a + " / " + b + " = " + a/b); }; } ... Auswertung desTests § Wir wollen nur Quotienten (für a,b)grösser als 0drucken: Scanner console = new Scanner(System.in); System.out.print("Eingabe zweier Zahlen: "); int a = console.nextInt(); int b = console.nextInt(); // a/b > 0 UND // b != 0 System.out.println(a + " / " + b + " = " + a/b); } ... Reihenfolge ist wichtig § Dieser Codeführt zu einer Fehlermeldung wenn b==0: // Warning. Scanner console = new Scanner(System.in); System.out.print("Eingabe zweier Zahlen: "); int a = console.nextInt(); int b = console.nextInt(); if (a/b>0) && (b!=0) { System.out.println(a + " / " + b + " = " + a/b); }; } ... Bedingte ("short-circuit")Auswertung § Dieser Codeführt zu keiner Fehlermeldung wenn b==0: // Now there is no problem Scanner console = new Scanner(System.in); System.out.print("Eingabe zweier Zahlen: "); int a = console.nextInt(); int b = console.nextInt(); if (b!=0) && (a/b>0) { System.out.println(a + " / " + b + " = " + a/b); }; } ... 38 40 DeMorgan'sRegeln DeMorgan'sRegeln:Regeln für dieNegationboolescher Ausdrücke. § Praktisch wenn mandasGegenteil eines Ausdrucks braucht. Ursprünglicher Ausdruck Negierter Ausdruck Alternative a && b a || b !a || !b !a && !b !(a && b) !(a || b) § Beispiel: Original if (x == 7 && y > 3) { Negiert if (x != 7 || y <= 3) { ... } ... } 2.5Nochmals Schleifen § Bisher:Obergrenze für Schleifenzähler standzu Beginn der Schleife fest § Jetzt:mehr Flexibilität § Korrekte Terminierung wichtig 43 Eine triviale Aufgabe ... § Schreiben Sie eine Methode printNumbers diedieZahlen von1bis Ndurch Komma getrennt ausgibt. Beispiel: Obergrenze N eingeben: sollte ergeben: 1, 2, 3, 4, 5 5 Fehlerhafte Lösungen public static void printNumbers() { Scanner console = new Scanner(System.in); System.out.print("Obergrenze N eingeben: "); int max = console.nextInt(); for (int i = 1; i <= max; i++) { System.out.print(i + ", "); } System.out.println(); // to end the line of output } Outputbei Eingabe 5: 1, 2, 3, 4, 5, Fehlerhafte Lösungen public static void printNumbers() { Scanner console = new Scanner(System.in); System.out.print("Obergrenze N eingeben: "); int max = console.nextInt(); for (int i = 1; i <= max; i++) { System.out.print(", " + i); } System.out.println(); // to end the line of output } Outputbei Eingabe 5: , 1, 2, 3, 4, 5 Gartenzaun Analogie § Wir geben n Zahlen aus aber brauchen nur n - 1Kommas. § Aehnlich dem Bau eines Weidezaunes mit Pfosten und Querstreben § Wenn wir - wie inder1.fehlerhaften Lösung – Pfosten undStreben installieren dann hatderletzte Pfosten inderLuft hängende Streben. for(Laenge desZauns){ Betoniere Pfosten. Installiere Querstreben. } Schleife § Fügen Sie eine Anweisung ausserhalb derSchleife hinzu um denersten "Pfosten"zu plazieren Betoniere Pfosten. for(Laenge desZauns - 1){ Installiere Querstreben. Betoniere Pfosten. } Lösungen basierend aufdieser Idee System.out.print(1); for (int i = 2; i <= max; i++) { System.out.print(", " + i); } System.out.println(); // to end the line Alternative:1.oder letzter Durchlauf durch dieSchleife kann verändert werden: for (int i = 1; i <= max - 1; i++) { System.out.print(i + ", "); } System.out.println(max); // to end the line "off-by-one"Error(Um-Eins-daneben-Fehler) § DieSchleife wurde einmal zuviel (oder einmal zuwenig) durchlaufen. § "Zaunpfahlproblem"– es gibt sogar eine DWikipediaSeite (Inhalt ohne Gewähr) 50 Terminierung vonLoops § Verwandeln Sie dieMethode printNumbers ineine neue Methode printPrimes diealle Primzahlen bis zur Obergrenze maxausgibt. § Beispiel:printPrimes mit Eingabe 50ergibt: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 § Wenn max<2,gebe nichts aus. § Eine Primzahl p kann ingenau zwei Faktoren zerlegt werden:p und1 53 // Prints all prime numbers up to the given max. publicstaticvoidmain(String[]args){ Scannerconsole=newScanner(System.in); Beispiellösung System.out.print("Inputmax:"); intmax=console.nextInt(); //Printsallprimenumbersuptothegivenmax. if(max>=2){ System.out.print("2"); for(inti=3;i<=max;i++){ if(isPrime(i,max)){ System.out.print(","+i); } } } } System.out.println(); //isPrimereturnstrueifiisprime 56 while Schleifen Klassifizierung vonSchleifen § bestimmte Schleife (definiteloop):Anzahl derAusführungen desRumpfes ist vorher bekannt. § Diefor Schleifen waren bisher immer bestimmte Schleifen. § Drucke "hello"10-mal. § Finden Sie alle Primzahlen <einer ganzen Zahl n. § Drucken Sie jede ungerade Zahl zwischen 7und91. § unbestimmte Schleife (indefiniteloop):Anzahl der Ausführungen desRumpfes ist nicht vorher bekannt. Klassifizierung vonSchleifen § unbestimmte Schleife (indefiniteloop):Anzahl der Ausführungen desRumpfes ist nicht vorher bekannt. § Lesen Sie denInputvonderKonsole bis derBenutzer eine nichtnegativeganze Zahl eingibt. § Wiederholen Sie bis derBenutzer ein "q"eingegeben hat. § Lesen Sie eine Datei bis drei aufeinanderfolgende Sätze mit einem "!"enden. § Nehmen Sie Beiträge (viacrowdfunding)entgegen bis dasZiel erreicht ist. Diewhile Schleife § while Schleife:Führen Sie denSchleifenrumpf solange aus wie derboolesche Ausdruck test denWerttrue ergibt. while (test) { statement(s); } § Beispiel: int num = 1; while (num*num <= 2000) { System.out.print(num + " "); num = num * 2; } // output: 1 2 4 8 16 32 // initialization // test // update Diewhile Schleife § while Schleife:Führen Sie denSchleifenrumpf solange aus wie derboolesche Ausdruck test denWerttrue ergibt. while (test) { statement(s); } nein ja Ist testwahr? § Beispiel: int num = 1; while (num*num <= 2000) { System.out.print(num + " "); num = num * 2; } // output: 1 2 4 8 16 32 Anweisung(en)im Loopausfuehren Anweisung nach Loopausfuehren 62 Beispiellösung public static boolean isPrime (int arg, int max){ // Determine how many factors the given number has. boolean found = false; int step = 2; } while (!found) { if (arg % step == 0) { found = true; // another factor found } else { step++ ; // keep on searching } } // other factor == arg: prime found return (step == arg); Beispiel while Schleife // finds the first factor of 91, other than 1 int n = 91; int factor = 2; while (n % factor != 0) { factor++; } System.out.println("First factor is " + factor); // output: First factor is 7 § while ist hier bessser als for weil wir nicht wissen wie oftwir den Zähler erhöhen müssen umden1.Faktor zu finden Werte dieHinweise sind … § Hinweiszeichen (Sentinel)("sentinel"):Ein WertderdasEnde eine Reihe anzeigt § sentinelloop:Schleife deren Rumpf ausgeführt wird bis ein Sentinel gesehen wurde § Beispiel:Ein Programm soll Zahlen einlesen bis derBenutzer eine 0eingibt;dann soll dieSumme aller eingegebenen Zahlen ausgegeben werden. § (Indiesem Beispiel ist 0dasHinweiszeichen/derSentinel.) Werte dieHinweise sind … § Beispiel:Ein Programm soll Zahlen einlesen bis derBenutzer eine 0eingibt;dann soll dieSumme aller eingegebenen Zahlen ausgegeben werden. § (Indiesem Beispiel ist 0dasHinweiszeichen/derSentinel.) Enter a Enter a Enter a Enter a The sum number number number number is 60 (0 (0 (0 (0 to to to to quit): quit): quit): quit): 10 20 30 0 Fehlerhafte Lösung § Wasist andiesem Programm falsch? Scanner console = new Scanner(System.in); int sum = 0; int number = 1; // "dummy value", anything but 0 while (number != 0) { System.out.print("Enter a number (0 to quit): "); number = console.nextInt(); sum = sum + number; } System.out.println("The total is " + sum); Ein anderes Hinweiszeichen … § Aendern Sie dasProgramm sodass -1derSentinelist. § Examplelogofexecution: Enter a number (-1 Enter a number (-1 Enter a number (-1 Enter a number (-1 Enter a number (-1 The total is 80 to to to to to quit): quit): quit): quit): quit): 15 25 10 30 -1 Ein anderes Hinweiszeichen … § Setzen Sie denSentinelauf-1: Scanner console = new Scanner(System.in); int sum = 0; int number = 1; // "dummy value", anything but -1 while (number != -1) { System.out.print("Enter a number (-1 to quit): "); number = console.nextInt(); sum = sum + number; } System.out.println("The total is " + sum); § Jetzt ist dasResultfalsch.Warum? The total was 79 DasProblemmit diesem Programm § UnserProgramm folgt diesem Muster: summe =0. while(inputist nicht dersentinel){ drucke prompt;leseinput. addiere inputzu summe. } § Beim letzten Durchlauf durch denRumpf wird derSentinel-1 zur Summe addiert: DasProblemmit diesem Programm § Beim letzten Durchlauf durch denRumpf wird derSentinel-1 zur Summe addiert: drucke prompt;leseinput(-1). addiere input(-1)zu summe. § Beispiel inkorrekter Terminierung (off-by-oneerror, Zaunpfahlproblem): § Müssen N Zahlen lesen aber nur dieersten N-1addieren. Lösung summe =0. drucke prompt;leseinput. while(inputist nicht dersentinel){ addiere inputzu summe. drucke prompt;leseinput. } //setzen eines pfostens //installationquerstrebe //setzen eines pfostens § Schleifen mit einem Sentinelfolgen oftdiesem Muster. Beispiel mit Sentinel Scanner console = new Scanner(System.in); int sum = 0; // pull one prompt/read ("post") out of the loop System.out.print("Enter a number (-1 to quit): "); int number = console.nextInt(); while (number != -1) { sum = sum + number; // moved to top of loop System.out.print("Enter a number (-1 to quit): "); number = console.nextInt(); } System.out.println("The total is " + sum); do/while Schleife § do/while Schleife: Führt dentestamEnde desSchleifenrumpfes aus umzu entscheiden,ob ein weiterer Durchlauf nötig ist § Stellt sicher dass derRumpf { … } mindestens einmal ausgeführt wird. Anweisung(en)im Loopausfuehren do { statement(s); } while (test); Ist testwahr? nein Anweisung nach Loopausfuehren ja do/while Schleife Nochmal Beispiel // Add numbers till -1 is entered Scanner console = new Scanner(System.in); int sum = 0; Anweisung(en)im Loopausfuehren Ist testwahr? nein // first round nothing to add int number = 0; Anweisung nach Loopausfuehren do { sum = sum + number; System.out.print("Enter a number (-1 to quit): "); number = console.nextInt(); } while (number != -1); System.out.println("The total is " + sum); ja