Programmierkurs C - Sommersemester 2011, 2. Vorlesung

Werbung
Programmierkurs C
Sommersemester 2011, 2. Vorlesung
Stuttgart, den 12. April 2011
Heiko Schulz
University of Stuttgart, Math. department
Rückschau
L
Algorithmen, Berechenbarkeit, Computer,
L
Programmiersprachen und Compiler,
L
Die Programmiersprache C, Syntax,
L
Variablen und elementare Datentypen,
L
Operatoren: Zusweisungsoperator, arithmetische Operatoren .
34
Anatomie eines C-Programms I
L
35
Programmkopf mit Anweisungen an Compiler/Präprozessor:
#include, etc.
L
Blöcke von Anweisungen, Anweisungen durch Semikolon ; getrennt.
L
Hauptfunktion int main() mit angeschlossenem Funktionsblock in
{}.
L
In der Hauptfunktion: return 0; zum Beenden des Programms.
L
Kommentare und Leerzeichen werden ignoriert.
Anatomie eines C-Programms II
36
Das Programm...
1 /*
*/
hello .c
#include
3
4 int
5
6
return
2
< s t d i o . h>
main ( )
{
p r i n t f (" Hallo
7
//
Welt ! \ n" ) ;
0;
hier
ist
Schluss
8 }
... ist äquivalent zu ...
1 /*
hello .c
Hallo
*/
#i n c l u d e
Welt ! \ n" ) ;
< s t d i o . h>
return
0;
/
*
int
hier
main ( )
ist
{
printf ("
Schluss
*/
}
Beispiel Division I
/
*
*/
div1 . c
#include
int
int
< s t d i o . h>
main ( )
{
a ,b,c;
a=
3;
b =7;
c =a / b ;
p r i n t f ( "% i /% i
= %i \ n " , a , b , c ) ;
c =b / a ;
p r i n t f ( "% i /% i
}
return
0;
= %i \ n " , b , a , c ) ;
37
Beispiel Division II
/
*
*/
div2 . c
#include
int
float
< s t d i o . h>
main ( )
a=
{
a ,b,c;
3.0;
b =7.0;
c =a / b ;
p r i n t f ( "%f /% f
= %f \ n " , a , b , c ) ;
c =b / a ;
p r i n t f ( "%f /% f
}
return
0;
= %f \ n " , b , a , c ) ;
38
Einschub: Compilieren mit
make
39
Vereinfachung des Compiler-Aufrufs via make-Kommando:
Wenn ein Makele existiert, wird
gcc
von
make
auf der Basis der Regeln
im Makele aufgerufen. Beispiel für ein Makele:
CC= g c c
OPTS=
all :
cast :
s t d =c99 W a l l
cast
fibonacci1
cast . c
$ ( CC )
fibonacci1 :
$ ( CC )
.
.
.
...
$ (OPTS)
cast . c
o
cast
fibonacci1 . c
$ (OPTS)
fibonacci1 . c
o
fibonacci1
Einschub: Compilieren mit
make
40
Bessere Variante über Platzhalter:
CC= g c c
OPTS=
all :
s t d =c99 W a l l
cast
inkr
fibonacci1
quadrat
wochentage
%:
fibonacci2
scanftest2
div1
div2
%. c
$ ( CC )
$ (OPTS)
fibonacci3
scanftest
$<
o
[email protected]
Dabei ist
L
$< die erste Abhängigkeit und
L
[email protected] der Name des zu erzeugenden Objekts.
summe
fibonacci4
tuwas
Vergleichsoperatoren
L
Vergleichsoperatoren:
@, A
@ ,A
,
L
!
: kleiner als, gröÿer als,
: kleiner oder gleich als, gröÿer oder gleich als,
: gleich, ungleich.
Die Vergleichsoperatoren haben geringere Priorität als
arithemtische Operatoren.
L
Die Operatoren <, >, <= und >= haben eine höhere Priorität als
== und !=.
41
Logische Operatoren
L
Auswertung logischer (Bool'scher) Aussagen.
L
Trit ein Vergleich zu, so spricht man von TRUE. In C steht ein
42
Wert ungleich 0 für TRUE.
L
Trit ein Vergleich nicht zu, so spricht man von FALSE. In C steht
der Wert 0 für FALSE.
L
Operatoren: ! steht für Negation, && für die UND-Verknüpfung
(AND) und || für die ODER-Verknupfung (OR).
L
Die Logischen Operatoren && und || haben eine geringere Priorität
als die Vergleichsoperatoren.
L
&& besitzt eine höhere Priorität als ||
L
Die Priorität des Negationsoperators ! ist sehr hoch, nur der
Klammeroperator ( ) besitzt eine höhere Priorität.
Zusammengesetze Zuweisungsoperatoren
L
Ein Ausdruck wie a = a + b; kann, um Schreibarbeit einzusparen,
durch a += b; ersetzt werden.
L
In gleicher Weise ergeben sich die zusammengesetzten Operatoren
-=, *=, /= und %=
L
Diese Schreibweise ist (insbesondere bei + und -) sehr weit
verbreitet.
L
Beispiele:
a
i
+=
=
10;
1;
erhöht der Wert von a um 10 und erniedrigt den Wert von i um 1.
43
Inkrement- und Dekrement-Operatoren
L
In C-Programmen gibt es oft Zählvariablen, die inkrementiert
(Addition von 1) oder dekrementiert (Subtraktion von 1) werden
müssen.
L
Dafür gibt es die Operatoren ++ (Inkrementoperator) und - (Dekrementoperator).
L
Die Operatoren - - und ++ können sowohl links
(Präx-Schreibweise) als auch rechts (Postx-Schreibweise) einer
Variablen stehen.
L
Bei Präxoperatoren wird die In- bzw. Dekrementierung vor allen
anderen Operationen durchgeführt, bei Postxoperatoren danach.
L
Inkrement- und Dekrement-Operatoren dürfen nicht auf der linken
Seite einer Zuweisung angewendet werden.
L
Die Priorität ist gleich wie die des Negationsoperators (!).
44
Inkrement- und Dekrement-Operatoren Beispiel
/
*
*/
inkr . c
#include
int
int
< s t d i o . h>
main ( )
a ,
45
{
b;
a =10;
a ++;
//
a
p r i n t f ( " a=% i \ n " ,
b=a + + ;
//
p r i n t f ( " a=%i ,
b=++a ;
//
p r i n t f ( " a=%i ,
}
return
0;
b
hat
jetzt
hat
jetzt
b=% i \ n " ,
a
den
Wert
11
den
Wert
11
a) ;
und
b
b=% i \ n " ,
a ,
haben
a ,
und
a
den
b) ;
jetzt
b) ;
den
Wert
13
Wert
12
Funktionen I
L
46
Wozu gibt es Funktionen? Zur Strukturierung von Programmen,
zur Wiederverwendung von Code-Teilen.
L
Es wird zwischen Deklaration und Denition einer Funktion
unterschieden.
L
Eine Deklaration hat die Form
TYP FUNKTIONSNAME ( TYP PARAM1 ,
TYP PARAM2 ,
...) ;
Sie deklariert den Funktionsprototyp, d.h. Name, Rückgabetyp und
Anzahl der Parameter, sowie Parametertypen der Funktion.
L
Eine Denition hat die Form
TYP FUNKTIONSNAME ( TYP PARAM1 ,
TYP PARAM2 ,
LOKALE VARIABLENDEKLARATIONEN ;
ANWEISUNGEN ;
}
return
. . . ;
...)
{
Funktionen II
L
47
Oft: Deklaration und Denition in einem Schritt, wie bei
Variablendeklaration und gleichzeitiger Zuweisung.
L
Soll die Funktion keine Rückgabewerte haben, so verwendet man
als Rückgabetyp den leeren Datentyp void, soll sie keine Parameter
haben, kann man für die Deklaration/Denition auch schreiben:
TYP FUNKTIONSNAME (
void
)
{
...
oder
TYP FUNKTIONSNAME ( )
{
...
}
}
Funktionen Beispiele I
L
Hauptfunktion int main() {... return 0; }
L
Funktion ohne Rückgabewert und Parameter:
void
tuwas ( )
printf (" ich
}
int
main ( )
tuwas ( ) ;
tuwas ( ) ;
}
{
{
tue
etwas . . . \ n" ) ;
48
Funktionen Beispiele II
L
Quadratzahl:
int
return
quadrat (
a
int
*a ;
a)
49
{
}
int
int
main ( )
{
a ,b;
a= q u a d r a t ( 3 ) ;
p r i n t f ( " a=% i \ n " ,
a) ;
b= q u a d r a t ( a ) ;
p r i n t f ( " a=%i ,
b=% i \ n " ,
a ,
b) ;
b=% i \ n " ,
a ,
b) ;
b= q u a d r a t ( b ) ;
p r i n t f ( " a=%i ,
}
return
0;
Funktionen Beispiele III
L
Summe:
int
int
int
return
summe (
a ,
c;
int
b)
50
{
c =a+b ;
c;
}
int
int
main ( )
{
a ,b,c;
a =1;
b =1;
c =summe ( a , b ) ;
c =summe ( c , 3 ) ;
p r i n t f ( " a=%i ,
}
return
0;
b=%i ,
c=% i \ n " ,
a ,
b,
c) ;
Variablen und ihre Gültigkeit
L
Variablen besitzen einen Gültigkeitsbereich (scope), innerhalb
dessen sie leben.
L
Man unterscheidet dabei den globalen Gültigkeitsbereich
(programmweit), den Datei-Gültigkeitsbereich (dateiweit), den
Funktions-Gültigkeitsbereich (funktionsweit) und den
Block-Gültigkeitsbereich (innerhalb eines Blockes).
L
Variablennamen (und Funktionsnamen) müssen innerhalb ihres
Gültigkeitsbereiches eindeutig sein.
L
Priorität der Gültigkeitsbereiche von global nach lokal, d.h. lokale
Variablen überdecken Sichtbarkeit globaler mit gleichem Namen.
Man sollte doppelte Verwendung von Variablennamen trotzdem
möglichst vermeiden.
51
Variablen und ihre Gültigkeit, Beispiel
L
1
2
3
4
5
Beispiel:
int
int
int
a =0;
// g l o b a l e
main ( )
a ,
Gueltigkeit
{
b,
c;
// f u n k t i o n s w e i t e
Gueltigkeit
a =1;
6
b =1;
7
c =4;
8
9
{
10
11
12
13
int
c ,
d;
// b l o c k w e i t e
Gueltigkeit
c =2;
d =5;
}
14
15
a =2
*c ;
// a
hat
den
Wert
8
16
b=a+b ;
// b
hat
den
Wert
9
17
a=b+d ;
// F e h l e r ,
18
19 }
return
0;
d
nicht
mehr
definiert !
52
Allgemeine Anatomie eines C-Programms
1 Include
Befehle
2 Globale
Deklarationen
( Variablen ,
Funktionen ,
3
4 TYP FUNKTION1 ( TYP PARAMETER1 ,
5
LOKALE VARIABLEN ;
6
ANWEISUNGEN ;
7
8 }
return
...)
{
...)
{
. . . ;
9
10 TYP FUNKTION2 ( TYP PARAMETER1 ,
11
LOKALE VARIABLEN ;
12
ANWEISUNGEN ;
13
14 }
15
16
17
return
int
18
19
20 }
53
. . . ;
main ( )
{
LOKALE VARIABLEN ;
ANWEISUNGEN ;
return
. . . ;
...)
Umwandeln von Datentypen (cast)
54
L
Explizite Datentypumwandlungen erreicht man mithilfe von Casts .
L
Ein Cast ist ein geklammerter Datentyp, der dem umzuwandelten
Ausdruck vorangestellt wird.
L
Syntax: (DATENTYP) AUSDRUCK;
L
Der Wert von AUSDRUCK wird in DATENTYP umgewandelt.
L
Beispiel:
1
2
int
double
double
int
n;
d;
3 n =
5;
4 d =
(
5 d +=
6 n =
)
n;
d;
//
1.5;
(
)
Vorsicht :
Information
geht
verloren !
Kontrolluss
L
Algorithmen lassen sich durch Flussdiagramme (Ablaufdiagramme)
beschreiben, zum Beispiel:
L
Kontrolluss: Verzweigungen, bedingte Ausführung, Schleifen,
Sprünge. Wie lassen sich diese Instrumente in C umsetzen?
55
Die if-Anweisung bedingte Ausführung
L
if-Anweisungen haben die Syntax
if
(
bedingung
)
anweisung ;
bedingung ein Bool'scher Ausdruck (wahr oder falsch) sein
bedingung erfüllt, wird anweisung ausgeführt. Falls
anweisung ein Block ist ( { ... } ). lässt man das Semikolon nach
anweisung weg.
wobei
muss. Ist
L
Soll im Alternativfall etwas anderes getan werden, wird der Befehl
else verwendet:
if
(
bedingung
)
anweisung1 ;
else
anweisung2 ;
bedingung erfüllt, wird anweisung1 ausgeführt, ansonsten
anweisung2. Dabei können anweisung1 und anweisung2 auch
Blöcke sein, wobei wieder die Semikolons nach anweisung1 und
anweisung2 weggelassen werden.
Ist
56
Die if-Anweisung bedingte Ausführung
L
Noch genauere Verzweigung:
if
(
bedingung1
anweisung2 ;
)
...
anweisung1 ;
else
else i f
57
( bedingung2 )
anweisungn ;
wobei die Anweisungen wieder auch Blöcke sein können.
L
Merke für Bedingungen: 0 bedeutet falsch, alle anderen
Ganzzahl-Werte bedeuten wahr.
L
Vorsicht: = ist der einfache Zuweisungsoperator,
== ist der Vergleichsoperator, der auf Gleichheit testet, eine
häuge Fehlerquelle.
Die if-Anweisung bedingte Ausführung
L
1
2
3
Beispiel:
int
if
4
}
5
6
}
7
8
9 }
groesser (
( a >b )
{
return
else i f
return else
return
a ,
1;
( a <b )
1;
{
0;
}
int
{
int
b)
{
58
Die if-Anweisung Fallstricke
L
1
2
3
FALSCH:
int
if
4
}
5
6
}
7
8
9 }
groesser (
( a=b )
{
return
else i f
return else
return
a ,
0;
1;
{
int
b)
Zuweisung ! !
( a <b )
1;
}
int
//
{
{
59
Die switch-Anweisung
L
60
Bestehen die Alternativen bei einer if-else-Abfrage aus ganzen
Zahlen oder einzelnen Zeichen, kann man stattdessen die
switch-Anweisung verwenden. So ist...
if
(
ausdr
==
)
==
ausdr0
ausdr1
{
...
)
}
{
)
{
aktion1 ;
else
{
aktion0 ;
}
}
else i f
standardaktion ;
... äquivalent zu...
switch
case
case
case
default
(
}
ausdr
)
{
ausdr0 :
aktion0 ;
ausdr1 :
aktion1 ;
ausdr2 :
...
:
break
break
standardaktion ;
;
;
else i f
(
ausdr
}
(
ausdr
==
ausdr2
Die switch-Anweisung
L
case gefolgt von ausdr und : ist eine Sprungmarke und wird nicht
als Anweisung interpretiert.
Sprungmarken (auch vom Muster Name:) werden bei der
Ausführung ignoriert.
L
Der Befehl break; führt zum Verlassen des switch-Blocks.
L
Ohne break geht es weiter zum nächsten Fall.
Anwendung: Initialisierung in mehreren Stufen.
Aber vergessene breaks sind auch beliebte Fehlerquelle!
61
Die switch-Anweisung Beispielprogramm
L
Beispiel:
int
wochentag ;
wochentag =3;
switch
case
break
case
break
case
break
( wochentag )
{
0:
p r i n t f ( " Noch
5
Tage
1
Tag
bis
zum
Wochenende . \ n " ) ;
;
...
4:
p r i n t f ( " Noch
bis
zum
Wochenende . \ n " ) ;
;
5:
p r i n t f ( " Juhu ,
}
;
es
ist
Wochenende ! \ n " ) ;
62
Die bedingte Auswertung
63
bedingung ? ausdr1 : ausdr2
L Ist bedingung wahr, so wird ausdr1 ausgewertet, andernfalls
ausdr2. Es handelt sich also um eine verkürzte if-Anweisung.
L
Syntax:
L
Beispiel: Anstatt
if
else
( zahl1
<
zahl2 )
min
=
zahl1 ;
min
=
zahl2 ;
zu schreiben, kann man auch kürzer
min
=
(
schreiben.
zahl1
<
zahl2
)
?
zahl1
:
zahl2 ;
Die for-Schleife
L
64
Syntax:
for
(
wobei
ausdruck1 ;
anweisung
bedingung ;
ausdruck2
)
anweisung ;
auch ein Anweisungsblock sein kann, der mit
{. . . } geklammert werden muss.
ausdruck1 initialisiert die Schleifenvariable(n).
L bedingung ist die Abbruchbedingung der Schleife.
Wenn bedingung falsch ist, wird die for-Schleife beendet.
L ausdruck2 reinitialisiert die Schleifenvariable(n) (beispielsweise
L
durch Inkrementierung).
L
Vorsicht: Kein Semikolon am Ende des for-Schleifenkopfs, wie in
for int
(
L
i =0;
i
<
n;
i ++) ;
p r i n t f ( "\%d \ n " , i ) ;
Seit C99 dürfen Zählvariablen im Schleifenkopf deklariert werden.
Die for-Schleife Beispielprogramm
/
*
*/
fibonacci1 . c
#include
int
int
main
< s t d i o . h>
()
{
aktuelle ,
n
=
vorletzte ,
=
i ,
n;
0;
letzte
=
printf
( " a_0 = %d \ n " ,
vorletzte
printf
( " a_1 = %d \ n " ,
letzte
( i
=
1;
2;
i
aktuelle
printf
letzte
}
return
0;
<=
=
n;
=
=
i
letzte
( "a_%d
vorletzte
}
letzte ,
10;
vorletzte
for
65
++)
+
= %d
letzte ;
aktuelle ;
) ;
) ;
{
vorletzte ;
\n" ,
i
,
aktuelle
) ;
Die while-Schleife I
L
66
Syntax:
while
wobei
(
bedingung
anweisung
)
anweisung ;
auch ein Anweisungsblock sein kann, der mit
{. . . } geklammert werden muss.
L
anweisung ausgeführt wird, wird bedingung geprüft.
bedingung bereits bei der ersten Auswertung falsch, wird
Bevor
Ist
die
Schleife nie durchlaufen.
L
Jede for-Schleife lässt sich durch eine äquivalente while-Schleife
ersetzen.
Die while-Schleife II
/
*
fibonacci2 . c
#include
int
int
()
{
aktuelle ,
//
letzte ,
vorletzte ,
10;
vorletzte
=
0;
letzte
=
printf
( " a_0 = %d \ n " ,
vorletzte
printf
( " a_1 = %d \ n " ,
letzte
i
i ,
n;
Initialisierung
=
=
1;
) ;
) ;
2;
while
( i
<=
aktuelle
printf
letzte
i ++;
}
return
0;
n
=
)
=
=
{
letzte
( "a_%d
vorletzte
}
*/
< s t d i o . h>
main
n
67
+
vorletzte ;
= %d \ n " ,
letzte ;
aktuelle ;
i ,
aktuelle
) ;
Die do . . . while-Schleife I
L
L
Syntax:
do
anweisung
while
(
68
bedingung
) ;
Im Gegensatz zu for- und while-Schleifen wird
bedingung
immer
am Ende eines Schleifendurchlaufs geprüft. Daher wird die Schleife
immer mindestens einmal durchlaufen.
bedingung
L
Ist
L
Wegen der besseren Lesbarkeit eines C-Programms sollte das
abschlieÿende Zeile stehen.
wahr, wird die Schleife ein weiteres Mal durchlaufen.
} while (bedingung);
immer auf einer extra
Die do . . . while-Schleife II
/
*
fibonacci3 . c
#include
int
int
main
=
*/
< s t d i o . h>
()
{
aktuelle ,
n
10;
letzte ,
vorletzte
=
vorletzte ,
0;
letzte
=
printf
( " a_0 = %d \ n " ,
vorletzte
printf
( " a_1 = %d \ n " ,
letzte
i
do
=
n;
) ;
) ;
2;
aktuelle
=
letzte
( "a_%d
vorletzte
letzte
=
=
while
return
( i
letzte ;
aktuelle ;
0;
<=
+
= %d
i ++;
}
i ,
1;
{
printf
}
69
n
) ;
vorletzte ;
\n" ,
i ,
aktuelle
) ;
Die Anweisungen break und continue I
L
...bieten zusätzliche, a-priori nicht bekannte Abbruchbedingungen
für Schleifen.
L
break bricht den Schleifendurchlauf ab und springt aus der Schleife
heraus.
L
continue bricht den
aktuellen
Schleifendurchlauf ab und setzt mit
dem nächsten Durchlauf fort.
L
Ziel: Vermeidung von Unübersichtlichkeit durch viele if-Blöcke.
70
Die Anweisungen break und continue II
L
71
Beispielprogramm Nur diejenigen der ersten n Fibonacci-Zahlen
sollen ausgegeben werden, die kleiner als 1000 und durch 3 teilbar
sind.
/
*
main
n,
n
=
for
< s t d i o . h>
()
{
aktuelle ,
if
if
letzte ,
vorletzte ,
i ;
5000;
(
letzte
vorletzte
aktuelle
=
=
=
vorletzte
letzte ,
letzte
+
(
aktuelle
>=
(
aktuelle
% 3)
printf
}
}
*/
fibonacci4 . c
#include
int
int
return
0;
( "a_%d
\t
=
1
,
letzte
i
=
=
2;;
i
aktuelle
=
i
)
{
vorletzte ;
break
continue
1000)
= %d
;
;
\n" ,
i
,
aktuelle
) ;
+
1,
Die goto-Anweisung I
72
L
Sprung an eine vordenierte Sprungmarke (Label).
L
Einzig sinnvolle Anwendung: Abbruch mehrfach geschachtelter
Schleifen. Vorsicht: schlechter Stil.
L
1
2
3
4
5
6
Beispiel:
while
for
if
{
(
=0;
i
i
<
sehrgross ;
i
++)
{
...
(
irgendwas
8
(
i
))
{
<
auchnichtklein ;
...
for
if
7
( j
=0;
j
...
9
10
(
bedingung ( i , j )
}
11
12
(1)
...
}
}
13 }
14 S c h l e i f e n e n d e :
...
)
{
goto
j
++)
{
Schleifenende ;
}
Die goto-Anweisung II
L
Andere Möglichkeit:
1 bool
2
3
4
5
6
7
73
Abbruch
while
for
if
=
i
false ;
0;
i
<
sehrgross ;
i
++)
{
(
irgendwas
(
i
))
{
...
for
if
( j
=
0;
j
<
auchnichtklein ;
j
++)
{
...
10
11
}
if
12
15 }
(
=
...
9
14
{
...
8
13
(1)
if
}
(
(
(
bedingung
break
;
break
break
Abbruch
Abbruch
)
( i
,
}
)
;
;
j )
)
{
Abbruch
=
true ;
Dateneingabe Die Funktion scanf
L
Die Funktion scanf dient zum Einlesen von Benutzereingaben.
L
Syntax:
scanf
(" format " ,
Der Formatstring
printf.
L
&v a r 1
format
,...) ;
ist nahezu gleich aufgebaut wie der von
Zu beachten: Nicht die Variable wird an scanf übergeben, sondern
eine Referenz (&) auf die Variable. Dazu später mehr!
L
Nicht-Formatanweisungen im Formatstring müssen mit eingegeben
werden, z.B. bei...
scanf
( " g a n z=%d " ,
&g a n z ) ;
müsste ganz= mit eingegeben werden.
74
Die Funktion scanf Beispielprogramm
/
*
scanftest . c
#include
int
int
char
float
main
75
*/
< s t d i o . h>
()
{
ganz ;
zeichen ;
printf
scanf
printf
scanf
printf
scanf
gleit ;
(" Bitte
( "% i " ,
(" Bitte
( "%s " ,
p r i n t f ( " ganz
zeichen ,
}
return
0;
sie
eine
sie
ein
ganze
Zahl
ein :
") ;
geben
Zeichen
ein :
") ;
&z e i c h e n ) ;
(" Bitte
( "%f " ,
geben
&g a n z ) ;
geben
sie
eine
Gleitkommazahl
ein :
") ;
&g l e i t ) ;
= %d \ n z e i c h e n
gleit ) ;
= %c \ n g l e i t
= %f \ n " ,
ganz ,
Vielen Dank...
... für Ihre Aufmerksamkeit und bis
morgen...
76
Herunterladen