• Keine Ergebnisse gefunden

252-0027 Einführung in die Programmierung

N/A
N/A
Protected

Academic year: 2022

Aktie "252-0027 Einführung in die Programmierung"

Copied!
53
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

252-0027

Einführung in die Programmierung

2.5 “if”-Anweisungen

2.6 Nochmals Schleifen: “while” Loops 2.Y Output

Thomas R. Gross

Department Informatik ETH Zürich

(2)

Uebersicht

§ 2.2 Typen und Variable

§ Deklaration von Variablen

§ 2.3 Schleifen (Loops)

§ 2.3.1 “for” Loops

§ 2.3.2 Verschachtelte Schleifen

§ 2.4 Methoden mit Parametern

§ 2.5 “if”-Anweisungen

§ 2.6 Nochmals Schleifen

§ “while” Loops

§ 2.X Input

§ 2.Y Output 2

(3)

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;

(4)

Boolesche Ausdrücke

if (((x>0) && (y>0)) && (z > 0)) { // block 1

}

// more code

if (((x>0) && (y>0)) && (z >= 0)) { // block 2

}

§ Was ist an diesem Code Beispiel schlecht?

4

(5)

Boolesche Ausdrücke

if (((x>0) && (y>0)) && (z > 0)) { // block 1

}

// more code

if (((x>0) && (y>0)) && (z >= 0)) { // block 2

}

§ Was ist an diesem Code Beispiel schlecht?

§ (x>0) && (y>0) mehrfach berechnet

5

(6)

Typ boolean

§ Boolesche Werte können in Variablen des Typs boolean gespeichert werden.

§ boolean ist ein Basistyp (primitive type)

§ Parameterübergabe:

§ Der Typ boolean kennt nur zwei Werte: wahr (true) und falsch (false).

§ boolean quadrant1;

§ Oder boolean quadrant1 = true;

deklarieren boolesche Variable.

(7)

Typ boolean

§ Boolesche Werte können in Variablen des Typs boolean gespeichert werden.

§ boolean ist ein Basistyp (primitive type)

§ Parameterübergabe: value semantics

§ Der Typ boolean kennt nur zwei Werte: wahr (true) und falsch (false).

§ boolean quadrant1;

§ Oder boolean quadrant1 = true;

deklarieren boolesche Variable.

(8)

Typ boolean

§Ein Vergleich ("test") ist ein boolescher Ausdruck (ein Ausdruck der ein boolean Ergebnis hat).

§ Ergebnis kann in einer Variable des Typs boolean gespeichert werden

§Boolesche Variable können mit den booleschen Operatoren kombiniert werden.

(9)

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 von x, y …. 11

(10)

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!");

}

(11)

Hinweise

§ Manchmal sieht man solchen Code (test ob eine Variable den Wert true hat):

if (isPrime == true) { // schlecht ...

}

§ Das ist nicht nötig und redundant. Besser :

if (isPrime) { // gut ...

}

(12)

Hinweise

§ Auch nicht besser ist der Test für false:

if (isPrime == false) { // schlecht

if (!isPrime) { // gut

(13)

Bedingte ("short-circuit") Auswertung

§ Für && und || müssen nicht immer beide Operanden ausgewertet werden, um das Ergebnis zu ermitteln

§ Java beendet die Auswertung eines booleschen Ausdrucks sobald das Ergebnis fest steht.

§ Ausdrücke werden von links nach rechts, gemäss Präzedenz ausgewertet

§ && stoppt sobald ein Teil(ausdruck) false ist

§ || stoppt sobald ein Teil(ausdruck) true ist

(14)

Bedingte ("short-circuit") Auswertung

§ Java beendet die Auswertung eines booleschen Ausdrucks sobald das Ergebnis fest steht.

§ Ausdrücke werden von links nach rechts, gemäss Präzedenz ausgewertet

§ && stoppt sobald ein Teil(ausdruck) false ist

§ || stoppt sobald ein Teil(ausdruck) true ist

§ Diese Art der Auswertung heisst bedingte Auswertung

§ Folgende Teilausdrücke werden abhängig von zuerst ausgewerteten Ausdrücken (nicht) evaluiert

(15)

Auswertung des Tests

§ Wir wollen nur Quotienten (für a,b) grösser als 0 drucken:

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);

...

(16)

Auswertung des Tests

§ Viele "if" Statements machen den Code unlesbar

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);

};

} ...

(17)

Auswertung des Tests

§ Wir wollen nur Quotienten (für a,b) grösser als 0 drucken:

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);

}

...

(18)

Reihenfolge ist wichtig

§ Dieser Code fü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);

};

}

...

(19)

Bedingte ("short-circuit") Auswertung

§ Dieser Code fü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);

};

}

...

(20)

38

(21)

40

(22)

De Morgan's Regeln

De Morgan's Regeln: Regeln für die Negation boolescher Ausdrücke.

§ Praktisch wenn man das Gegenteil eines Ausdrucks braucht.

§ Beispiel:

