Programmiersprachen Einführung in C Gliederung

Werbung
Programmiersprachen
Einführung in C
Teil 5: Kontrollstrukturen
Prof. Dr. Jörg Schwenk
Lehrstuhl für Netz- und Datensicherheit
Gliederung Programmiersprachen
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Von der Maschinensprache zu C
Die Struktur von C-Programmen
Variable und Datentypen in C
Bildschirm Ein-/Ausgabe
Kontrollstrukturen
Funktionen
Programmierstil, Programmierrichtlinien
Felder u. Zeichenketten
Ausdrücke
Arbeiten mit Dateien
Strukturen, Aufzählungstypen
Zeiger
Enums, Strukturen und Unions
Speicherklassen
Optional: Vertiefung einiger Themen
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
2
1
Kontrollstrukturen
1 Ohne Kontrollstrukturen:
1 lineare Programme
1 sequentielle Ausführung der Anweisungen
1 Probleme:
1
1
1
1
1
keine Reaktion auf äußere und innere Bedingungen möglich
keine Ausnahmebehandlung / Fehlerbehandlung möglich
starrer Ablauf, keine Wiederholungen
Parametrisierung eingeschränkt
arme Algorithmen-Schemata für Programmentwurf
1 Abhilfe
1 Anweisungen für die bedingte Ausführung von Anweisungsblöcken
1 Verzweigung und Mehrfachverzweigung, Kaskadierung von Bedingungen
1 Wiederholungsanweisungen für die wiederholte Ausführung von
Anweisungsblöcken
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
3
Verzweigung mit IF
1
allgemeine Formen bedingter Anweisungen
( <Bedingungsausdruck>
<Anweisung> ;
)
( <Bedingungsausdruck>
<Anweisung> ;
else
<Anweisung> ;
)
if
if
1
// Einzelanweisung
// Einzelanweisung
// Einzelanweisung
Behandlung von Anweisungsfolgen
if ( <Bedingungsausdruck> )
<Anweisungsfolge>
{
// Anweisungsfolge in { ... }
}
if ( <Bedingungsausdruck> )
<Anweisungsfolge>
{
// Anweisungsfolge in { ... }
}
else {
<Anweisungsfolge>
// Anweisungsfolge in { ... }
}
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
4
2
Beispiele für Fallunterscheidungen
1 Schleichwegfahrt: Fahrt Richtung Osten, wenn Tageszeit
zwischen 7 und 19 Uhr und Fußgängerampel auf rot, dann fahre
Schleichweg, sonst fahre geradeaus.
1 Abbruchbedingungen für Eingaben: noch eine Diskette
formatieren ?
1 Entscheidungen über Variablenwerte
1 Steuerung technischer Vorgänge: Wenn Vorlauftemperatur unter
Soll, dann öffne Mischer
1 wenn Vorlauftemperatur nicht höher als (Zimmer-Temp. + 5°) und
Rücklauf zwischen Vorlauf und (Vorlauf - 2°), dann U mwälzpumpe
aus
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
5
Beispiel: Zahlenklassifizieren
void main ()
{
const int zehn = 10;
int wert = 0;
printf(”\ngib eine Zahl ein : ”);
scanf("%d", &wert);
if
( wert == zehn ){
printf(”der Wert ist zehn ”);
// falls Wert gleich (Vorsicht !!)
}
else {
// andernfalls überprüfe, ob
if ( wert > zehn ){
printf(” Der Wert ist größer als zehn ”);
}
else {
// falls das auch nicht gilt
printf("Der Wert ist kleiner als zehn ”);
}
}
}
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
6
3
Beobachtungen (bei großer
Schachtelungstiefe)
1 Große Schachtelung führt schnell zur Unübersichtlichkeit
1 Einrückung im Programmtext ermöglicht Überblick
1 Strukturierung durch Verteilen auf mehrere Funktionen fördert
Übersichtlichkeit
1 Falls möglich auf switch-Anweisung (später) ausweichen
1 Achtung beim Test: im Extremfall Verdoppelung der
Programmpfade mit jeder neuen Entscheidungsebene
123456789
7
(Schachtelungsebene)
44897777
477712342356789
566
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
7
Vergleiche und logische Operatoren
1 Vergleichsoperatoren und logische Operatoren liefern als Ergebnis ...
1
1
in C++ Wahrheitswerte (Datentyp: bool),
in C jedoch einfach einen Zahlenwert, welcher entsprechend interpretiert
wird
wahr
/
falsch
true
/
false
≠0
/
0
(interne Realisierung)
1 Vergleichsoperatoren
1
1
gleich | ungleich|kleiner |größer |kleiner oder gleich |größer oder gleich
==
!=
<
>
<=
>=
Vergleiche haben geringere Auswertepriorität als arithmetische
Operatoren
if (i < lim-1) --> if (i < (lim-1)) // wie erwartet!
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
8
4
Vergleiche und logische Operatoren
1 Besonderheit in C/C++
1
1
1
1
Jeder Ausdruck kann als Wahrheitswert interpretiert werden
Daher:
if (3*x/12) zulässig; In Abhängigkeit von x wird
verzweigt
Insbesondere:if ( x = 12 ) ebenfalls zulässig; Konsequenzen???
Wertzuweisung hat niedrigere Priorität als Vergleichsoperatoren!
if ( (c=getchar()) != 'n') // Klammerung nötig!
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
9
Verwendung von Bedingungen
1 Beispiele
1
1
1
1
1
1
1
1
1
if (zahl > 10)
if (zahl)
if (zahl != 0)
//identisch zum Vorigen
if (3*x < 0)
if (x*x > 3*y*z)
if (fp = fopen("Datei", "r"))
if (test(x))
while (*d++ = *s++) ; //Zuweisung! (später)
for(i=0; i<27; i++)
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
10
5
Verwendung von Bedingungen
1 Empfehlung: auf Lesbarkeit achten!
1
1
1
Bei Vergleichen den "konstanteren" Teil auf die rechte Seite des
Vergleichsoperators stellen,
z.B.
for(i=0; i<27; i++)
nicht:
for(i=0; 27>i; i++)
Kein unnötiger Gebrauch von Wertzuweisungen im
Bedingungsteil; Beispiel:
fp = fopen("Datei", "r");
if (fp != NULL)
wäre ebenfalls möglich gewesen
Lieber (aufgrund der Auswerteprioritäten) zuviel Klammern setzen
als eine zuwenig!
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
11
logische Operatoren
1 ... verknüpfen Wahrheitswerte zu einem neuen Wahrheitswert
1 ... sind definiert über Ausdrücken, die zu Wahrheitswerten
ausgewertet werden können
Operator
UND
Schreibweise Schema wahr, wenn
!
! a
/ NOT
a ist falsch
&&
a && b beide sind wahr
/ AND
ODER
/ OR
NICHT
Kontrollstrukturen
||
a || b
Beispiel
! (a < b)
(a==b)&&(b < c)
ein Operand wahr (a<b) || (a>b)
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
12
6
logische Operatoren
1 Prioritäten
1 ! hat höhere Priorität als die Vergleichsoperatoren
1 die Priorität von && ist größer als die von ||
1 beide haben geringere Priorität als die Vergleichsoperatoren!
1 Wichtige Besonderheit bei C/C++
1 && oder || - Ausdrücke werden strikt von links nach rechts
bewertet
1 ... und zwar nur solange (!), bis das Resultat der logischen
Verknüpfung feststeht!
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
13
Verwendungsbeispiele
1 Bedingungsausdrücke (if-Anweisung , bedingte Schleifen)
Verknüpfen von Wahrheitswerten, Variablen und Vergleichsausdrücke
1
1
1
1
1
1
if (!( a < 1.0) )
if (!a)
if (!test(a))
if ( (a < 1.0) && (b > 4.7))
if ( a < 1.0 && b > 4.7 )
// ausreichend wäre:
do ...... while ((c=getchar()) != 'n'
&&
c != 'y')
in Wertzuweisungen für Wahrheitswerte:
a = a && (b < c) ;
a = (a == b) || (b == c);
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
14
7
Verwendungsbeispiele
1 Bedingungsausdrücke (if-Anweisung , bedingte Schleifen)
Verknüpfen von Wahrheitswerten, Variablen und Vergleichsausdrücke
1
1
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c !=
EOF; ++ i)
s[i] = c;
if (test() && tue_manches() )
// Achtung: tue_manches() wird nur aufgerufen, wenn test() true lieferte!!!
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
15
switch
1 Typische Anwendungen
1
1
1
1
Fallunterscheidung
Auswahlentscheidungen - 1 aus n
Anweisungskaskade mit berechnetem Einstieg
vollständige Mehrfachverzweigung
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
16
8
switch
1 Syntax
1
1
1
1
1
switch ( <Ganzzahlausdruck> )
{
case <Ganzzahlkonstante>: <Anweisung>
// Fall 1
....
case <Ganzzahlkonstante>: <Anweisung>
// Fall n
default :
<Default-Anweisung> // sonst-Fall
}
<Ganzzahlausdruck>: Ausdruck, der zu einem ganzzahligen Wert
ausgewertet wird
<Ganzzahlkonstante>: ganze Zahl oder Zeichen , keine strings!
<Anweisung>
alle in C/C++ erlaubten, formulierbaren Anweisungen,
besonders: break; (Verlassen der switchAnweisung)
<Default-Anweisung>
Sonst-Fall, kann fehlen
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
17
Abarbeitung der switch-Anweisung
1 Auswerten des <Ganzzahlausdruck>
1 Vergleich mit <Ganzzahlkonstante> der case-Konstante
1 Bei Gleichheit Ausführen der <Anweisung> hinter ":"
1 Anweisungsausführung ohne / mit break;
1 sequentielle Bearbeitung aller folgenden <Anweisungen> bis zum
ersten break;
1 oder bis Ende der switch ... } - Anweisung
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
18
9
Abarbeitung der switch-Anweisung
1 Besonderheit: <Anweisung> bzw. break kann auch fehlen:
1 Zusammenfassen mehrerer Fälle zu gleicher Bearbeitung
switch (ausdruck) {
case 1:
case 2:
printf("Fälle 1 & 2 ...");
break;
}
1 keine Übereinstimmung mit Fall-Konstante
1 Ausführen der <Default-Anweisung>
1 fehlt <Default-Anweisung>, Fortsetzung hinter switch ... }
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
19
Beispiel für Verwendung von switch:
Realisierung von Auswahl-Menüs
Cmd = getchar();
switch (Cmd) {
case 'h':
printf("Hilfe:\n");
printf("p - PKW eingeben\n";
printf("m - Motorrad eingeben\n";
printf("s <Kennzeichen> Daten zum Kennzeichen abrufen\n";
printf("d - alle Daten abrufen\n";
printf("x - Programm verlassen\n\n";
break;
case 'p':
/* Abfrage der PKW-Daten und Ablegen der Daten */
break;
case 'm':
/* Abfrage der Motorrad-Daten und Ablegen der Daten */
break; ...
case 'd':
/* Ausgabe der gesamten erfassten Daten */
break;
}
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
20
10
Zählschleife mit for
1 Wiederholung von Anweisungen abhängig von Zählvariable
1 typische Anwendungen:
1 Indexlauf, Indizierung von Feldelementen
1 Berechnungen, abhängig von Zählvariable
for (<Initialisierungsausdruck> ;
// initialisiert Zählvar.
<Durchlassausdruck>
;
// Bedingung für Durchlauf
<Schleifennachlaufausdruck> ) // Operation auf Zählvariable
< Anweisung> oder {< Anweisungsfolge>} // Schleifenrumpf
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
21
Zählschleife mit for
1 Besonderheiten / zu beachten
1 Durchlassausdruck wird vor dem (ersten) Betreten des
Schleifenrumpfs überprüft und kann somit zum "Überspringen" des
Schleifenrumpfs führen
1 Wert einer globalen Zählvariable ist nach der for-Schleife definiert
1 Die Berechnung innerhalb des Schleifenrumpfs muß der
Abbruchbedingung zustreben (Durchlassausdruck = false)
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
22
11
Zähl-Schleife mit for
1 Komma-Operator ermöglicht Initialisierung mehrerer
Variablen bzw. Fortschaltung mehrerer Variablen im
Schleifennachlaufausdruck
for (j=0, i=1; j<max; i++, j++) ...
1 Jeder der drei for-Schleifenabschnitte (Init, Durchlassen,
Fortschalten) kann leer sein. Ein fehlender
Durchlassausdruck wird als 'wahr' angenommen!!!
for ( ; ; ) // Formulierung einer unendlichen Schleife
--> Die Abbruchbedingung muß somit im Schleifenrumpf
stehen (break, return, oä.)
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
23
Zähl-Schleife mit for
1 Der Anweisungsteil kann leer sein (weil schon alles im for-Kopf
passiert).
Empfehlung: Dies optisch durch eine Zeile nur mit Semikolon
verdeutlichen!!!
for (i=0; z[i]=q[i]; i++)
;
Kontrollstrukturen
// z und q Zeichenketten
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
24
12
Beispiele
1 for (x=10 ; x<=15 ; x++)
// Schleifenkopf
{
printf("%d %d\n", x, x*x); // Schleifenrumpf
}
// { } Hier eigentlich unnötig
1234
56666766668666696666
666
1 max = feld[0];
// Was wird berechnet ?
for ( x=1; x<maxanz ; x=x+1 ) //
{
if (feld[x] > max)
//
max = feld[x];
//
}
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
25
Äquivalente Formulierung von for in
Form einer while-Schleife
<Initialisierungsausdruck>
while (<Durchlassausdruck>)
{
<Anweisungen....>
<Schleifennachlaufausdruck>
}
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
26
13
Bedingte Schleifen mit while und do
... while
1 Anwendungen:
1 bedingte Wiederholung einer Anweisung / Anweisungsfolge
1 do ... while besonders für Tastaturabfragen ... bis Eingabe gültig
1 Syntax der while-Schleife:
while ( <Bedingungsausdruck> )
<Anweisung> bzw. {<Anweisungsfolge> }
1 Semantik
1 Solange <Bedingungsausdruck> wahr, führe <Anweisung...>
aus.
1 Prüfe vor erstem Durchlauf
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
27
Bedingte Schleifen mit while und do
... while
1 Syntax der do ... while - Schleife:
do
<Anweisung>
bzw. { <Anweisungsfolge> }
while (<Bedingungsausdruck>)
1 Semantik:
1 Führe den Schleifenrumpf aus, solange der <Bedingungsausdruck>
wahr ist
1 Prüfe nach dem (ersten) Durchlauf --> mindestens ein Durchlauf!
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
28
14
Bedingungen für alle Schleifen
1 Der <Bedingungsausdruck> muß durch die Operationen im
Schleifenrumpf dem Wahrheitswert false zustreben
(nicht unbedingt monoton!)
1 dann:
1 sonst:
Schleife terminiert
Endlosschleife
1 Als <Bedingungsausdruck> zulässig
1 alle arithmetischen Ausdrücke,
1 alle Zeiger-Ausdrücke und
1 alle unzweideutig in solche konvertierbaren Ausdrücke
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
29
Unbedingte Fortsetzungen mit goto,
continue, break, return
1 goto marke ;
1 Herkunft: Assembler, Fortran, Basic,...
1 Wirkung: Unbedingte Fortsetzung des Programmlaufs bei der durch
Marke angezeigten Stelle innerhalb derselben Funktion
1 Anwendung
1 möglicher, aber nicht nötiger Anwendungsfall kann das Verlassen einer
tiefen Schachtelung sein, wenn Fehler, z.B. bei Funktionsaufrufen,
eingetreten sind.
1 for (...)
{ ...
while (...)
{ ...
if (schwerer_fehler) goto fehlerbehandlung;
}
}
fehlerbehandlung: fehler_behandlungs_anweisung ;
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
30
15
continue
1 Bedeutung
1 Beende aktuellen Durchlauf durch den Schleifenrumpf
1 setze Schleife mit neuem Durchlauf (d.h. ggf. Fortschaltung,
Durchlassprüfung) fort
1 Wirkung
1 Abbrechen des aktuellen Schleifendurchlaufs
1 nicht jedoch der ganzen Schleifenanweisung!!!
1 Anwendung
1 eher selten
1 Einsparung von if-Schachtelungen innerhalb des Schleifenrumpfs
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
31
Beispielprogramm für continue
1 // programm anz_ohne, Beispiel für die Anwendung von continue
// das Prog. zählt die Zeichenvorkommen != dem Zeichen in c (variable)
void main (void)
{
const maxstr = 20;
char str [maxstr] = ”Maximilian”;
char c = 'i';
// Vergleichszeichen
int anzahl = 0, anz_ohne_c = 0; // index bzw. zählervariable
while (str [anzahl])
// solange string-Ende nicht erreicht
{
if (str[anzahl++] ==c)
continue;
// beende Rumpfdurchlauf falls==c
anz_ohne_c = anz_ohne_c + 1; // sonst: erhöhe zähler
}
// enthält Zeichenanzahl ohne c
}
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
32
16
Beispielprogramm für continue
1 Wie kann man auf dieses continue verzichten bzw. es ohne Verlust
ersetzen?
if (str[anzahl++] != c)
// erhöhe zähler, wenn zeichen != c
anz_ohne_c = anz_ohne_c + 1;
// erhöhe feldindex, = gesamtanzahl
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
33
break
1 Bedeutung / Wirkung:
1 Bricht die Bearbeitung des aktuellen umgebenden switch-Blocks
oder der umgebenden Schleife ab.
1 Fortsetzung bei der Anweisung, die dem switch bzw. der Schleife
folgt.
1 Anwendung
1 durchaus geläufige Verwendung
1 Realisierung einer echten Mehrfachverzweigung in switch
1 Abbruch einer Schleife beim Eintreten von Ablaufbesonderheiten,
evtl. von Fehlern
1 Einsparung von 'Hilfsvariablen', die im Durchlassausdruck immer
wieder abgetestet werden müssen sowie das Verlassen einer
möglicherweise tiefen IF-Schachtelung
Kontrollstrukturen
Quelle: R. Eck und U. Wienkop
Programmieren I, GSO FH Nürnberg
34
17
Herunterladen