Verzweigung oder bedingte Anweisung. Aufgabe: Ein Autofahrer tankt sein Auto voll und schreibt den...

Preview:

Citation preview

Verzweigung oder

bedingte Anweisung

Aufgabe:Ein Autofahrer tankt sein Auto voll und schreibt den Kilometerstand auf (drei-stelliger Tageszähler).Wenn er das nächste Mal tankt, macht er das gleiche und notiert sich zusätzlich noch die getankten Liter.Wie groß ist der Benzinverbrauch pro 100 km ?Flussdiagramm + C-Programm !

d = zneu – zalt

Ausgabe (bv100)

Eingabe(zalt)

Eingabe(zneu)

Eingabe(bv)

bv100 = bv / d * 100

int main(){ double zalt, zneu, d, bv, bv100; printf("\nKilometerstand "); scanf("%lf", &zalt); fflush(stdin); printf("\nKilometerstand "); scanf("%lf", &zneu); fflush(stdin); printf("\nBenzinverbrauch \n"); scanf("%lf", &bv); fflush(stdin);

... d = zneu - zalt; bv100 = bv/d * 100; printf("L/100 km %f",bv100); return 0;}

Differenz kann negativ werden

Wann berechnet das C-Programm ein falsches Ergebnis ?

Zählerstand beim 1. Tankvorgang: 900 km

Beispiel für negative Differenz

Zählerstand beim 2. Tankvorgang: 100 km

Differenz = 100 – 900 = - 800km

Es werden nun 200 km bis zum nächsten Tankvorgang gefahren.Welcher Kilometerstand steht dann auf dem Tacho?

Welcher neue Kilometerstand müsste in Wirklichkeit aber auf dem Tacho stehen?

1000 km + 100 km

Welche Differenz berechnet das Programm?

Aufgabe:Verändern Sie das Flussdiagramm so, dass dieser Fall (Zählerüberlauf) berücksichtigt wird.

d = zneu – zalt

Ausgabe (bv100)

Eingabe(zalt)

Eingabe(zneu)

Eingabe(bv)

bv100 = bv / d * 100

zneu zaltf

w

Eingabe(zalt)

Eingabe(zneu)

Eingabe(bv)

zneu = zneu + 1000

zneu zaltf

w

Eingabe(zalt)

Eingabe(zneu)

Eingabe(bv)

zneu = zneu + 1000

d = zneu – zalt

Ausgabe(bv100)

bv100 = bv / d * 100

C-Syntax für die Einseitige

Verzweigung

if (Ausdruck) Anweisung;

Bedingung Nächste auszuführende Anweisung, wenn Bedingung wahr.

Wahr bedeutet:

Wert des Ausdrucks: !=0

Nächste auszuführende (d.h. die diesem roten Rahmen folgende) Anweisung,

wenn Bedingung falsch.Falsch bedeutet:

Wert des Ausdrucks: 0

Aufgabe:Verändern Sie das C-Programm so, dass dieser Fall (Tachoüberlauf) berücksichtigt wird.

... if(zneu <= zalt){ zneu = zneu + 1000; } d = zneu - zalt; bv100 = bv/d * 100; printf("L/100km %f",bv100); return 0;}

bei einer Anweisung sind Klammern nicht nötig.

Trotzdem:Immer Klammern machen.

Struktogrammeals Alternative zu Flussdiagrammen

Eingaben, Ausgaben, einfache

Anweisungen.Beispiele:

Fläche = Länge * Breite

Umfang = 2*(Länge + Breite)

Flussdiagramm für eine

Einseitige Verzweigung

zneu <= zaltf

w

zneu = zneu + 1000

Struktogramm für eine Einseitige Verzweigung

zneu <= zalt

w

zneu = zneu + 1000

f

Bei einer zweiseitigen Verzweigung würde hier mindestens eine Anweisung stehen!

Beispiel:

//Eingabeteil (wurde weg-// gelassen)

if (zneu <= zalt) zneu = zneu+1000; printf("Zählerüberlauf");

}d = zneu–zalt;erg = b/d*100;printf("\n L/100 km %f",erg);

Block (Verbundanweisung): fasst mehrere Anweisungen zusammen