Ursprünglicher Ausdruck Negierter Ausdruck Alternative

a && b !a || !b !(a && b) a || b !a && !b !(a || b)

Original Negiert

if (x == 7 && y > 3) {

...

}

if (x != 7 || y <= 3) {

...

}

(23)

2.5 Nochmals Schleifen

§ Bisher: Obergrenze für Schleifenzähler stand zu Beginn der Schleife fest

§ Jetzt: mehr Flexibilität

§ Korrekte Terminierung wichtig

43

(24)

Eine triviale Aufgabe ...

§ Schreiben Sie eine Methode printNumbers die die Zahlen von 1 bis N durch Komma getrennt ausgibt.

Beispiel:

Obergrenze N eingeben: 5

sollte ergeben:

1, 2, 3, 4, 5

(25)

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 }

Output bei Eingabe 5: 1, 2, 3, 4, 5,

(26)

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 }

Output bei Eingabe 5: , 1, 2, 3, 4, 5

(27)

Gartenzaun Analogie

§ Wir geben n Zahlen aus aber brauchen nur n - 1 Kommas.

§ Aehnlich dem Bau eines Weidezaunes mit Pfosten und Querstreben

§ Wenn wir - wie in der 1. fehlerhaften Lösung – Pfosten und Streben installieren dann hat der letzte Pfosten in der Luft hängende Streben.

for (Laenge des Zauns) { Betoniere Pfosten.

Installiere Querstreben.

}

(28)

Schleife

§ Fügen Sie eine Anweisung ausserhalb der Schleife hinzu um den ersten "Pfosten" zu plazieren

Betoniere Pfosten.

for (Laenge des Zauns - 1) { Installiere Querstreben.

Betoniere Pfosten.

}

(29)

Lösungen basierend auf dieser 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 die Schleife kann verändert werden:

for (int i = 1; i <= max - 1; i++) { System.out.print(i + ", ");

}

System.out.println(max); // to end the line

(30)

"off-by-one" Error

(Um-Eins-daneben-Fehler)

§ Die Schleife wurde einmal zuviel (oder einmal zuwenig) durchlaufen.

§ "Zaunpfahlproblem" – es gibt sogar eine D Wikipedia Seite (Inhalt ohne Gewähr)

50

(31)

Terminierung von Loops

§ Verwandeln Sie die Methode printNumbers in eine neue Methode printPrimes die alle Primzahlen bis zur

Obergrenze max ausgibt.

§ Beispiel: printPrimes mit Eingabe 50 ergibt:

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 in genau zwei Faktoren zerlegt werden: p und 1

(32)

53

(33)

Beispiellösung

// Prints all prime numbers up to the given max.

public static void main (String[] args) {

Scanner console = new Scanner(System.in);

System.out.print("Input max: ");

int max = console.nextInt();

// Prints all prime numbers up to the given max.

if (max >= 2) {

System.out.print("2");

for (int i = 3; i <= max; i++) {

if (isPrime(i, max)) { // isPrime returns true if i is prime System.out.print(", " + i);

} }

System.out.println();

} }

(34)

56

(35)

while Schleifen

(36)

Klassifizierung von Schleifen

§ bestimmte Schleife (definite loop): Anzahl der Ausführungen des Rumpfes ist vorher bekannt.

§ Die for Schleifen waren bisher immer bestimmte Schleifen.

§ Drucke "hello" 10-mal.

§ Finden Sie alle Primzahlen < einer ganzen Zahl n.

§ Drucken Sie jede ungerade Zahl zwischen 7 und 91.

§ unbestimmte Schleife (indefinite loop): Anzahl der Ausführungen des Rumpfes ist nicht vorher bekannt.

(37)

Klassifizierung von Schleifen

§ unbestimmte Schleife (indefinite loop): Anzahl der Ausführungen des Rumpfes ist nicht vorher bekannt.

§ Lesen Sie den Input von der Konsole bis der Benutzer eine nicht- negative ganze Zahl eingibt.

§ Wiederholen Sie bis der Benutzer ein "q" eingegeben hat.

§ Lesen Sie eine Datei bis drei aufeinanderfolgende Sätze mit einem

"!" enden.

§ Nehmen Sie Beiträge (via crowdfunding) entgegen bis das Ziel erreicht ist.

(38)

Die while Schleife

§ while Schleife: Führen Sie den Schleifenrumpf so lange aus wie der boolesche Ausdruck test den Wert true ergibt.

while (test) { statement(s);

}

§ Beispiel:

int num = 1; // initialization while (num*num <= 2000) { // test

System.out.print(num + " ");

num = num * 2; // update }

// output: 1 2 4 8 16 32

(39)

Die while Schleife

§ while Schleife: Führen Sie den Schleifenrumpf so lange aus wie der boolesche Ausdruck test den Wert true 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

Anweisung(en) im Loop ausfuehren Ist test wahr?

Anweisung nach Loop ausfuehren

ja nein

(40)

62

(41)

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);

}

