Am Tag 3, »Anweisungen, Ausdrücke und Operatoren«,
haben Sie die if
-Anweisung kennen gelernt, mit der Sie
zum ersten Mal auf den Programmablauf Einfluss nehmen konnten. Häufig stehen Sie
jedoch vor dem Problem, dass die Entscheidung zwischen wahr und unwahr allein
nicht ausreicht. Heute lernen Sie daher drei weitere Wege kennen, wie Sie den
Programmfluss beeinflussen können. Heute lernen Sie:
for
-, while
- und do...while
-Scheifen Anweisungen mehrmals
hintereinander ausführt
Hier, in diesem Kapitel werden wir die Themen noch nicht erschöpfend behandeln. Es soll Ihnen nur ausreichend Wissen vermittelt werden, so dass Sie mit dem Aufsetzen richtiger Programme beginnen können. Detailwissen zu diesen Themen finden Sie in Kapitel 12, »Fortgeschrittene Programmsteuerung«.
Bevor wir mit der for
-Anweisung beginnen, sollten wir einen kleinen Abstecher in die
Grundlagen der Arrays machen. (Siehe Tag 7, »Numerische Arrays«, für eine
komplette Behandlung der Arrays.) for
-Anweisung und Arrays sind in C eng
miteinander verbunden. Deshalb ist es schwierig, eines ohne das andere zu erklären.
Um Ihnen die Arrays in den Beispielen zu den for
-Anweisungen verständlich zu
machen, möchte ich erst einmal eine kurze Einführung zu den Arrays geben.
Ein Array ist eine indizierte Zusammenstellung von Datenspeicherpositionen, die den
gleichen Namen tragen und sich voneinander durch einen Index unterscheiden - eine
Zahl in eckigen Klammern, die auf den Variablennamen folgt. (Wenn Sie weiterlesen,
wird dies sicher verständlicher.) Wie andere C-Variablen auch müssen Arrays
deklariert werden. Eine Array-Deklaration umfasst den Datentyp und die Größe des
Arrays (die Anzahl der Elemente im Array). So deklariert die folgende Anweisung zum
Beispiel ein Array namens daten
, das vom Typ int
ist und 1000 int
-Elemente
enthält.
int daten[1000];
Um auf die einzelnen Elemente Bezug zu nehmen, verwenden Sie einen Index wie
daten[0]
bis daten[999]
. Das erste Element lautet daten[0]
und nicht daten[1]
. In
anderen Sprachen, wie zum Beispiel BASIC, erhält das erste Element im Array die
Zahl 1. Dies gilt aber nicht für C.
Jedes Element dieses Arrays entspricht einer normalen Integer-Variablen und kann auch genauso verwendet werden. Der Index eines Arrays kann auch eine andere C-Variable sein, wie folgendes Beispiel zeigt:
int daten[1000];
int zaehlung;
zaehlung = 100;
daten[zaehlung] = 12; /* Identisch mit daten[100] = 12 */
Diese Einführung in die Welt der Arrays war sehr kurz, sollte jedoch ausreichen, um Ihnen zu zeigen, wie Arrays in den nun folgenden Programmbeispielen verwendet werden. Und sollten Sie momentan noch nicht alles im Zusammenhang mit den Arrays verstehen, dann machen Sie sich nur keine Gedanken. Am Tag 7 werden wir Arrays im Detail besprechen.
Deklarieren Sie Ihre Arrays nicht mit unnötig großen Indizes. Sie verschwenden nur Speicher. Und merken Sie sich, dass in C Arrays mit dem Index 0 und nicht 1 beginnen. |
Standardmäßig wird ein C-Programm von oben nach unten ausgeführt. Die
Ausführung beginnt mit der main()
-Funktion und schreitet Anweisung für Anweisung
weiter, bis sie das Ende von main()
erreicht hat. In richtigen C-Programmen wird
diese Abfolge jedoch selten eingehalten. Die Programmiersprache C bietet eine Reihe
von Anweisungen zur Programmsteuerung, mit denen Sie die Programmausführung
beeinflussen können. Den Bedingungsoperator und die if
-Anweisung haben Sie
bereits kennen gelernt, so dass wir jetzt zu drei weiteren nützlichen
Steueranweisungen kommen können:
Die for
-Anweisung ist ein Programmkonstrukt, das einen Block von einer oder
mehreren Anweisungen mehrmals hintereinander ausführt. Manchmal wird sie auch
for
-Schleife genannt, da die Programmausführung diese Anweisung normalerweise
mehr als einmal durchläuft. In früheren Beispielen in diesem Buch sind Ihnen schon
einige for
-Anweisungen begegnet. Jetzt möchte ich Ihnen zeigen, was sich dahinter
verbirgt.
Ein for
-Anweisung hat die folgende Struktur:
for ( Initial; Bedingung; Inkrement )
Anweisung;
Initial
, Bedingung
und Inkrement
sind allesamt C-Ausdrücke. Anweisung
ist eine
einfache oder komplexe C-Anweisung. Wenn die Programmausführung auf eine for
-
Anweisung stößt, passiert Folgendes:
Initial
wird ausgewertet. Initial
ist in der Regel eine Zuweisung,
die eine Variable auf einen bestimmten Wert setzt.
Bedingung
wird ausgewertet. Bedingung
ist normalerweise ein
relationaler Ausdruck (Vergleich).
Bedingung
zu unwahr
(das heißt Null) ausgewertet wird, endet die for
-
Anweisung und die Ausführung fährt mit der ersten Anweisung nach Anweisung
fort.
Bedingung
zu wahr
(das heißt ungleich Null) ausgewertet wird, wird (werden)
die C-Anweisung(en) in Anweisung
ausgeführt.
Inkrement
wird ausgewertet und die Ausführung kehrt zurück zu
Schritt 2.
Abbildung 5.1 zeigt den Ablauf einer for
-Anweisung. Beachten Sie, dass Anweisung
niemals ausgeführt wird, wenn Bedingung
bereits bei der ersten Auswertung unwahr
ergibt.
Listing 5.1 enthält ein einfaches Beispiel für eine for
-Anweisung, die die Zahlen von 1
bis 20 ausgeben soll. Sie werden sicherlich feststellen, dass der resultierende Code
wesentlich kompakter und kürzer ist, als für jeden der 20 Werte eine eigene printf()
-
Anweisung zu verwenden.
Listing 5.1: Eine einfache for-Anweisung.
1: /* Beispiel für eine einfache for-Anweisung */
2:
3: #include <stdio.h>
4:
5: int count;
6:
7: int main(void)
8: {
9: /* Gibt die Zahlen von 1 bis 20 aus */
10:
11: for (count = 1; count <= 20; count++)
12: printf("%d\n", count);
13:
14: return 0;
15: }
Abbildung 5.1: Eine schematische Darstellung einer for-Anweisung.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Abbildung 5.2 veranschaulicht den Ablauf der for
-Schleife aus Listing 5.1.
Abbildung 5.2: Wie die for-Schleife aus Listing 5.1 funktioniert.
Zeile 3 bindet die Header-Datei für die Standardein-/-ausgabe ein. Zeile 5 deklariert
eine Variable vom Typ int
namens count
, die in der for
-Schleife verwendet wird. Die
Zeilen 11 und 12 enthalten die for
-Schleife. In der for
-Schleife wird die erste
Anweisung zuerst ausgeführt. In diesem Listing lautet die erste Anweisung count = 1
,
das heißt count
wird initialisiert und kann dann vom Rest der Schleife verwendet
werden. Der zweite Schritt der for
-Anweisung besteht darin, die Bedingung count <=
20
auszuwerten. Da count
gerade mit 1 initialisiert wurde, wissen Sie, dass dieser Wert
kleiner als 20 ist, so dass die Anweisung in dem for
-Befehl, der printf()
-Aufruf,
ausgeführt wird. Nach Ausführung des printf()
-Aufrufs wird der Inkrementierungs-
Ausdruck count++
ausgewertet. Dadurch wird count
um 1 erhöht, so dass die Variable
nun den Wert 2 erhält. Jetzt beginnt das Programm in der Schleife von vorn und prüft
die Bedingung erneut. Wenn sie immer noch wahr ist, wird printf()
wieder
ausgeführt, count
erneut inkrementiert (erhöht auf 3) und die Bedingung erneut
geprüft. Diese Schleife wird so lange fortgeführt, bis die Bedingung nicht mehr zutrifft,
das heißt falsch ist, woraufhin das Programm die Schleife verlässt und mit der
nächsten Zeile (Zeile 14) fortfährt, die 0 zurückliefert, bevor sie das Programm
beendet.
Die for
-Anweisung wird häufig, wie in dem obigen Beispiel, dafür verwendet,
»hochzuzählen«, das heißt, ein Zähler wird um einen Wert inkrementiert. Sie können
damit aber genauso gut »herunterzählen«, das heißt, die Zählervariable dekrementieren
(im Gegensatz zu inkrementieren).
for (count = 100; count > 0; count-- )
Der Wert, um den Sie »hoch- bzw. herunterzählen« muss nicht 1
sein, wie folgendes
Beispiel zeigt:
for (count = 0; count < 1000; count += 5)
Die for
-Anweisung ist ziemlich flexibel. Sie können beispielsweise auf die
Initialisierung verzichten, wenn die Variable bereits zuvor in Ihrem Programm
initialisiert wurde. (Sie müssen jedoch trotzdem, wie hier gezeigt, das Semikolon als
Trennzeichen verwenden.)
count = 1;
for ( ; count < 1000; count++)
Die Initialisierung muss keine Initialisierung im eigentlichen Sinn sein. Es kann ein
beliebiger C-Ausdruck sein. Was auch immer es ist, es wird ausgeführt, sobald die for
-
Anweisung das erste Mal erreicht wird. So wird im folgenden Beispiel die Meldung
»Array wird sortiert...«
ausgegeben:
count = 1;
for (printf("Array wird sortiert...") ; count < 1000; count++)
/* Sortieranweisungen */
Sie können auch die Inkrementierung fortlassen und die Aktualisierung im Rumpf der
for
-Anweisung vornehmen. Vergessen Sie aber nicht, das Semikolon zu setzen. Um
die Zahlen von 0 bis 99 auszugeben, könnten Sie zum Beispiel schreiben:
for (count = 0; count < 100; )
printf("%d", count++);
Der Test, mit dem die Schleife endet, kann ein beliebiger C-Ausdruck sein. Solange er
als wahr
(ungleich Null) ausgewertet wird, wird die for
-Anweisung ausgewertet. Sie
können mit den logischen Operatoren von C komplexe Testbedingungen
konstruieren. Die folgende for
-Anweisung gibt die Elemente eines Arrays namens
array[]
aus und stoppt erst, wenn alle Elemente ausgegeben worden sind oder ein
Element mit dem Wert von 0 vorliegt:
for (count = 0; count < 1000 && array[count] != 0; count++)
printf("%d", array[count]);
Sie könnten diese for
-Schleife sogar noch einfacher gestalten, indem Sie sie wie folgt
formulieren. (Wenn Sie die Änderung an der Testbedingung nicht verstehen, schlagen
Sie noch einmal unter Tag 3 nach.)
for (count = 0; count < 1000 && array[count]; )
printf("%d", array[count++]);
Sie können auf die for
-Anweisung eine Leeranweisung folgen lassen, so dass die
ganze Arbeit in der for
-Anweisung ausgeführt wird. Zur Erinnerung, eine
Leeranweisung ist ein Semikolon allein in einer Zeile. Um zum Beispiel alle Elemente
eines Arrays mit 1000 Elementen mit dem Wert 50 zu initialisieren, könnten Sie
schreiben:
for (count = 0; count < 1000; array[count++] = 50)
;
In dieser for
-Anweisung wird der Wert 50 jedem Element des Arrays durch den
Inkrementierungsteil der Anweisung zugewiesen.
Am Tag 3 wurde darauf hingewiesen, dass der Komma-Operator in C am häufigsten
in for
-Anweisungen verwendet wird. Sie können einen Ausdruck erzeugen, indem Sie
zwei Unterausdrücke mit dem Komma-Operator trennen. Die zwei Unterausdrücke
werden ausgewertet (von links nach rechts), und der ganze Ausdruck wird dann zu
dem Wert des rechten Unterausdrucks ausgewertet. Mit Hilfe des Komma-Operators
können Sie jeden Teil einer for
-Anweisung mehrere Aufgaben ausführen lassen.
Angenommen Sie haben zwei Arrays, a[]
und b[],
mit je 1000 Elementen und Sie
wollen den Inhalt von a[]
in umgekehrter Reihenfolge in b[]
kopieren, so dass nach
dem Kopiervorgang b[0] = a[999]
, b[1] = a[998]
ist und so weiter. Wie dies geht,
zeigt die folgende for
-Anweisung:
for (i = 0, j = 999; i < 1000; i++, j-- )
b[j] = a[i];
Der Komma-Operator dient also dazu, zwei Variablen, i
und j
, zu initialisieren und
bei jeder Schleifeniteration zu inkrementieren bzw. zu dekrementieren.
for (Initial; Bedingung; Inkrement)
Anweisung(en);
Initial
ist ein beliebiger gültiger C-Ausdruck. In der Regel ist es eine Zuweisung, die
eine Variable auf einen bestimmten Wert setzt.
Bedingung
ist ein beliebiger gültiger C-Ausdruck, in der Regel ein relationaler
Ausdruck. Wenn Bedingung
als unwahr
(Null) ausgewertet wird, endet die for
-
Anweisung und das Programm wird mit der ersten Anweisung nach Anweisung(en);
fortgesetzt. Im anderen Fall werden die Anweisungen in Anweisung(en)
ausgeführt.
Inkrement
ist ein beliebiger gültiger C-Ausdruck. In der Regel ist es ein Ausdruck, der
eine durch den ersten Ausdruck initialisierte Variable inkrementiert.
Bei Anweisung(en)
handelt es sich um die C-Anweisungen, die ausgeführt werden,
solange die Bedingung wahr ist.
Die for
-Anweisung gehört zu den Schleifen. Sie kann einen Initialisierungs-, einen
Bedingungs- und einen Inkrementteil in sich einschließen. Die for
-Anweisung führt
zuerst die Initialisierungsanweisung aus. Danach wird die Bedingung geprüft. Wenn
die Bedingung wahr ist, werden die mit der Bedingung verknüpften Anweisungen
ausgeführt. Anschließend wird der Inkrementierungsausdruck ausgewertet. Zum
Schluss prüft die for
-Anweisung die Bedingung erneut und durchläuft die Schleife so
lange, bis die Bedingung falsch ist.
/* Gibt beim Zählen von 0 bis 9 den Wert von x aus */
int x;
for (x = 0; x <10; x++)
printf( "\nDer Wert von x ist %d", x );
/* Liest so lange Werte ein, bis die Zahl 99 eingegeben wird */
int nbr = 0;
for ( ; nbr != 99; )
scanf( "%d", &nbr );
/* Erlaubt die Benutzereingabe von bis zu 10 Integer-Werten */
/* Die Werte werden in einem Array namens wert gespeichert. */
/* Wenn 99 eingegeben wird, stoppt die Schleife. */
int wert[10];
int ctr, nbr=0;
for (ctr = 0; ctr < 10 && nbr != 99; ctr++)
{
puts("Geben Sie eine Zahl ein, mit 99 verlassen ");
scanf("%d", &nbr);
wert[ctr] = nbr;
}
Eine for
-Anweisung kann innerhalb einer anderen for
-Anweisung ausgeführt werden.
Dies nennt man Verschachteln. (Am Tag 3 haben Sie bereits die Verschachtelung
von if
-Anweisungen gesehen). Durch das Verschachteln von for
-Anweisungen lassen
sich komplexe Programmierprobleme lösen. Listing 5.2 ist zwar kein komplexes
Programm, aber es zeigt, wie zwei for
-Anweisungen ineinander verschachtelt werden.
Listing 5.2: Verschachtelte for-Anweisungen.
1: /* Beispiel für die Verschachtelung zweier for-Anweisungen */
2:
3: #include <stdio.h>
4:
5: void rechteck_zeichnen( int, int);
6:
7: int main(void)
8: {
9: rechteck_zeichnen( 8, 35 );
10:
11: return 0;
12: }
13:
14: void rechteck_zeichnen( int reihe, int spalte )
15: {
16: int spa;
17: for ( ; reihe > 0; reihe -- )
18: {
19: for (spa = spalte; spa > 0; spa -- )
20: printf("X");
21:
22: printf("\n");
23: }
24: }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Die Hauptarbeit dieses Programms wird in Zeile 20 geleistet. Wenn Sie dieses
Programm ausführen, werden 280 X
in Form eines Rechtecks von 8 x 35 Zeichen auf
dem Bildschirm ausgegeben. Das Programm weist zwar nur einen Befehl zur Ausgabe
eines X
auf, aber dieser befindet sich in zwei Schleifen.
In diesem Listing wird in Zeile 5 ein Funktionsprototyp für rechteck_zeichnen()
deklariert. Diese Funktion übernimmt zwei Variablen, reihe
und spalte
, vom Typ int
,
die die Abmaße des auszugebenden Rechtecks enthalten. In Zeile 9 ruft main()
rechteck_zeichnen()
auf und übergibt für reihe
den Wert 8
und für spalte
den Wert 35
.
Wenn Sie die Funktion rechteck_zeichnen()
genau betrachten, werden Ihnen
vielleicht einige Dinge auffallen, die nicht sofort verständlich sind. So kann man sich
fragen, warum die lokale Variable spa
deklariert oder in Zeile 22 die Funktion
printf()
verwendet wurde. Das alles wird etwas klarer, nachdem wir erst einmal die
beiden for
-Schleifen betrachtet haben.
In Zeile 17 beginnt die erste for
-Schleife. Die Initialisierung wird übersprungen, da der
Anfangswert für reihe
der Funktion als Argument übergeben wurde. Ein Blick auf die
Bedingung zeigt Ihnen, dass diese for
-Schleife so lange ausgeführt wird, bis reihe
gleich 0
ist. Bei der ersten Ausführung von Zeile 17 ist reihe
gleich 8
. Deshalb fährt
das Programm mit Zeile 19 fort.
Zeile 19 enthält die zweite for
-Anweisung. Dort wird der übergebene Parameter
spalte
in eine lokale Variable, spa
, vom Typ int
kopiert. Der Wert von spa
ist
anfänglich 35
(der Wert der via spalte
übergeben wurde), und spalte
behält seinen
ursprünglichen Wert bei. Da spa
größer als 0
ist, wird Zeile 20 ausgeführt und ein X
ausgegeben. Daraufhin wird spa
dekrementiert und die Schleife fortgeführt. Wenn spa
gleich 0
ist, endet die for
-Schleife und der Programmfluss springt in Zeile 22. Zeile 22
bewirkt, dass die Ausgabe auf dem Bildschirm in einer neuen Zeile fortgesetzt wird.
(Mehr zur Ausgabe erfahren Sie am Tag 6, »Grundlagen der Ein- und Ausgabe«.) Mit
dem Sprung in die neue Bildschirmzeile hat die Programmausführung das Ende der
Anweisungen in der ersten for
-Schleife erreicht und führt den
Dekrementierungsausdruck aus, der 1 von reihe
subtrahiert, so dass der Wert jetzt 7
beträgt. Damit geht die Programmsteuerung zurück in Zeile 19. Beachten Sie, dass
der Wert von spa
bei seiner letzten Verwendung 0
war. Wenn Sie anstelle von spa
spalte
verwendet hätten, würde diese Variable den Bedingungstest nicht bestehen, da
sie zu keiner Zeit größer als 0
werden würde. Es würde nur die erste Zeile ausgegeben.
(Sie können sich selbst davon überzeugen, indem Sie aus Zeile 19 den
Initialisierungsteil löschen und die beiden spa
-Variablen in spalte
ändern.)
Die while
-Anweisung, auch while
-Schleife genannt, führt einen Anweisungsblock so
lange aus, wie eine spezifizierte Bedingung wahr ist. Die while
-Anweisung hat
folgende Form:
while (Bedingung)
Anweisung;
Bedingung
ist ein beliebiger C-Ausdruck und Anweisung
ist eine einfache oder
komplexe C-Anweisung. Wenn die Programmausführung auf eine while
-Anweisung
stößt, passiert Folgendes:
Bedingung
wird ausgewertet.
Bedingung
als unwahr
(das heißt als Null) ausgewertet wird, endet die while
-
Anweisung und die Ausführung fährt mit der ersten Anweisung nach Anweisung
fort.
Bedingung
als wahr
(das heißt ungleich Null) ausgewertet wird, wird (werden)
die C-Anweisung(en) in Anweisung
ausgeführt
In Abbildung 5.3 sehen Sie den Ablauf der Programmausführung in einer while
-
Anweisung.
Abbildung 5.3: Ablauf der Programmausführung in einer while-Anweisung.
Listing 5.3 enthält ein einfaches Programm, das eine while
-Anweisung dazu
verwendet, die Zahlen von 1 bis 20 auszugeben. (Die gleiche Aufgabe wurde auch von
der for
-Anweisung in Listing 5.1 ausgeführt.)
Listing 5.3: Eine einfache while-Anweisung.
1: /* Beispiel einer einfachen while-Anweisung */
2:
3: #include <stdio.h>
4:
5: int count;
6:
7: int main(void)
8: {
9: /* Gibt die Zahlen von 1 bis 20 aus */
10:
11: count = 1;
12:
13: while (count <= 20)
14: {
15: printf("%d\n", count);
16: count++;
17: }
18: return 0;
19: }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Analysieren Sie Listing 5.3 und vergleichen Sie es mit Listing 5.1, in der das gleiche
Problem mit Hilfe einer for
-Anweisung gelöst wurde. Zeile 11 initialisiert count
mit
dem Wert 1
. Da die while
-Anweisung keinen Initialisierungsabschnitt enthält, müssen
Sie daran denken, alle Variablen vor der while
-Schleife zu initialisieren. Zeile 13
enthält die eigentliche while
-Anweisung, einschließlich der gleichen Bedingung wie in
Listing 5.1: count <= 20
. Zeile 16 in der while
-Schleife übernimmt die
Inkrementierung von count
. Was würde Ihrer Meinung nach passieren, wenn Sie die
Zeile 16 in Ihrem Programm weggelassen hätten? Ihr Programm wüsste nicht, wann
es aufhören sollte, da count
immer 1
und damit immer kleiner als 20
wäre.
Vielleicht haben Sie inzwischen bemerkt, dass eine while
-Anweisung im Wesentlichen
einer for
-Anweisung entspricht, bei der die Initialisierung und Inkrementierung fehlen.
Demzufolge ist
for ( ; Bedingung ; )
while (Bedingung)
Aufgrund dieser Ähnlichkeit kann alles, was mit einer for
-Anweisung möglich ist,
auch mit einer while
-Anweisung bewältigt werden. Wenn Sie jedoch while
verwenden, müssen alle erforderlichen Initialisierungen zuvor in einer eigenen
Anweisung vorgenommen werden und die Aktualisierung muss in Form einer
Anweisung in der while
-Schleife selbst erfolgen.
In allen Fällen, in denen Initialisierung und Aktualisierung unverzichtbar sind,
bevorzugen die meisten erfahrenen C-Programmierer die for
-Anweisung -
hauptsächlich wegen der besseren Lesbarkeit des Quelltextes. Bei einer for
-
Anweisung stehen die Ausdrücke für Initialisierung, Test und Inkrementierung alle
zusammen und sind damit leicht zu finden und zu ändern. Bei einer while
-Anweisung
stehen Initialisierung und Aktualisierung an getrennten Stellen und sind mitunter nicht
leicht auszumachen.
while (Bedingung)
Anweisung(en);
Bedingung
ist ein beliebiger gültiger C-Ausdruck, in der Regel ein relationaler
Ausdruck. Wenn Bedingung
als unwahr
(Null) ausgewertet wird, endet die while
-
Anweisung und die Ausführung fährt mit der ersten Anweisung nach Anweisung(en);
fort. Im anderen Fall wird die erste Anweisung in Anweisung(en)
ausgeführt.
Bei Anweisung(en)
handelt es sich um die C-Anweisungen, die ausgeführt werden,
solange die Bedingung
wahr ist.
Die while
-Anweisung gehört zu den Schleifen. Mit ihrer Hilfe kann man eine
Anweisung oder einen Anweisungsblock so lange wiederholt ausführen lassen, wie
eine gegebene Bedingung wahr ist (ungleich Null). Wenn die Bedingung
bereits bei der
ersten Ausführung des while
-Befehls nicht wahr ist, werden die Anweisung(en)
nie
ausgeführt.
int x = 0;
while (x < 10)
{
printf("\nDer Wert von x ist %d", x );
x++;
}
/* Liest solange Werte ein, bis die Zahl 99 eingegeben wird */
int nbr=0;
while (nbr <= 99)
scanf("%d", &nbr );
/* Erlaubt die Benutzereingabe von bis zu 10 Integer-Werten */
/* Die Werte werden in einem Array namens wert gespeichert. */
/* Wenn 99 eingegeben wird, stoppt die Schleife. */
int wert[10];
int ctr = 0;
int nbr;
while (ctr < 10 && nbr != 99)
{
puts("Geben Sie eine Zahl ein, mit 99 verlassen ");
scanf("%d", &nbr);
wert[ctr] = nbr;
ctr++;
}
Wie schon vorher die for
- und if
-Anweisungen können auch while
-Anweisungen
verschachtelt werden. In Listing 5.4 finden Sie ein Beispiel für verschachtelte while
-
Anweisungen. Dies ist zwar nicht der beste Einsatzbereich für eine while
-Anweisung,
aber das Beispiel hält einiges Neue für Sie bereit:
Listing 5.4: Verschachtelte while-Anweisungen.
1: /* Beispiel für verschachtelte while-Anweisungen */
2:
3: #include <stdio.h>
4:
5: int array[5];
6:
7: int main(void)
8: {
9: int ctr = 0,
10: nbr = 0;
11:
12: printf("Dies Programm fordert Sie auf, 5 Zahlen einzugeben\n");
13: printf("Jede Zahl muss zwischen 1 und 10 liegen\n");
14:
15: while ( ctr < 5 )
16: {
17: nbr = 0;
18: while (nbr < 1 || nbr > 10)
19: {
20: printf("\nGeben Sie Zahl %d von 5 ein: ", ctr + 1 );
21: scanf("%d", &nbr );
22: }
23:
24: array[ctr] = nbr;
25: ctr++;
26: }
27:
28: for (ctr = 0; ctr < 5; ctr++)
29: printf("Der Wert von %d lautet %d\n", ctr + 1, array[ctr] );
30:
31: return 0;
32: }
Dies Programm fordert Sie auf, 5 Zahlen einzugeben
Jede Zahl muss zwischen 1 und 10 liegen
Geben Sie Zahl 1 von 5 ein: 3
Geben Sie Zahl 2 von 5 ein: 6
Geben Sie Zahl 3 von 5 ein: 3
Geben Sie Zahl 4 von 5 ein: 9
Geben Sie Zahl 5 von 5 ein: 2
Der Wert von 1 lautet 3
Der Wert von 2 lautet 6
Der Wert von 3 lautet 3
Der Wert von 4 lautet 9
Der Wert von 5 lautet 2
Wie schon in den vorherigen Listings enthält Zeile 1 einen Kommentar, der das
Programm beschreibt, und Zeile 3 eine #include
-Anweisung für die Header-Datei der
Standardein-/-ausgabe. Zeile 5 deklariert ein Array (namens array
), das fünf Integer-
Werte aufnehmen kann. Die Funktion main()
deklariert zwei zusätzliche lokale
Variablen, ctr
und nbr
(in den Zeilen 9 und 10). Beachten Sie, dass diese Variablen
bei ihrer Deklaration mit 0
initialisiert werden. Auch möchte ich Sie auf den Komma-
Operator am Ende von Zeile 9 hinweisen, der als Trennzeichen dient und nbr
als int
deklariert, ohne dass dafür in Zeile 10 die Angabe des int
-Typs wiederholt werden
muss. Deklarationen dieser Art sind gängige Praxis unter vielen C-Programmierern.
Die Zeilen 12 und 13 geben eine Meldung aus, die darüber informiert, was das
Programm macht und was vom Anwender erwartet wird. In den Zeilen 15 bis 26
stehen der erste while
-Befehl und seine Anweisungen. Eingebettet darin befindet sich
in den Zeilen 18 bis 22 eine verschachtelte while
-Schleife mit eigenen Anweisungen,
die Teil der äußeren while
-Anweisung ist.
Die äußere Schleife wird so lange ausgeführt, wie ctr
kleiner als 5
ist (Zeile 15).
Solange ctr
kleiner als 5
ist, setzt Zeile 17 nbr
auf 0
, die Zeilen 18 bis 22 (die
verschachtelte while
-Anweisung) lesen eine Zahl in die Variable nbr
ein, Zeile 24 legt
die Zahl in array
ab und Zeile 25 inkrementiert ctr
. Die Aufgabe der äußeren Schleife
besteht also darin, fünf Zahlen entgegenzunehmen, sie jeweils in array
abzulegen und
sie mit ctr
zu indizieren.
Die innere Schleife ist ein gutes Beispiel für den sinnvollen Einsatz einer while
-
Anweisung. Im Programm stellen nur die Zahlen von 1 bis 10 gültige Eingaben dar
und solange der Anwender keine gültige Zahl eingibt, soll das Programm nicht
fortgeführt werden. Die Zeilen 18 bis 22 enthalten den zugehörigen Code. Die while
-
Anweisung sorgt dafür, dass für Eingaben kleiner als 1 oder größer als 10 der
Anwender erneut aufgefordert wird, eine Zahl einzuzugeben, und diese dann
eingelesen wird.
Die Zeilen 28 und 29 geben die Werte aus, die in array
gespeichert sind. Beachten
Sie, dass der for
-Befehl die Variable ctr
verwenden kann, weil diese von den while
-
Anweisungen nicht mehr benötigt wird. Die for
-Schleife, die bei Null beginnt und um
1 inkrementiert, wird fünfmal durchlaufen und gibt den Wert von ctr
plus 1 (da die
Zählung bei Null begann) sowie den entsprechenden Wert in array
aus.
Es gibt zwei Dinge in diesem Programm, die Sie zu Übungszwecken einmal ändern sollten. Zum einen können Sie den Wertebereich, den das Programm akzeptiert, verändern. Erweitern Sie ihn doch einfach von 1 bis 10 auf 1 bis 100. Außerdem können Sie die Anzahl der einzugebenden Werte variieren. Im jetzigen Programm sind das fünf Zahlen. Versuchen Sie es doch einmal mit 10.
Das dritte Schleifenkonstrukt von C ist die do...while
-Schleife, die einen
Anweisungsblock so lange ausführt, wie eine bestimmte Bedingung wahr ist. Eine
do...while
-Schleife testet die Bedingung allerdings erst am Ende der Schleife und
nicht am Anfang, wie das bei den for
- und der while
-Schleifen der Fall ist.
Der Aufbau einer do...while
-Schleife sieht folgendermaßen aus:
do
Anweisung;
while (Bedingung);
Bedingung
ist ein beliebiger C-Ausdruck und Anweisung
ist eine einfache oder
komplexe C-Anweisung. Wenn das Programm auf eine do...while
-Anweisung trifft,
passiert Folgendes:
Anweisung
werden ausgeführt.
Bedingung
wird ausgewertet. Ist sie wahr, kehrt die Ausführung zurück zu
Schritt 1. Ist sie falsch, wird die Schleife beendet.
Den Ablauf einer do...while
-Schleife finden Sie in Abbildung 5.4.
Abbildung 5.4: Der Ablauf einer do...while-Schleife.
Die Anweisungen einer do...while
-Schleife werden immer mindestens einmal
ausgeführt. Dies liegt daran, dass die Testbedingung am Ende der Schleife und nicht
am Anfang ausgewertet wird. for
- und while
-Schleifen dagegen werten die
Testbedingung zu Beginn der Schleife aus, so dass ihre Anweisungen nicht ausgeführt
werden, wenn die Testbedingung bereits bei Eintritt in die Schleife unwahr ist.
do...while
-Schleifen werden seltener verwendet als while
- und for
-Schleifen. Sie sind
vor allem dort angebracht, wo die Anweisung(en) der Schleife zumindest einmal
ausgeführt werden muss (müssen). Sie können das Problem auch ohne weiteres mit
einer while
-Schleife lösen, indem Sie sicher stellen, dass die Testbedingung wahr ist,
wenn die Programmausführung die Schleife das erste Mal erreicht. Allerdings wäre
eine do...while
-Schleife wahrscheinlich unkomplizierter.
Listing 5.5 zeigt Ihnen ein Beispiel für eine do...while
-Schleife.
Listing 5.5: Eine einfache do...while-Schleife.
1: /* Beispiel für eine einfache do...while-Anweisung */
2:
3: #include <stdio.h>
4:
5: int menue_option_einlesen( void );
6:
7: int main(void)
8: {
9: int option;
10:
11: option = menue_option_einlesen();
12:
13: printf("Sie haben die Menü-Option %d gewählt\n", option );
14:
15: return 0;
16: }
17:
18: int menue_option_einlesen( void )
19: {
20: int auswahl = 0;
21:
22: do
23: {
24: printf("\n" );
25: printf("\n1 - Datensatz hinzufügen" );
26: printf("\n2 - Datensatz ändern ");
27: printf("\n3 - Datensatz löschen ");
28: printf("\n4 - Verlassen");
29: printf("\n" );
30: printf("\nGeben Sie Ihre Wahl ein: " );
31:
32: scanf("%d", &auswahl );
33:
34: }while ( auswahl < 1 || auswahl > 4 );
35:
36: return auswahl;
37: }
1 - Datensatz hinzufügen
2 - Datensatz ändern
3 - Datensatz löschen
4 - Verlassen
Geben Sie Ihre Wahl ein: 8
1 - Datensatz hinzufügen
2 - Datensatz ändern
3 - Datensatz löschen
4 - Verlassen
Geben Sie Ihre Wahl ein: 4
Sie haben die Menü-Option 4 gewählt
Dieses Programm stellt ein Menü mit vier Optionen bereit. Der Anwender wählt eine
der vier Optionen aus, und das Programm gibt dann die gewählte Zahl aus. Spätere
Programme in diesem Buch verwenden und erweitern dieses Konzept. Der größte Teil
des Listings sollte Ihnen vom Verständnis her keine Schwierigkeiten bereiten. Die
Funktion main()
in den Zeilen 7 bis 16 enthält nichts, was Sie nicht schon kennen.
Der Rumpf von
main()
hätte auch wie folgt in einer Zeile geschrieben werden können:printf( "Sie haben die Menü-Option %d gewählt", menue_option_einlesen() );
Wenn man aber das Programm erweitern und auf die getroffene Auswahl reagieren
möchte, benötigt man den von menue_option_einlesen()
zurückgegebenen Wert.
Deshalb ist es ratsam, diesen Wert einer Variablen (wie option
) zuzuweisen.
Die Zeilen 18 bis 37 enthalten die Funktion menue_option_einlesen()
. Diese Funktion
gibt auf dem Bildschirm ein Menü aus (Zeilen 24 bis 30) und nimmt den Zahlencode
der getroffenen Auswahl entgegen. Da Sie ein Menü mindestens einmal anzeigen
müssen, um eine Antwort zu erhalten, bietet sich hier die Verwendung einer
do...while
-Schleife an. In unserem Programm wird das Menü so oft angezeigt, bis
eine gültige Auswahl getroffen wurde. Zeile 34 enthält den while
-Teil der do...while
-
Anweisung und wertet den eingegebenen Wert für die Menüauswahl (sinnvollerweise
auswahl
genannt) aus. Wenn der eingegebene Wert nicht zwischen 1 und 4 liegt, wird
das Menü erneut angezeigt und der Benutzer zu einer neuen Menüauswahl
aufgefordert. Wird eine gültige Zahl eingegeben, fährt das Programm mit Zeile 36
fort, die den Wert der Variablen auswahl
zurückliefert.
do
{
Anweisung(en);
}while (Bedingung);
Bedingung
ist ein beliebiger gültiger C-Ausdruck, in der Regel ein relationaler
Ausdruck. Wenn Bedingung
als unwahr
(Null) ausgewertet wird, endet die while
-
Anweisung und die Ausführung fährt mit der ersten Anweisung nach der while-
Anweisung fort. Im anderen Fall springt das Programm zurück zu dem do
-Teil und die
C-Anweisung(en) in Anweisung(en)
wird
(werden) ausgeführt
Bei Anweisung(en)
handelt es sich um eine einfache C-Anweisung oder einen Block
von Anweisungen. Diese Anweisungen werden beim ersten Durchlauf der Schleife
und danach so lange, wie Bedingung
wahr ist, ausgeführt.
Die do...while
-Anweisung gehört zu den Schleifen. Mit ihrer Hilfe kann man eine
Anweisung oder einen Anweisungsblock so lange wiederholt ausführen lassen, wie
eine gegebene Bedingung wahr ist (ungleich Null). Im Gegensatz zu einem while
-
Befehl werden die Anweisungen einer do...while
-Schleife mindestens einmal
ausgeführt.
/* Ausgabe erfolgt, auch wenn die Bedingung falsch ist! */
int x = 10;
do
{
printf("\nDer Wert von x ist %d", x );
}while (x != 10);
/* Liest so lange Werte ein, bis die Zahl 99 eingegeben wird */
int nbr;
do
{
scanf("%d", &nbr );
}while (nbr <= 99);
/* Erlaubt die Benutzereingabe von bis zu 10 Integer-Werten */
/* Die Werte werden in einem Array namens wert gespeichert. */
/* Wenn 99 eingegeben wird, stoppt die Schleife. */
int wert[10];
int ctr = 0;
int nbr;
do
{
puts("Geben Sie eine Zahl ein, mit 99 verlassen ");
scanf( "%d", &nbr);
wert[ctr] = nbr;
ctr++;
}while (ctr < 10 && nbr != 99);
Der Begriff verschachtelte Schleife bezieht sich auf eine Schleife, die innerhalb einer anderen Schleife verwendet wird. Sie haben bereits einige Beispiele für verschachtelte Schleifen kennen gelernt. Bezüglich der Verschachtelungstiefe sind Ihnen in C praktisch keine Grenzen gesetzt. Sie müssen nur aufpassen, dass jede innere Schleife komplett von der äußeren Schleife eingeschlossen ist. Schleifen dürfen sich nicht überlappen. Aus diesem Grund ist folgender Code nicht erlaubt:
for ( count = 1; count < 100; count++)
{
do
{
/* die do...while-Schleife */
} /* Ende der for-Schleife */
}while (x != 0);
Wenn die do...while
-Schleife komplett von der for
-Schleife umschlossen ist, gibt es
keine Probleme:
for (count = 1; count < 100; count++)
{
do
{
/* die do...while-Schleife */
}while (x != 0);
} /* Ende der for-Schleife */
Wenn Sie verschachtelte Schleifen verwenden, sollten Sie daran denken, dass
Änderungen in der inneren Schleife unter Umständen Auswirkungen auf die äußere
Schleife haben können. Die innere Schleife kann jedoch auch völlig unabhängig von
den Variablen der äußeren Schleife sein. In unserem Beispiel ist dem allerdings nicht
so. Wenn in dem obigen Beispiel der Wert count
in der inneren do...while
-Schleife
geändert wird, hat das Einfluss darauf, wie oft die äußere for
-Schleife ausgeführt wird.
Einrückungen erhöhen die Lesbarkeit von Code mit verschachtelten Schleifen. Jede Schleifenebene sollte sich von der vorherigen durch Einrückung abheben. Damit machen Sie deutlich, welcher Code zu welcher Schleife gehört.
Nach der heutigen Lektion sind Sie schon fast gerüstet, um selbst richtige C- Programme aufzusetzen.
In C gibt es drei Schleifenanweisungen, die den Programmfluss steuern: for
, while
und do...while
. Jedes dieser Konstrukte lässt Ihr Programm einen Anweisungsblock
in Abhängigkeit von dem aktuellen Wert bestimmter Programmvariablen keinmal,
einmal oder mehrere Male ausführen. Viele Programmieraufgaben lassen sich durch
die wiederholte Ausführung, wie sie durch diese Schleifenanweisungen möglich sind,
elegant lösen.
Auch wenn sich alle drei Anweisungen auf das gleiche Problem anwenden lassen,
unterscheiden sie sich doch durch besondere Eigenheiten. Bei der for
-Anweisung
können Sie in einem Befehl initialisieren, auswerten und inkrementieren. Die while
-
Anweisung wird ausgeführt, solange eine Bedingung wahr ist, und die do...while
-
Anweisung führt ihre Anweisungen mindestens einmal aus und anschließend so lange,
bis die Bedingung zu unwahr
ausgewertet wird.
Unter Verschachtelung versteht man die Unterbringung eines Befehls innerhalb eines
anderen. In C können alle Befehle verschachtelt werden. Am Tag 3 habe ich Ihnen
bereits gezeigt, wie Sie die if
-Anweisung verschachteln. Heute wurden die for
-, die
while
- und die do...while
-Anweisungen verschachtelt.
Frage:
Woher weiß ich, welche Anweisung ich zur Programmsteuerung verwenden muss
- for
, while
oder do...while
?
Antwort:
Wenn Sie sich die einzelnen Syntaxbeispiele anschauen, werden Sie
feststellen, dass man mit allen dreien ein Schleifenproblem lösen kann. Jede
Anweisung hat jedoch so ihre Eigenheiten. Die for
-Anweisung eignet sich am
besten, wenn Sie wissen, dass Sie in Ihrer Schleife initialisieren und
inkrementieren müssen. Wenn Sie lediglich eine Bedingung abfragen und
keine bestimmte Anzahl von Schleifeniterationen durchführen wollen, ist
while
zu empfehlen. Und wenn Sie davon ausgehen, dass der zugehörige
Anweisungsblock mindestens einmal ausgeführt werden muss, ist do...while
die beste Wahl. Da alle drei für die meisten Probleme verwendet werden
können, möchte ich Ihnen empfehlen, sich mit allen dreien vertraut zu
machen und dann in jeder Programmsituation individuell abzuwägen, welches
Konstrukt am besten geeignet ist.
Frage:
Wie tief kann ich meine Schleifen verschachteln?
Antwort:
Für die Verschachtelungstiefe sind Ihnen keine Grenzen gesetzt. Wenn Ihr
Programm mehr als zwei Verschachtelungsebenen benötigt, sollten Sie
überlegen, ob Sie nicht besser eine Funktion verwenden. Vielleicht stellen Sie
fest, dass die vielen geschweiften Klammern das Lesen des Codes erschweren
- dann könnte eine Funktion Abhilfe schaffen.
Frage:
Kann ich unterschiedliche Schleifenbefehle verschachteln?
Antwort:
Sie können if
, for
, while
, do...while
oder irgendwelche anderen Befehle
verschachteln. Sie werden bald feststellen, dass viele Programme, die Sie
schreiben wollen, das Verschachteln von zumindest einigen dieser Befehl
erforderlich machen.
Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, sowie Übungen, die Sie anregen sollen, das Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Die Lösungen zu den Fragen und den Übungen finden Sie in Anhang C.
for
- und einer while
-Anweisung?
while
- und einer do...while
-
Anweisung?
while
-Anweisung verwenden und mit dieser die
gleichen Ergebnisse erzielen kann wie mit einer for
-Anweisung?
while
-Anweisung in einer do...while
-Anweisung verschachtelt
werden?
for
-Anweisung?
while
-Anweisung?
do...while
-Anweisung?
long
enthält.
x
, nachdem die folgende Anweisung ausgeführt wurde?
for (x = 0; x < 100, x++) ;
ctr
, nachdem die folgende Anweisung ausgeführt wurde?
for (ctr = 2; ctr < 10; ctr += 3) ;
X
gibt der folgende Code aus?
for (x = 0; x < 10; x++)
for (y = 5; y > 0; y - )
puts("X");
for
-Anweisung, die in Dreierschritten von 1 bis 100 zählt.
while
-Anweisung, die in Dreierschritten von 1 bis 100 zählt.
do...while
-Anweisung, die in Dreierschritten von 1 bis 100
zählt.
datensatz = 0;
while (datensatz < 100)
{
printf( "\nDatensatz %d ", datensatz );
printf( "\nNächste Zahl..." );
}
MAXWERTE
ist nicht
das Problem!)
for (zaehler = 1; zaehler < MAXWERTE; zaehler++);
printf("\nZaehler = %d", zaehler );