{

Übrigens: Welchem Prinzip widerspricht dieses Programm ?

Dem EVA-Prinzip !

Eingabe(bv)

Eingabe(zneu)

Eingabe(zalt)

Bitte Struktogramm zum vorigen C-

Programm vervollständigen !

d = zneu–zalt

Ausgabe(bv100)

bv100 = bv/d*100

zneu <= zaltw f

Eingabe(bv)

Eingabe(zneu)

Eingabe(zalt)

zneu = zneu+1000

Ausgabe("Zählerüberlauf")

Aufgabe:Bestimmung des Maximums zweier ganzer Zahlen, also:

Struktogramm + Flussdiagramm +C-Programm !

Achtung: Bis jetzt können wir nur die einseitige Verzweigung in C umsetzen !!!

max = b

Ausgabe(max)

a < bw f

Eingabe(b)

Eingabe(a)

max = a

a >= bw f

Ist es möglich, dass das Programm alle zwei false-Teile durchläuft?

max = b

Ausgabe(max)

a < bw f

Eingabe(b)

Eingabe(a)

max = a

a >= bw f

Nein, denn wenn eine Bedingung false ist, muss die andere Bedingung true sein!

a < bf

w

Eingabe(a)

Eingabe(b)

max = b

Ausgabe(max)

a >= bf

w

max = a

#include "stdafx.h" #include <stdio.h>int main(){ int a,b,max;  printf("\nEingabe der ersten Zahl: "); scanf("%d", &a); fflush(stdin);  printf("\nEingabe der zweiten Zahl: "); scanf("%d", &b); fflush(stdin); // Wie geht es weiter ?

Möglich: Trennen von Variablennamen mit Komma

Kommentar

if (a<b){  max = b;}

printf("Max=%d", max);

if (a>=b){  max = a;}

Logisch gleichwertig:!(a<b)

return 0;}

Wir machen ein paar Tests, denn die Wahrheit ist konkret

!

if (a<b){  max = b;}

printf("Max=%d", max);

if (a>=b){  max = a;}

12 Für a werde 2 eingegeben

Für b werde 1 eingegeben

2 1

2

2

if (a<b){  max = b;}

printf("Max=%d", max);

if (a>=b){  max = a;}

53 Für a werde 3 eingegeben

Für b werde 5 eingegeben

3 5

5

5

if (a<b){  max = b;}

printf("Max=%d", max);

if (a>=b){  max = a;}

77 Für a werde 7 eingegeben

Für b werde 7 eingegeben

7 7

7

7

Andere Lösung mit einseitiger

Verzweigung:

max = b

Ausgabe(max)

a < bw f

Eingabe(b)

Eingabe(a)

max = a

a > bw f

max = a

a == bw f

Andere Lösung mit einseitiger

Verzweigung:

max = b

Ausgabe(max)

a < bw f

Eingabe(b)

Eingabe(a)

max = a;

Das vorläufige Maximum wird auf den Wert der Variablen a gesetzt.

Ist das vorläufige Maximum kleiner als die 2. Zahl, dann ist das endgültige Maximum gleich der 2. Zahl

oder als eine elegantere Alternative:

Aufgabe:

Bestimmen des Maximums zweier ganzer Zahlen.

Flussdiagramm mit zweiseitiger Verzweigung !

a < bf

w

Eingabe(a)

Eingabe(b)

max = b

Ausgabe(max)

max = a

Ende

Anfang

Und hier das zugehörige

Struktogramm für diese zweiseitige

Verzweigung

a<bw

max = b

f

max = a

C - Syntax für die zweiseitige

Verzweigung

if (Ausdruck) Anweisung1;else Anweisung2;

Nächste Anweisung, wenn Bedingung wahr

Bedingung

Nächste Anweisung, wenn Bedingung falsch

wahr bedeutet:Wert des Ausdrucks != 0

falsch bedeutet:Wert des Ausdrucks = 0

Wie kann man also ganz allgemein die folgende

zweiseitige Verzweigung durch zwei einseitige

Verzweigungen darstellen ?

if (B){  A1;}else{ A2;}

if(B){  A1;}if(!B){ A2;}

A1, A2 und B sind alles Ausdrücke

Aufgabe:

Bestimmung des Maximums zweier ganzer

Zahlen.C-Programm

if (a<b){  max = b;}else{ max = a;}

printf("Maximum =%d", max);

Bedingung

Nächste Anweisung, wenn Bedingung wahr

Nächste Anweisung, wenn Bedingung falsch

bei einer Anweisung sind Klammern nicht nötig.

Trotzdem:Immer Klammern machen.

return 0;}

Programmverlauf

Annahme:

Bedingung wahr

if (a<b){  max = b;}else{ max = a;}

printf("Maximum =%d", max);

1 22

2

Zum Beispiel ...

Annahme:

Bedingung falsch

if (a<b){  max = b;}else{ max = a;}

printf("Maximum =%d", max);

2 1

2

2

Zum Beispiel ...

Warum ist folgende Lösung falsch ?

Frage:

if (a<b){  max = b;}printf("Maximum =%d", max);

}

Programmverlauf

Annahme:

Bedingung wahr

if (a<b){  max = b;}printf("Maximum = %d ", max);