(42)

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 oft wir den Zähler erhöhen müssen um den 1. Faktor zu finden

(43)

§ Hinweiszeichen (Sentinel) ("sentinel"): Ein Wert der das Ende eine Reihe anzeigt

§ sentinel loop: Schleife deren Rumpf ausgeführt wird bis ein Sentinel gesehen wurde

§ Beispiel: Ein Programm soll Zahlen einlesen bis der Benutzer eine 0 eingibt; dann soll die Summe aller eingegebenen Zahlen ausgegeben werden.

§ (In diesem Beispiel ist 0 das Hinweiszeichen/der Sentinel.)

Werte die Hinweise sind …

(44)

§ Beispiel: Ein Programm soll Zahlen einlesen bis der Benutzer eine 0 eingibt; dann soll die Summe aller eingegebenen Zahlen ausgegeben werden.

§ (In diesem Beispiel ist 0 das Hinweiszeichen/der Sentinel.) Enter a number (0 to quit): 10

Enter a number (0 to quit): 20 Enter a number (0 to quit): 30 Enter a number (0 to quit): 0 The sum is 60

Werte die Hinweise sind …

(45)

Fehlerhafte Lösung

§ Was ist an diesem 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);

(46)

Ein anderes Hinweiszeichen …

§ Aendern Sie das Programm so dass -1 der Sentinel ist.

§ Example log of execution:

Enter a number (-1 to quit): 15 Enter a number (-1 to quit): 25 Enter a number (-1 to quit): 10 Enter a number (-1 to quit): 30 Enter a number (-1 to quit): -1 The total is 80

(47)

Ein anderes Hinweiszeichen …

§ Setzen Sie den Sentinel auf -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 das Result falsch. Warum?

The total was 79

(48)

Das Problem mit diesem Programm

§ Unser Programm folgt diesem Muster:

summe = 0.

while (input ist nicht der sentinel) { drucke prompt; lese input.

addiere input zu summe.

}

§ Beim letzten Durchlauf durch den Rumpf wird der Sentinel -1 zur Summe addiert:

(49)

Das Problem mit diesem Programm

§ Beim letzten Durchlauf durch den Rumpf wird der Sentinel -1 zur Summe addiert:

drucke prompt; lese input (-1).

addiere input (-1) zu summe.

§ Beispiel inkorrekter Terminierung (off-by-one error, Zaunpfahlproblem):

§ Müssen N Zahlen lesen aber nur die ersten N-1 addieren.

(50)

Lösung

summe = 0.

drucke prompt; lese input. // setzen eines pfostens

while (input ist nicht der sentinel) {

addiere input zu summe. // installation querstrebe drucke prompt; lese input. // setzen eines pfostens }

§ Schleifen mit einem Sentinel folgen oft diesem Muster.

(51)

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);

(52)

do/while Schleife

§ do/while Schleife: Führt den test am Ende des Schleifenrumpfes aus um zu entscheiden, ob ein weiterer Durchlauf nötig ist

§ Stellt sicher dass der Rumpf { … } mindestens einmal ausgeführt wird.

do {

statement(s);

} while (test);

Anweisung(en) im Loop ausfuehren

Ist test wahr?

Anweisung nach Loop ausfuehren

ja

nein

(53)

do/while Schleife

Nochmal Beispiel

// Add numbers till -1 is entered

Scanner console = new Scanner(System.in);

int sum = 0;

// first round nothing to add int number = 0;

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);

Anweisung(en) im Loop ausfuehren

Ist test wahr?

Anweisung nach Loop ausfuehren

ja

nein

Referenzen

ÄHNLICHE DOKUMENTE

Um Eclipse einfacher zu starten, können Sie eine Verknüpfung erstellen.. Gehen Sie mit Ihrem Datei-Explorer in den Ordner, wo Sie Eclipse

§ Programm: Folge von Anweisungen, die von einem Computer ausgeführt werden (können).. § Programm realisiert

§ Schiedsrichter entscheidet ob das Symbol legal ist oder nicht (für diese EBNF Beschreibung)2. § Symbol legal gemäss einer Regel: alle Buchstaben des Symbols stimmen mit den

Windows: Rechtsklicken Sie auf die Datei eclipse.exe und wählen Sie Senden an → Desktop (Verknüpfung erstellen).. macOS: Ziehen Sie das Eclipse-Symbol in

§ Sie lernen zu entscheiden ob ein Symbol legal ist (für eine EBNF Beschreibung)?. § Sie können entscheiden ob zwei EBNF Beschreibungen äquivalent

§ Wenn eine Methode einen Parameter erwartet dann muss dieser auch übergeben werden. printPunkte(); // ERROR: parameter value

containsAll( coll ) returns true if this set contains every element from given set equals( set ) returns true if given other set contains the same elements iterator() returns

§ Eine Aussage gilt für den Zustand eines Programms wenn die Auswertung der Aussage mit dem Zustand das Ergebnis true ergibt. § Die Auswertung jedes Variable ergibt den Wert