C++ - Kontrollstrukturen – Teil 1 - fbi.h

Werbung
FB Informatik
Prof. Dr. R.Nitsch
C++ - Kontrollstrukturen – Teil 1
Reiner Nitsch
℡ 8417
[email protected]
Programmablaufsteuerung
FB Informatik
Prof. Dr. R.Nitsch
• Kontrollstrukturen geben an
– in welcher Reihenfolge (Sequenz)
– ob (Auswahl) und
– wie oft (Wiederholung)
Anweisungen ausgeführt werden, bzw.
– ob andere Programme aufgerufen
werden (Aufruf)
• Lineare Kontrollstrukturen
– sind Kontrollstrukturen, die nur
Sequenz, Wiederholung, Auswahl und
Aufruf verwenden, aber keine
Sprünge
• Strukturierte Programmierung
– implementiert einen Algorithmus
durch ausschließliche Verwendung
einfacher Anweisungen und linearer
Kontrollstrukturen
Anweisungen
Anweisungen
einfache
einfache
Anweisungen
Anweisungen
lineare
Kontrollstrukturen
Kontrollstrukturen
Sequenz
Sequenz
Aufruf
Aufruf
Auswahl
Auswahl
Wiederholung
Wiederholung
Zur Erklärung wird eine Beschreibung auf
höherer Sprachebene gewählt
Struktogramm
Struktogramm (DIN
(DIN 66261)
66261)
Nassi-Shneiderman on the Web
14.05.2008
Kontrollstrukturen - Teil 1
2
Kontrollstrukturen und ihre Struktogramme (DIN 66261)
FB Informatik
Prof. Dr. R.Nitsch
• Struktogramme ermöglichen die visuelle Darstellung von Kontrollstrukturen
• Die Grundbausteine von Struktogrammen sind die in den folgenden Abschnitten
gezeigten Strukturblöcke. Sie werden jeweils durch ein Rechteck graphisch dargestellt
und können durch Schachtelung und Aufeinanderstapeln kombiniert werden.
• Der Programmablauf wird stets von oben nach unten gelesen
Verarbeitung
Anweisung(en)
Block
Bezeichner
Anweisung(en)
Sequenz, Folge
Anweisung(en) 1
Anweisung(en) 2
…
14.05.2008
Die Verarbeitung ist der einfachste Strukturblock.
Er enthält eine oder mehrere Anweisungen
in Text- oder Pseudocode-Form.
Ein Block (Verbundanweisung) stellt eine Hilfskonstruktion dar, mit der Strukturblöcke zusammengefasst
werden können, um ihnen einen gemeinsamen
Namen (Bezeichner) zu geben. Man kann einen Block
als Funktion im Sinne von C++ auffassen.
Der Strukturblock "Sequenz" bzw. "Folge" symbolisiert
die Hintereinanderausführung der in ihr auftretenden
Strukturblöcke.
Eine Sequenz ist selbst eine Verarbeitung
Kontrollstrukturen - Teil 1
Counter erzeugen
Null setzen
um 1 erhöhen
C ausgeben
void Ausgabe()
{ Anweisung(en); }
Lies Zahl ein
Zahl = Zahl2
Gib Zahl aus
3
Abweisende Schleife – while
FB Informatik
Prof. Dr. R.Nitsch
Schleife mit vorausgehender Bedingungsprüfung (pretested loop, abweisende Schleife)
Mit B wird eine Bedingung (logischer Ausdruck)
bezeichnet, S ist ein Strukturblock.
B
S
Die Abarbeitung beginnt mit einem Test der
Bedingung. Ergibt dieser Test false, so wird
der nächste Strukturblock verarbeitet. Liefert
der Test true, so wird der Strukturblock S
ausgeführt. Danach wird der vorliegende
Strukturblock erneut ausgeführt (Das heißt, B
wird getestet, . . .).
C++ Syntax
while (B) {
//Anweisungen aus S
}
Beispiel
while(true) { /*Anweisung(en)*/ } // unendliche Schleife
while(false){ /*Anweisung(en)*/ } //Anweisungen werden nie ausgeführt
Schleifenvariable nötig!
14.05.2008
Kontrollstrukturen - Teil 1
4
Abweisende Schleife – while
FB Informatik
Prof. Dr. R.Nitsch
Beispiel
Schleifenvariable SV
initialisieren
solange Ausdruck unter
Berücksichtigung von SV
true ( ≠ 0) ist
"Nutzleistung"
Veränderung der SV
Richtung Ziel
Regeln
1. Zuerst die Zusicherungen.
Daraus ergeben sich die
notwendigen lokalen Variablen!
2. Algorithmus schreiben und
Prüfbedingung festlegen.
3. Prüfen des Algorithmus mit
Extremwerten:
value = 1;
value > 1;
class Counter { …
int value;
void countdown();
public:
Counter(int val);
… };
Counter::Counter(int val) { value=val; }
void Counter::countdown() {
assert(
);
Vorbedingung?
while (value
)
Was hier steht, kann erst
{
nach Definition des Veränderungscout << value << endl; schritts festgelegt werden
--value;
Nutzleistung
}
Veränderungsschritt
cout << 0 << endl;
assert(
);
Nachbedingung?
}
Schleife für Grenzfälle prüfen: value = 1 ?
14.05.2008
Kontrollstrukturen - Teil 1
5
Abweisende Schleife – while - Wait a moment
FB Informatik
Prof. Dr. R.Nitsch
1. Version
long stop (10000);
while (--stop);
2. Version: Funktion void wait( double seconds )
Nachteil: Wartezeit von Taktfrequenz des Prozessors abhängig!
Abhilfe: Bibliotheksfunktion clock() Headerdateien time.h bzw. ctime enthalten Deklaration.
clock() gibt Zeitdauer seit Programmstart zurück
Ergebnistyp: clock_t als Aliasname für den tatsächlichen (plattformabhängigen) Ergebnistyp
(z.B. long, unsigned long,…)
Syntax zur Definition von Aliasnamen:
#define clock_t long
//Preprozessor ersetzt clock_t durch long im Sourcecode
oder besser
//wird häufig in Bibliotheken verwendet.
typedef long clock_t;
#include <ctime>
Typ
Aliasname
void wait(double seconds) {
für Typ
assert ( seconds >= 0 );
clock_t end = clock() + CLOCKS_PER_SEC * seconds;
while ( clock() < end )
;
}
14.05.2008
Kontrollstrukturen - Teil 1
7
Abweisende Schleife – while - Noch ein Beispiel
Summe beliebig vieler Zahlen
ersten Wert eingeben
Ende der Eingabe ?
Wert verarbeiten
Nächsten Wert eingeben
FB Informatik
Prof. Dr. R.Nitsch
• Frage: Wie entscheidet das Programm,
dass alle Zahlen eingegeben sind?
• Lösung: Man kann einen speziellen Wert
benutzen, um "end of data" zu
signalisieren. Ein solcher Wert wird
sentinel (dt: Wächter) genannt.
int Counter::accumulate() {
int nextVal;
Schleifenvariable
value = 0;
Rückgabewert initialisieren
cin >> nextVal;
sentinel = alle negativen Zahlen
while( nextVal >= 0 ) {
value += nextVal;
cin >> nextVal;
Schleifenvariable Richtung Ziel verändern
}
return value;
}
14.05.2008
Kontrollstrukturen - Teil 1
9
HS-Übung 2: abweisende Schleife mit while
FB Informatik
Prof. Dr. R.Nitsch
Finden und korrigieren Sie die Fehler in den nachfolgenden Programmsegmenten
a) While ( c <= 5) {
product +=c;
++c;
b) while (z >= 0)
sum += z;
c) x=1;
while (x <= 10);
x++;
e) Die Zahlen 1..100 sollen
addiert werden!
f)
n = 1;
while ( n < 10 )
cout << n++ << endl;
int x=1, total=0;
while (x<=100)
total +=x;
x++;
while ( y > 0 ) {
cout << y << endl;
++y;
}
14.05.2008
Kontrollstrukturen - Teil 1
d) Der nachfolgende Programmcode
soll die Werte 1…10 ausgeben!
10
HS-Übung 3: abweisende Schleife mit while
FB Informatik
Prof. Dr. R.Nitsch
Bestimmen Sie die Ausgabe der folgenden Programme :
void main( ) {
int x = 1, total = 0, y;
while ( x <= 5 )
{
y = x * x;
cout << y << " ";
total += y;
++x;
}
cout << total;
}
14.05.2008
void main( ) {
int Zeile = 10, Spalte;
while ( Zeile >= 1) {
Spalte = 1;
while ( Spalte <= 10 ) {
cout << (Zeile % 2 ? "<" : ">");
++Spalte;
} // while ( Spalte <= 10 )
--Zeile;
cout << endl;
} // while ( Zeile >= 1)
} // main
Kontrollstrukturen - Teil 1
11
HS-Übung 4: abweisende Schleife mit while
•
•
•
FB Informatik
Prof. Dr. R.Nitsch
Schreiben Sie eine Funktion ggt die den größten gemeinsamen Teiler zweier
Parametern vom Typ int bestimmt und zurück gibt.
Testen Sie die Funktion mit einer Anwendung, die solange 2 Zahlen von der
Tastatur einliest und den ggt ausgibt, bis eine der beiden Eingabezahlen 0 ist.
Hinweis: Um 2 Bedingungen gleichzeitig zu testen, können Sie den logischen && Operator verwenden. Bsp: while ( payIn > 0 && payIn < 100 )
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 nein, ggT um eins vermindern
• Falls ja, Schleife verlassen und mit nächster
Anweisung fortfahren
14.05.2008
Kontrollstrukturen - Teil 1
⇒ Hausaufgabe
12
Annehmende Schleife – do while
FB Informatik
Prof. Dr. R.Nitsch
Schleife mit nachfolgender Bedingungsprüfung: annehmende Schleife
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.
B
C++ Syntax:
do {
//Anweisungen aus S
} while (B);
Unterschied zur annehmenden Schleife: S wird mindestens einmal ausgeführt!
Nur anwenden in begründeten Ausnahmefällen, z.B. wiederholte Benutzereingabe
Beispiel 1
Vom Benutzer eingegebene positive Zahlen
sollen aufsummiert werden.
int Counter::accumulate() {
int nextVal;
Schleifenvariable
value = 0;
Rückgabewert initialisieren
do {
cin >> nextVal;
Schleifenvariable Richtung Ziel verändern
value += nextVal;
Implementierung mit abweisender
"Nutzleistung"
} while ( nextVal >=0 );
oder annehmender Schleife besser?
return value;
sentinel: nextVal<0
}
Achtung: Sentinelwert wird auch addiert! Was nun?
14.05.2008
Kontrollstrukturen - Teil 1
13
Annehmende Schleife – do while
Beispiel 2
void Counter::countdown() {
assert( value > 0 );
do {
cout << value << endl;
--value;
} while (value
);
cout << 0 << endl;
assert (value == 0 );
}
FB Informatik
Prof. Dr. R.Nitsch
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:
ok
wert = 1
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 '}'
14.05.2008
char c = ' ';
Diese Schleife while ( c != '*' ){
char c;
endet nie!
cin >> c; cout << c;
Kontrollstrukturen - Teil 1 }
14
Schleife mit fester Wiederholungsanzahl - for
FB Informatik
Prof. Dr. R.Nitsch
Eigentlich überflüssig, aber von Programmierern gern benutzt
SV initialisieren
Solange Bedingung B
wahr (≠0) ist
S
C++ Syntax
ist äquivalent zu
for ( SVinit; B; SVincrement)
S;
SV verändern
Richtung Ziel
S
Beispiel: Quadratzahltabelle
for ( int i = 1; i <= 3; i++ )
1
2
4
cout << i << i*i << endl;
3
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
14.05.2008
SVinit
while (B) {
S
SVincrement
}
Kontrollstrukturen - Teil 1
Ausgabe
1
2
3
1
4
9
15
Einfache Beispiele für for - Anweisung
FB Informatik
Prof. Dr. R.Nitsch
a ) Dekrementieren der SV in Schritten von 1
for ( int i = 5 ; i >= 1 ; i-- ) {
cout << i << ' '; }
Ausgabe:
5 4 3 2 1
Ausgabe:
7 14 21 28 35
Ausgabe:
10 8 6 4 2
b ) Inkrementieren der SV in Schritten > 1
for ( int i = 7 ; i <= 35 ; i +=7 ) {
cout << i << ' '; }
c ) Dekrementieren der SV in Schritten > 1
for ( int i = 10 ; i >= 2 ; i -=2 ) {
cout << i << ' '; }
14.05.2008
Kontrollstrukturen - Teil 1
16
Schleife mit fester Wiederholungsanzahl - for
Beispiel: countdown
void Counter::countdown()
{
assert ( value > 0 );
for ( ; value
; --value )
cout << value << endl;
FB Informatik
Prof. Dr. R.Nitsch
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
und ggf. Prüfbedingung/Algorithmus
korrigieren :
value = 1
value > 1 ; z.B value = 2
assert (value == 0 );
}
Jeder der 3 Ausdrücke in for-Anweisung kann weggelassen werden:
Beispiel
14.05.2008
for ( ; ; )
cout << "Wird nie fertig"
besser
Kontrollstrukturen - Teil 1
for ( ; true ; ) S
17
Schleife mit fester Wiederholungsanzahl - for
Beispiel: GGT zweier Ganzzahlen mit for
FB Informatik
Prof. Dr. R.Nitsch
⇒ 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
14.05.2008
Kontrollstrukturen - Teil 1
18
Der Komma-Operator
•
•
•
•
•
FB Informatik
Prof. Dr. R.Nitsch
meist in for-Anweisung verwendet
erlaubt dort mehrere Ausdrücke, wo syntaktisch nur ein 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?
14.05.2008
Kontrollstrukturen - Teil 1
19
Verzweigungen (Alternativen): Bedingte Verarbeitung (if)
B
wahr
FB Informatik
Prof. Dr. R.Nitsch
• Bedingung B entscheidet, ob der Strukturblock S ausgeführt wird
falsch
S
C++ Syntax
if ( B ) {
// Anweisungen aus S
}
• Bedingung ist wahr
(oder hat Wert != 0)
Strukturblock S
wird ausgeführt
• Bedingung ist falsch
(oder hat Wert 0)
Strukturblock S
wird übersprungen
• Ein Strukturblock kann eine einzelne Anweisung sein oder mehrere
Anweisungen, die mit {} zu einem Strukturblock zusammengefasst
werden.
Beispiel
if ( zahl
cout <<
if ( zahl
cout <<
14.05.2008
% 2 == 1 )
"ungerade Zahl";
% 2 == 0 )
"gerade Zahl"
oder
if (zahl % 2)
cout << "ungerade Zahl";
if ( zahl % 2 - 1)
cout << "gerade Zahl"
Kontrollstrukturen - Teil 1
20
Verzweigung: Einfache Alternative (if…else)
B
wahr
S1
falsch
S2
FB Informatik
Prof. Dr. R.Nitsch
C++ Syntax
if (
//
}
else
//
}
B ) {
Anweisungen aus S1
{
Anweisungen aus S2
Beispiel
if ( zahl%2 == 1 )
cout << "ungerade Zahl";
else
cout << "gerade Zahl";
14.05.2008
Kontrollstrukturen - Teil 1
21
Verzweigung: Verschachtelte if…else Anweisungen
B1
wahr
B2
w
falsch
f
S2
S1
FB Informatik
Prof. Dr. R.Nitsch
if ( zahl>0 )
if ( zahl%2 == 0 )
cout << "Positive und gerade Zahl" ;
else
cout << "Positive und ungerade Zahl" ;
gehört immer zum letzten if !
Andere Zugehörigkeit durch Blockbildung:
if ( zahl>0 )
{
if ( zahl%2 == 0 )
cout << "Positive und gerade Zahl" ;
}
else
cout << "Zahl negativ oder Null" ;
B1
wahr
B2
w
S1
14.05.2008
f
falsch
Struktogramm dazu ?
if (B1)
if (B2)
S1();
else
S2();
else
if (B3)
S3();
else
S4();
syntaktisch ok und
übersichtlich durch
Einrückungen
Struktogramm dazu ?
wahr
B2
w
S2
S1
Kontrollstrukturen - Teil 1
B1
falsch
f w
S2
S3
B3
f
S4
22
Mehrfache Verzweigungen: Mehrfache if…else Anweisungen
B1
w
f
w
B2
f
w
S1
S2
S3
f
S4
Jedes else gehört zum
vorausgehenden if!
14.05.2008
FB Informatik
Prof. Dr. R.Nitsch
zuSchnell = radarMessung();
if ( zuSchnell<=10 )
cout << "Glueck gehabt !!" << endl;
else if ( zuSchnell<=20 )
bussgeld = 50;
else if ( zuSchnell<=30 )
bussgeld = 100;
else
cout << "Lappen her !!" << endl;
zuSchnell = radarMmessung();
if ( zuSchnell<=10 )
cout << "Glueck gehabt !!" << endl;
else
if ( zuSchnell<=20 )
bussgeld = 50;
else
if ( zuSchnell<=30 )
bussgeld = 100;
else
cout << "Lappen her !!" << endl;
Kontrollstrukturen - Teil 1
23
HS-Übung 5: Kontrollstrukturen
FB Informatik
Prof. Dr. R.Nitsch
Finden Sie die Fehler in den nachfolgenden Programmsegmenten und korrigieren Sie sie:
Lösung
For ( x=100 , x>=1 , x++ )
cout << x << endl;
Lösung
for ( x =.1 ; x!=1.0; x+=.1 )
cout << x << endl;
if ( x=2 ) x++ else x--;
Lösung
if ( age<=40);
else if ( age<=50 )
cout << "Grufti";
else;
cout << "Uhu";
Lösung
14.05.2008
Kontrollstrukturen - Teil 1
24
HS-Übung 6: Kontrollstrukturen
FB Informatik
Prof. Dr. R.Nitsch
Was wird jeweils ausgegeben?
if ( x < 10 )
if ( y > 10)
cout << '*';
else
cout << '+';
cout << '#';
if (y == 8)
if (x == 5)
cout << "@"
else
cout << "#";
cout << "%";
cout << "*";
14.05.2008
x=8
y=12
x=5
y=8
x=8
y=8
x=8
y=5
⇒ Hausaufgabe
if ( x < 10 ) {
if ( y > 10)
cout << '*';
}
else {
cout << '+';
cout << '#';
}
x=12
y=8
x=7
y=8
x=8
x=8
y=12 y=8
x=12 x=12
y=8
x=12
x=5
y=7
Kontrollstrukturen - Teil 1
25
HS-Übung 6: Kontrollstrukturen
FB Informatik
Prof. Dr. R.Nitsch
6.1 Schreiben Sie Programmfragmente, die folgende Ausgaben generieren können:
*
**
***
****
*****
*****
****
***
**
*
*****
****
***
**
*
*
**
***
****
*****
⇒ Hausaufgabe
Erlaubt sind nur die Ausgabeanweisungen cout << '*', cout << ' ' und cout << endl
6.2 Schreiben Sie ein Programmfragment, das die Zahl π = 4 −
4 4 4 4
+ − + − ... + ...
3 5 7 9
mit einer Genauigkeit von 9 Nachkommastellen ausrechnet.
6.3 Schreiben Sie ein Programmfragment, das alle geraden Zahlen 2…100 ausgibt, mit
Ausnahme der Zahlen der 10er-Reihe unter Verwendung der while-, do…while und forAnweisung.
14.05.2008
Kontrollstrukturen - Teil 1
26
HS-Übung 7: Kontrollstrukturen
•
FB Informatik
Prof. Dr. R.Nitsch
In einer Fabrik zur Produktion von Fahrrad-Zahlenschlössern soll ein Computer
eingesetzt werden, der die Schließnummern festlegt. Das nötige Programm soll
folgende Anforderungen erfüllen:
a) Jede Schließnummer ist eine dreistellige Zahl.
b) Paarweise gleiche Ziffern in einer Schließnummer sind nicht erlaubt (z.B. ist
232 keine zulässige Schließnummer)
c) Alle gültigen Schließnummern soll das Programm so am Bildschirm ausgeben,
dass jeweils 20 Schließnummern in einer Zeile angeordnet sind.
d) Es soll die Anzahl der erzeugten, gültigen Schließnummern feststellen und am
Bildschirm ausgeben.
So sollen Anfang und Ende der Bildschirmausgabe aussehen:
012 013 014 015 016 017 018 019 021 023 024 025 026 027 028 029 031 032
036 037 038 039 041 042 043 045 046 047 048 049 051 052 053 054 056 057
061 062 063 064 065 067 068 069 071 072 073 074 075 076 078 079 081 082
085 086 087 089 091 092 093 094 095 096 097 098 102 103 104 105 106 107
…………………………………………………………………………………………………………………….
915 916 917 918 920 921 923 924 925 926 927 928 930 931 932 934 935 936
940 941 942 943 945 946 947 948 950 951 952 953 954 956 957 958 960 961
964 965 967 968 970 971 972 973 974 975 976 978 980 981 982 983 984 985
Insgesamt 720 Kombinationen
14.05.2008
Kontrollstrukturen - Teil 1
034
058
083
108
035
059
084
109
937 938
962 963
986 987
27
Herunterladen