1 2

Zum Beispiel ...2

2

Annahme:

Bedingung falsch

if (a<b){  max = b;}

Wert von max ist unbekannt und deshalb mit hoher Wahrscheinlichkeit nicht gleich dem Wert von a

printf("Maximum = %d ", max);

2 1Zum Beispiel ...

?

Aufgabe:

Bestimmen des Maximums und Minimums zweier

ganzer Zahlen.Struktogramm +

C-Programm

a<bw

max = b

f

max = a

min = a min = b

Eingabe(a,b)

Ausgabe (max,min)

#include "stdafx.h" #include <stdio.h>

int main(){ int a; int b; int min; int max; // Eingabeteil wie immer // Dann weiter mit ...

if (a<b){ max = b; min = a; }else{ max = a; min = b;}

Anweisungen in einem Block zusammenfassen

Blockbeginn

Blockende

kein Semikolon

printf("Max=%d, Min=%d", max, min); return 0;}

Block: Fasst mehrere Anweisungen zusammen.

Vorschlag: In "nicht

einfachen" Anweisungen (wie z.B. if...else, bzw. if) immer Block

benutzen.

WICHTIG: Nach einem Block

kommt keinSemikolon.

Stellen Sie den Algorithmus durch ein Struktogramm dar, der das Maximum dreier in beliebiger Reihenfolge eingegebener Zahlen berechnet.

Aufgabe:

Eingabe(z1,z2,z3)

z1<z2W F

max = z2 max = z1

max<z3W F

max = z3

Ausgabe(max)

Erstellen Sie das zu diesem Struktogramm zugehörige

C-Programm

#include "stdafx.h" #include <stdio.h>

int main(){ int z1; int z2; int z3; int max; // Eingabeteil wie immer // Dann weiter mit ...

if(z1<z2){ max=z2; } else{ max=z1; } if(max<z3){ max=z3; } printf("Max=%d\n", max); return 0;

}

Stellen Sie den Algorithmus durch ein Struktogramm dar, der das Maximum und Minimum dreier in beliebiger Reihenfolge eingegebener Zahlen berechnet.

Aufgabe:

Eingabe(z1,z2,z3)

z1<z2W Fmax = z2

Ausgabe(max, min)

min = z1max = z1min = z2

max<z3W F

max = z3

min>z3W F

min= z3

Erstellen Sie das zu diesem Struktogramm zugehörige

C-Programm

#include "stdafx.h" #include <stdio.h>

int main(){ int z1; int z2; int z3; int max; int min; // Eingabeteil wie immer // Dann weiter mit ...

if(z1<z2){ max=z2; min=z1; } else{ max=z1; min=z2; } if(max<z3){ max=z3; } if(min>z3){ min=z3; } printf("Max=%d Min=%d\n", max, min); return 0;}

Erzeugen Sie einen Algorithmus (und stellen Sie diesen durch ein Struktogramm dar), der drei in beliebiger Reihenfolge eingegebene Zahlen ihrer Größe nach sortiert und ausgibt (kleinste, mittlere, grösste).

Aufgabe:

TESTEN Sie Ihre Lösung (Struktogramm).Machen Sie dazu folgende Überlegungen:

Unter 3 Zahlen gibt es genau 3 verschiedene, genannt a, b und c.Wie viele verschiedene Möglichkeiten (bzgl. der Reihenfolge der Eingabe) gibt es diese 3 Zahlen einzugeben? Bitte notieren Sie diese Möglichkeiten.

3 verschiedene Zahlen:a b ca c bb a cb c ac a bc b a

Unter 3 Zahlen gibt es genau 2 verschiedene, genannt a und b.Wie viele verschiedene Möglichkeiten (bzgl. der Reihenfolge der Eingabe) gibt es diese 3 Zahlen einzugeben? Bitte notieren Sie diese Möglichkeiten.

Genau 2 gleiche Zahlen:a a bb a aa b a b b aa b bb a b

Unter 3 Zahlen gibt es genau 3 gleiche, genannt a, a, und a.Wie viele verschiedene Möglichkeiten (bzgl. der Reihenfolge der Eingabe) gibt es diese 3 Zahlen einzugeben? Bitte notieren Sie diese Möglichkeiten.

Genau 3 gleiche Zahlen:a a a

Zusammengefasst:

a b ca c bb a cb c ac a bc b a

a a bb a aa b a b b aa b bb a b

a a a

Eine mögliche Lösung der vorigen Aufgabe:

Bemerkung:Die Lösung wird in der folgenden Folie durch ein Flußdiagramm dargestellt. Wandeln Sie dieses Flussdiagramm in ein Struktogramm um.

w

k:=z3m:=z1g:=z2

