Inhalt
4.2 Zusammengesetzte Anweisungen
(Anweisungsblöcke)
4.4 Strukturbezogene Sprunganweisung
4.6 Beispiel Euklidischer Algorithmus
Ein Programm besteht aus einer Folge von Funktionen. Jede Funktion hat einen Deklarationsteil, eine Folge von lokalen Deklarationen, und einen Anweisungsteil, einer Folge hintereinandergeschriebener Anweisungen.
Ausdrucksanweisungen
zusammengesetzte Anweisungen
Schleifenanweisungen
Auswahlanweisungen
Sprunganweisungen
Syntax: [ Ausdruck ] ;
Semantik: Berechnung des Ausdrucks.
Das Semikolon ;
ist hier ein Abschlusssymbol, kein Trennzeichen.
i
+ 1; keine Wirkung nach außen.
++ i; i wird inkrementiert.
Leeranweisung: ;
double r = 2, PI =
3.141593, U, A;
U = 2 * PI * r; A = PI * r * r;
Syntax: { [ lokale Deklaration ... ] [ Anweisung ... ] }
Leeranweisung: {}
Blöcke können geschachtelt werden.
Semantik:
Die angegebenen Anweisungen werden hintereinander entsprechend ihrer Reihenfolge abgearbeitet.
Verfügbarkeitsbereich lokaler Deklarationen.
Gültigkeit: Sichtbarkeit einer Größe ⇒ Zugriff
Verfügbarkeit: Lebensdauer einer Größe ⇒ Speicher
bloecke.c
/*
* Demonstration von Lebensdauer und
Sichtbarkeit
*/
# include
<stdio.h>
int main()
{
int x = 0; printf( "%d\n", x); /* 0 */
{
int x = 1; printf( "%d\n",
x); /* 1 */
{
int x = 2; printf( "%d\n",
x); /* 2 */
}
printf( "%d\n", x); /* 1 */
}
printf( "%d\n", x); /* 0 */
return 0;
}
Die while
Schleife ist eine vorgeprüfte (prechecked), abweisende Schleife:
Die Bedingung wird überprüft bevor die Anweisung ausgeführt wird.
Solange die Bedingung wahr ist wird
die Anweisung wiederholt.
Syntax: while ( Bedingung ) Anweisung
Semantik:
1. Die Bedingung wird ausgewertet.
2. Ist ihr Wert wahr (logisch
interpretiert), so wird die Anweisung
ausgeführt
und mit 1. fortgesetzt.
int x = 5;
while( x > 0
)
{
printf("%d \n", --x);
}
Ausgaben in den einzelnen Schleifendurchläufen:
Durchlauf |
x |
0 |
5 |
1 |
4 |
2 |
3 |
3 |
2 |
4 |
1 |
5 |
0 |
|
0 |
Die do
Schleife ist eine nachgeprüfte (postchecked), nicht abweisende
Schleife: Die Anweisung wird ausgeführt bevor die Bedingung überprüft wird. Solange die
Bedingung wahr ist wird die Anweisung wiederholt.
Syntax: do Anweisung while ( Bedingung );
Semantik:
1. Die Anweisung wird ausgeführt.
2. Ist der Wert der Bedingung wahr, so wird mit 1.
fortgesetzt.
Das Semikolon am Ende der do - Schleife ist für die
Syntaxanalyse notwendig!
int x, y; x = y = 0;
do
{
x += ++y;
printf( "%d %d\n", x, y);
} while( y <
5);
Zwischenergebnisse in den einzelnen
Schleifendurchläufen:
Durchlauf |
x |
y |
|
0 |
0 |
1 |
1 |
1 |
2 |
3 |
2 |
3 |
6 |
3 |
4 |
10 |
4 |
5 |
15 |
5 |
|
15 |
5 |
Unterschied zur while
– Schleife:
Während while - Schleifen zuerst die
Schleifenbedingungen testen und dann die Anweisung ausführen, führen die do
- Schleifen die Anweisung einmal aus, bevor sie die Bedingung überprüfen:
In der while - Schleife wird der
Schleifenkörper nicht unbedingt
durchlaufen.
In der do - Schleife wird der
Schleifenkörper mindestens einmal
durchlaufen.
Syntax: for ( [ Ausdruck1 ] ; [ Bedingung
] ; [ Ausdruck2
] ) Anweisung
Das Semikolon
fungiert hier als Trennzeichen!
Semantik:
1. Der Ausdruck1 wird ausgeführt.
2. Ist der Wert der Bedingung falsch, so wird die Schleife
abgebrochen.
3. Die Anweisung wird ausgeführt.
4. Der Ausdruck2 wird ausgeführt, anschließend bei 2. fortgesetzt.
Ausdruck1, Bedingung und Ausdruck2
sind optional. Fehlt die Bedingung,
so muss man explizit für den Abbruch sorgen!
Die Fakultät natürlicher Zahlen wird iterativ definiert:
itFak.c
/*
* Berechnen der Fakultaet fuer n = 12,
iterativ
*/
# include
<stdio.h>
int main()
{
int i, n = 12; /* 13! = 6'227'020'800 > ULONG_MAX */
unsigned long fak = 1;
for( i = 2; i <= n; i++) fak *= i;
/*
* for( i = 2; i <= n; fak *= i++);
* for( ; n > 1; fak *= n--);
*/
printf( "%lu\n", fak); /* 479'001'600 */
return 0;
}
ULONG_MAX Macro in <limits.h> für die
gröβte darstellbare unsigned long - Zahl
%lu Formatbeschreiber für unsigned
long - Ausgabe
Durch die Strukturierungsmöglichkeiten einer Programmiersprache gibt es eine Vielzahl von Sprüngen, die beim Programmablauf ausgeführt werden. Das Verlassen einer Schleifen erfolgt durch eine Bedingung. Eine Auswahlanweisung steuert das Durchlaufen eines Programmteils in Abhängigkeit einer Bedingung.
Es ist aber auch möglich, explizit ein Verlassen einer Anweisung zu erzwingen.
Beenden einer Anweisung
Syntax: break;
Semantik:
Die Abarbeitung der Anweisung wird abgebrochen.
Speziell für Schleifen kann ein Schleifendurchlauf abgebrochen werden.
Beenden eines
Schleifendurchlaufs
Syntax: continue;
Semantik:
Die Abarbeitung des Schleifendurchlaufs wird abgebrochen,
danach die Schleifenbedingung überprüft und entsprechend ihrem Wert die
Schleife weiterbehandelt.
Beispiel formale Endlosschleife.
sum.c
/*
* sum.c: Summenbildung
*/
# include
<stdio.h>
int main()
{
int zahl, summe = 0, add = 0;
do
{ /*
Schleifenabbruch */
if( scanf( "%d", &zahl) == EOF) break;
if( zahl == 0) continue; /*
Durchlaufabbruch */
summe += zahl; ++add;
} while( 1); /* Formale Endlosschleife */
printf( "Summe: %d\n", summe);
printf( "Additionen: %d\n", add);
return 0;
}
Syntax: if ( Bedingung ) Anweisung1 [ else Anweisung2 ]
Semantik:
1. Die Bedingung wird ausgewertet.
2. Ist ihr Wert wahr, so wird
die Anweisung1 ausgeführt.
3. Ist ihr Wert falsch, so
wird, falls vorhanden, die Anweisung2
ausgeführt.
Lösung der Gleichung .
if( a == 0)
if( b == 0) printf("L = R\n");
else printf("L = {}\n");
else printf("L
= { %f}\n", -b/a);
Bei geschachtelten if - Anweisungen wird
einem else stets das letzte vorhergehende if zugeordnet. Evtl. sind
Leeranweisungen erforderlich.
Auswahlanweisung oder bedingte Anweisung ?
Die bedingte Ausdrucksanweisung
x = Bedingung ? Ausdruck1 : Ausdruck2 ;
ist folglich äquivalent mit der Auswahlanweisung
if ( Bedingung )
x = Ausdruck1 ; else
x = Ausdruck2 ;.
Das Beispiel (s.o.)
quadrant = x >= 0? y >= 0? 1: 4:
y >= 0? 2: 3;
als if - Anweisung:
if( x >= 0)
if( y >= 0) quadrant = 1; else
quadrant = 4;
else
if( y >= 0) quadrant = 2; else
quadrant = 3;
Syntax: switch ( int_Ausdruck )
{
case int_Konstante1 : Anweisung11 Anweisung12 ...
case int_Konstante2 : Anweisung21 Anweisung22 ...
. .
.
[..default : d_Anweisung1 d_Anweisung2 ... ]
}
Der default - Fall kann an
jeder Stelle in der Auswahlliste stehen.
Semantik:
1. Der int_Ausdruck wird berechnet.
2. Sein Wert wird mit den int_Konstanten verglichen.
3. Bei Gleichheit wird die
Arbeit dort fortgesetzt.
4. Bei Ungleichheit mit allen int_Konstanten wird, falls vorhanden, bei default fortgesetzt.
Ablaufdiagramm einer switch - Anweisung für
den Sonderfall, das default am Ende der Auswahlliste steht:
Semantische
Falle:
Entgegengesetzt zu anderen Programmiersprachen haben
wir es hier nicht mit einer üblichen Fallunterscheidung zu tun, denn nach dem
Einsetzen der Abarbeitung von Anweisungen werden alle darauffolgenden Anweisungen
auch abgearbeitet. Um das zu verhindern, muss man mit break; die switch
- Anweisung explizit abbrechen.
Natürlich kann man sich die hier verwendete
Implementierung auch zunutze machen:
. .
. case Sub : op2
= - op2;
case Add : . . .
zahl1.c
/*
*Erzeugen des zu einer Zahl gehoerigen
Zahlwortes
*/
# include
<stdio.h>
int main()
{
int n;
/* Eingabe */
printf(
"Eingabe Zahl zwischen 100 und 999 :\n");
scanf( "%d", &n);
/* Verarbeitung und Ausgabe */
switch( n / 100)
{
case 1: printf( "Ein"); break; /* Hunderter */
case 2: printf( "Zwei"); break;
case 3: printf( "Drei"); break;
case 4: printf( "Vier"); break;
case 5: printf( "Fuenf"); break;
case 6: printf( "Sechs"); break;
case 7: printf( "Sieben"); break;
case 8: printf( "Acht"); break;
case 9: printf( "Neun"); break;
default:
printf( "Falsche Zahl\n"); return 1;
}
printf( "hundert");
switch( n % 100)
{
case 1: printf(
"eins"); break; /* Sonderfaelle */
case 11: printf( "elf"); break;
case 12: printf( "zwoelf");
break;
case 16: printf( "sechzehn");
break;
case 17: printf( "siebzehn");
break;
default: switch( n % 10) /* 13, 14, 15, 18, 19 */
{
case 0: /* nichts */ break; /* Einer */
case 1: printf( "ein"); break;
case 2: printf( "zwei"); break;
case 3: printf( "drei"); break;
case 4: printf( "vier"); break;
case 5: printf( "fuenf"); break;
case 6: printf( "sechs"); break;
case 7: printf( "sieben"); break;
case 8: printf( "acht"); break;
case 9: printf( "neun");
}
if( n % 100 / 10 > 1) printf(
"und");
switch( n % 100 / 10)
{
case 0: /* nichts */ break;/* Zehner */
case 1: printf( "zehn"); break;
case 2: printf(
"zwanzig"); break;
case 3: printf(
"dreiszig"); break;
case 4: printf( "vierzig");
break;
case 5: printf(
"fuenfzig"); break;
case 6: printf(
"sechzig"); break;
case 7: printf(
"siebzig"); break;
case 8: printf(
"achtzig"); break;
case 9: printf( "neunzig");
}
}
printf( "\n");
return 0;
}
Berechnung des größten gemeinsamen Teilers ggT(
m, n) und des kleinsten gemeinsamen Vielfachen kgV( m, n)
zweier natürlicher Zahlen n und m mittel
Euklidischen Algorithmus.
"Eingabe, Verarbeitung,
Ausgabe" . . . Das EVA – Prinzip der Datenverarbeitung.
ggTkgV.c
/*
*
ggTkgV.c:
* Berechnen des groessten gemeinsamen Teilers
und
* des kleinsten gemeinsamen Vielfachen
* zweier natuerlicher Zahlen.
*/
# include <stdio.h>
int main()
{
unsigned int
m, n, a, b, c;
/*
Eingabe */
printf( "m
= ");
scanf("%d", &m);
printf( "n
= ");
scanf("%d", &n);
/*
Verarbeitung */
a = m; b = n;
do
{
c = a % b; /* Rest der ganzzahligen Division */
a = b; b = c; /* Vertauschen der Werte */
} while( c != 0);
/*
Ausgabe */
printf( "ggT(
%d, %d) = %d\n",
m, n, a);
printf( "kgV(
%d, %d) = %d\n",
m, n, m * n /a);
return 0;
}