Inhalt
Schleifen:
while-Schleife
do-while-Schleife
for-Schleife
Vorsicht! Endlosschleife
Sprunganweisungen:
break
continue
Übungsaufgaben
In diesem Teil des Tutorials geht es um sehr wichtige Bestandteile einer Programmiersprache – die Schleifen. Eine Schleife erlaubt einen Anweisungsblock mehrmals zu wiederholen bis eine bestimmte Abbruchbedingung erreicht ist.
Durch die while-Schleife wird der Anweisungsblock so lange wiederholt, wie die Bedingung wahr ist.
Funktionsprinzip:
Ablauf einer while-Schleife
Die Syntax:
while( Bedingung ) { // Anweisung(en) }
Ähnlich wie bei bedingten Anweisung gibt es auch bei Schleifen eine kurze Schreibweise, falls nur eine Anweisung ausgeführt werden soll.
while( Bedingung ) // eine Anweisung
Um die Funktionalität besser zu verinnerlichen, gibt es wie immer einen Beispiel zum Thema:
// while-Schleife Beispiel 1. int zaehler = 0; // die schleife wiederholt sich 3-mal while( zaehler < 3 ) { cout << (zaehler+1) <<". Durchlauf."<<endl; zaehler++; }
Zuerst wird überprüft ob der zaehler kleiner als 3 ist. Da beim ersten Durchgang der zaehler auf Null gesetzt wurde, ist die Bedingung wahr und die Anweisungen kann ausgeführt werden. Am Ende der Schleife wird zaehler um eins erhöht.
Der zweite Durchgang sieht ähnlich aus.
Beim dritten Durchgang wird der zaehler auf 3 inkrementiert. Nachdem die Schleife zum dritten Mal durchgelaufen ist, wird die Bedingung auf ihre Gültigkeit überprüft. Die Bedingung sieht folgender Maßen aus: (3 < 3) – das ist ein mathematischer Widerspruch, d.h. die Bedingung ist false. Die Schleife wird beendet und das Programm läuft weiter.
Hier ein weiteres, etwas praktischeres Beispiel:
// while-Schleife Beispiel 2 int alter = 0; cout << "Wie alt sind Sie?"<<endl; cin >> alter; // Programm läuft nur dann weiter, wenn der Benutzer zwischen // 14 und 90 Jahre alt ist (basiert auf dem Vertrauen ^^ ) while( 14 > alter || alter > 90 ) { cout << "Zugang verweigert!" "Nur Personen im Alter von 14 bis 90 " "sind zugelassen." <<endl << "Bitte die Eingabe wiederholen!" <<endl; cin >> alter; }
Die while-Schleife spielt eine große Rolle in der Spieleprogrammierung, den bei einem Spiel müssen viele Aufgaben wie Input, Kollisionsalgorithmen und das Rendern mehrmals pro Sekunde ständig wiederholt werden. Die Angabe Frames/Sekunde ist eigentlich nichts anderes als eine Angabe für die Anzahl der Wiederholungen der Spiel-Schleife(while-Schleife) in einer Sekunde.
Bei einer while-Schleife wird zuerst die Bedingung überprüft und erst dann kommt man vielleicht zum Anweisungsblock. Programmierer sagen: die while-Schleife ist Kopfgesteuert. Im Gegensatz dazu ist die do-while-Schleife Fußgesteuert. Das heißt, dass die Bedingung erst am Ende des Anweisungsblocks überprüft wird. Die Anweisungen werden immer einmal ausgeführt, egal ob die Bedingung wahr oder falsch ist. Ansonsten verhält sich eine do-while Schleife genauso wie eine while-Schleife.
Funktionsprinzip:
Ablauf einer do-while-Schleife
Die Syntax:
do { // Anweisung(en) } while( Bedingung );
Alternative, kurze Syntax, bei einer Anweisung.
do // Anweisung while( Bedingung );
Achten Sie auf das Semikolon am Ende des while-Teils!
Uns bereits bekanntes Beispiel in abgewandelter Form:
// do-while-Schleife Beispiel 1 int zaehler = 0; // die schleife wiederholt sich solange die Bedingung wahr ist do { cout << "Wie alt sind Sie?" <<endl; cin >> alter; } while( 14 > alter || alter > 90 );
do-while-Schleife wird eher selten benutzt, was zum Teil daran liegt, dass jede do-while-Schleife in eine normale while-Schleife umgeschrieben werden kann, indem der ganze Anweisungsblock einfach vor die while-Schleife gesetzt wird.
Als Beispiel nehme ich Beispiel 1 zur while-Schleife und ersetze die while– durch do-while-Schleife.
int zaehler = 0; cout << "Wie alt sind Sie?" <<endl; cin >> alter; // die schleife wiederholt sich solange die Bedingung wahr ist while( 14 > alter || alter > 90 ) { cout << "Wie alt sind Sie?" <<endl; cin >> alter; }
Schauen Sie sich das erste Beispiel für die while-Schleife an. So eine „Zähl-Situation“ kommt in der Programmierung sehr oft vor. Deswegen gibt es eine Schleife, die nicht anderes ist, als eine auf Komfort spezialisierte while-Schleife. Diese Schleife wird auch als Zählschleife bezeichnet.
Die Syntax:
for( Initialisierung; Bedingung; Anweisung_1 ) { // Anweisung(en) }
Alternative,kurze Syntax, bei einer Anweisung.
for( Initialisierung; Bedingung; Anweisung_1 ) // Anweisung
In dem Initialisierungsteil können wir eine Variable anlegen und initialisieren z.B. int zaehler = 0;
Wie man eine Bedingung aufstellt wissen wir bereits z.B. zaehler < 3;
Und als Anweisung kann man irgendeine kurze Anweisung nehmen z.B. zaehler++;
// for-Schleife Beispiel 1 for (int zaehler = 0; zaehler < 3; zaehler++ ) { cout << (zaehler+1) <<". Durchlauf."<<endl; }
Erkennen Sie die Analogie zu dem ersten while-Schlefe-Beispiel? Im Grunde genommen haben wir eine Schleife gebaut, die sich 3-mal wiederholt. Das klappt aber nur deswegen, weil der Initialisierungsvorgang nur beim ersten Durchgang durchgeführt wird. Ansonsten würde der zaehler beim jeden Durchgang immer wieder neu erstellt und mit Null initialisiert. Die Bedingung wäre damit immer wahr und wir hätten eine Endlosschleife (dazu in ein paar Absätzen mehr).
Das ganze Prinzip soll durch eine Grafik verdeutlicht werden.
Ablauf einer for-Schleife
Anstatt immer Zaehler oder counter zu schreiben ist es unter den Programmierern sehr beliebt einfach ein i, k oder j zu verwenden.
Die Initialisierung, Bedingung und Anweisung im Schleifenkopf sind durch ein Semikolon getrennt, doch warum? Man könnte ja auch Komma verwenden, könnte man sich denken. Nein, es geht nicht, weil es für andere Aufgabe bereits reserviert ist. Es nämlich so, dass im Initialisierungsbereich nicht nur eine Initialisierung erfolgen kann, sondern mehrere, die durch ein Komma getrennt werden. Das gleiche gilt auch für den Bedingungs- und Anweisungs-Teil.
Ein schönes Beispiel dazu habe ich von meinem C++ Schullehrer abgeschaut ;)
// for-Schleife Beispiel 2 /* Sie haben ein Anfangskapital zur Verfügung und Sie wollen ein bestimmtes Endkapital erreichen. Wie viele Jahre dauert dies, wenn Sie einen bestimmten Zinssatz erhalten? */ float AnfangsKapital = 10000.0f, EndKapital = 50000.0f; float ZinsSatz = 4.25f/100.0f; // Zinssatz = 4,25% float Geld_Aktuell; int Jahre; for (Jahre = 0, Geld_Aktuell = AnfangsKapital; Geld_Aktuell < EndKapital; Jahre++, Geld_Aktuell = Geld_Aktuell *(1.0+ZinsSatz)) { /* hier nichts zu tun */ } /* Wenn die geschweiften Klammern leer sind, kann man diese auch weglassen und einfach ein Semikolon setzen. */ for (Jahre = 0, Geld_Aktuell = AnfangsKapital; Geld_Aktuell < EndKapital; Jahre++, Geld_Aktuell = Geld_Aktuell *(1.0+ZinsSatz));
Wenn es mehrere Bedingungen existieren, dann müssen auch alle erfüllt sein, damit die Schleife weiter läuft.
Wie jede andere Schleife kann auch die for-Schleife in einander verschachtelt werden.
for-Schleife Beispiel 3 // Malt ein Rechteck aus Os int rechteck_groesse_x = 30; int rechteck_groesse_y = 5; for (int y = 0; y < rechteck_groesse_y; y++) { for (int x = 0; x < rechteck_groesse_x; x++) { cout<<"O"; } cout<<endl; }
Als letztes möchte ich darauf hinweisen, dass die Variablen, die in dem Initialisierungsteil der for-Schleife erstellt wurden nur in dem Anweisungsblock der Schleife verwendet dürfen. So darf die Variable y (in oberem Beispiel) nach dem Verlassen der Schleife nach dem heutigen ISO C++ Standard nicht verwendet werden. Zum Glück wird dies von neuen Compilern erkannt und es wird eine Fehlermeldung ausgegeben.
Als Endlosschleife wird eine Schleifen bezeichnet, die keine Abbruchsbedingung hat und somit nicht beendet werden kann. Als Folge hängt sich das Programm auf.
Dazu ein einige Beipiele:
// Die Bedingung ist immer true // anstatt true kann auch eine beliebige zahl über 0 stehen while ( true ) { // mach etwas }
// Die Bedingung ist immer erfüllt (siehe in Teil 5 "Typische Fehler") int counter = 0; while ( counter < 500 || 100 ) { // mach etwas (mit counter) counter++; }
// hier existiert nicht mal eine Bedingung // exotisch, findet man wohl nicht in der Praxis ^^ for (;;) { // mach etwas }
Man sollte immer darauf achten dass die Bedingung stimmt, damit solche unschönen Sachen nicht den Spaß an der Programmierung verderben.
Die Endlosschleifen sind eigentlich nicht ganz Endlosschleifen. Man kann eine Endlosschleife auch beenden, wenn die Bedingung im Schleifenkopf oder Fuß inkorrekt ist oder sogar fehlt. Das geht durch die Sprunganweisungen.
Das break kennen Sie bereits von der switch-Anweisung. Ganz allgemein gesagt, sorgt der break-Befehl dafür, dass der äußere Anweisungsblock verlassen wird. Als Beispiel soll eine Endlosschleife dienen.
// break - Beispiel while ( true ) { int abbrechen = 0; cout << "Anweisungen ausführen? [nein=0]"<<endl; cin >> abbrechen; if( abbrechen == 0) break; // hier stehen die Anweisungen } // nach break geht's hier weiter
Das gleiche funktioniert auch mit do-while- und for-Schleifen.
Durch den continue-Befehl wird die Schleife nicht verlassen sondern springt zu der Schleifensteuerung.
Dabei werden zwei Fälle unterschieden:
- Fall (while- oder do-while): Alle Anweisungen nach dem continue werden übersprungen und die Schleife wird ab der Bedingung wieder von vorne abgearbeitet.
- Fall (for): Alle Anweisungen nach dem continue werden übersprungen, dann werden die Anwesungen in dem Schleifenkopf ausgeführt (z.B. zaehler++) und schliesslich geht es ab der Bedingung wieder von vorne los.
continue wird dann verwendet, wenn irgendeine Aufgabe nur bei bestimmten Bedingungen durchgeführt werden soll. Doch das gleiche lässt sich genau so leicht mit if-Anweisung realisieren.
// continue - Beispiel cout<<" Findet Zahlen die durch 7 teilbar sind." <<endl; for( int i = 1; i < 200; i++) { // wenn der Rest=0, dann ist die Zahl durch 7 teilbar if(i%7 != 0) continue; cout << i << endl; }
Oberes Beispiel ohne continue:
cout<<" Findet Zahlen die durch 7 teilbar sind." <<endl; for( int i = 1; i < 200; i++) { // wenn der Rest=0, dann ist die Zahl durch 7 teilbar if(i%7 == 0) cout << i << endl; }
Obwohl man continue meistens vermeiden kann, finde ich, dass es manchmal ziemlich nützlich sein kann um den Code übersichtlicher und damit auch lesbarer zu gestalten.
- Was ist erforderlich damit Schleifen richtig funktionieren?
- Wo liegt der Unterschied zwischen while– und do-while-Schleife?
- Erläutern Sie die Funktion der for-Schleife.
- Durch welche Sprunganweisung wird der Anweisungsblock verlassen?
- Schreiben Sie ein Programm, welches alle Primzahlen von 500 bis 700 ausrechnet.
Hinweis: Für Primzahlen gibt es keine Formel. Die Zahl X soll überprüft
werden, ob es sich um eine Primzahl handelt. Dazu müssen alle Zahlen von 0 bis X-1
durchgegangen werden und es muss geschaut werden ob X durch diese Zahl teilbar ist.
Wenn ‚ja‘, dann…
Im Grunde genommen ist es schon die Lösung, man muss es nur in C++ umsetzen.
Und der letzte Tipp: versuchen Sie es mit 2 for-Schleifen.
1 Gedanke zu „C++ Teil 6 – Schleifen und Sprunganweisungen“