z1 < z2 f

z3 < z1

z3 < z2

k:=z1m:=z3g:=z2

k:=z1m:=z2g:=z3

k:=z3m:=z2g:=z1

z3 < z2

z3 < z1

k:=z2m:=z3g:=z1

k:=z2m:=z1g:=z3

Ausgabe(k,m,g)

w

w

w

w

f f

ff

z1<z2W F

z3<z1W F

k=z3m=z1g=z2

z3<z2W Fk=z1m=z3g=z2

k=z1m=z2g=z3

z3<z2W F

k=z3m=z2g=z1

z3<z1W Fk=z2m=z3g=z1

k=z2m=z1g=z3

Eingabe(z1, z2, z3)

Ausgabe(k, m, g)

z1<z2W F

z3<z1W F

k=z3m=z1g=z2

z3<z2W Fk=z1m=z3g=z2

k=z1m=z2g=z3

z3<z2W F

k=z3m=z2g=z1

z3<z1W Fk=z2m=z3g=z1

k=z2m=z1g=z3

Eingabe(z1, z2, z3)

Ausgabe(k, m, g)

Wieviel if...else Anweisungen kommen in diesem Programm vor?

Genau eine (die rot umrandete)! Diese ist allerdings verschachtelt !!!

TESTEN Sie mit den gerade angegebenen Zahlenkombinationen dieses Struktogramm.

Erstellen Sie das zu diesem Struktogramm zugehörige

C-Programm

#include "stdafx.h"#include "stdio.h"int main(){ int z1, z2, z3, m, k, g;

// Eingabe printf("Eingabe der 1. Zahl: \n"); scanf("%d", &z1); fflush(stdin); printf("Eingabe der 2. Zahl: \n"); scanf("%d", &z2); fflush(stdin); printf("Eingabe der 3. Zahl: \n"); scanf("%d", &z3); fflush(stdin); // gleich kommt die Ausgabe

if (z1<z2){ if(z3<z1){ k=z3; m=z1; g=z2; } else{ if(z3<z2){ k=z1; m=z3; g=z2; } else{ k=z1; m=z2; g=z3; } } } else{ if(z3<z2){ k=z3; m=z2; g=z1; } else{ if(z3<z1){ k=z2; m=z3; g=z1; } else{ k=z2; m=z1; g=z3; } } }

// Ausgabe printf("sortierte Reihenfolge %d %d %d: \n", k, m, g); return 0;}

Nochmals zum EVA-Prinzip

Das EVA-Prinzip bedeutet:In einer Anweisung dürfen

nicht zwei verschiedene Komponenten von EVA stehen

(wie z.B. V und A)

Eingabe(zaehler , nenner)

nenner != 0W F

erg = zaehler / nenner

Ausgabe(erg)

Ausgabe("unerlaubte Division durch 0")

E

V

A+

Schlechter Programmierstil:

2 Komponenten in 1 Anweisung

Guter Programmierstil:

Eingabe(zaehler , nenner)

nenner != 0W F

erg = zaehler / nenner

erlaubt = 1

erlaubt = 0

E

V

erlaubt == 1W F

Ausgabe(erg)A

Ausgabe("Division durch 0")

Eingabe(zaehler , nenner)

W F

erg = zaehler / nenner

erlaubt = 1

erlaubt = 0

E

V

erlaubt == 1W F

Ausgabe(erg)A

Ausgabe("Division durch 0")

Wieviel if...else Anweisungen kommen in diesem Programm vor?

Genau 2!

nenner != 0

Aufgabe:Die Variablen n und t sollen den Datentyp integer haben.

Mit welcher Anweisung kann man nachprüfen, ob t ein Teiler von n ist, wie z.B. 3 ein Teiler

von 18 ist.

... if(n % t == 0){ // t teilt n } else{ // t teilt n nicht } ...

Mit dem Operator % wird der Rest berechnet. Wenn t Teiler von n ist, ist

der Rest gleich 0.

Gibt es eine andere Lösung, die die Operatoren / und * benutzt?

... if(n/t * t == n){ // t teilt n} else{ // t teilt n nicht } ...

Wenn n von t nicht geteilt wird, wird der Rest bei der Division abgeschnitten und

somit das Produkt n/t * t ungleich n

Geben Sie dazu ein paar Beispiele ...

... if(n/t * t == n){ // t teilt n} else{ // ... } ...

Also ist die nächste Anweisung im if-Teil der if ... else Anweisung.

21 7 7 21

3 * 7 21=

... if(n/t * t == n){ // ...} else{ // t teilt n nicht } ...

Also ist die nächste Anweisung im else-Teil der if ... else Anweisung.

20 7 7 20

2 * 7 20≠

Recommended