Programmieren in C++: Einführung
Dieses Buch ist unter einer Creative Commons-Lizenz lizensiert.
Verzweigungen ermöglichen in Abhängigkeit einer Bedingung eine unterschiedliche Code-Ausführung. Verzweigungen werden in C++ mit Hilfe des Schlüsselwortes if
erstellt. Betrachten Sie folgendes Beispiel.
#include <iostream> int main() { int i; std::cout << "Geben Sie eine Zahl ein: " << std::flush; std::cin >> i; if (i < 100) { std::cout << "Sie haben eine Zahl kleiner als 100 eingegeben." << std::endl; } }
Der Anwender wird aufgefordert, eine Zahl einzugeben. Diese wird über die Standardeingabe eingelesen und in der Variablen i gespeichert. Nun kommt die if
-Kontrollstruktur ins Spiel. Hinter dem Schlüsselwort if
wird innerhalb einer runden Klammer eine Bedingung überprüft. Derartige Überprüfungen finden normalerweise mit Hilfe von Vergleichsoperatoren statt. In diesem Fall wird überprüft, ob die in i gespeicherte Zahl kleiner als 100 ist. Ist dies der Fall - wird also von der Bedingung true
als Ergebnis zurückgegeben - so wird der Anweisungsblock zwischen den geschweiften Klammern hinter dem if
-Schlüsselwort ausgeführt.
Der grundsätzliche Aufbau einer if
-Kontrollstruktur sieht wie folgt aus.
if (BEDINGUNG) { ANWEISUNGSBLOCK }
Die Anweisungen im Anweisungsblock werden genau dann und genau einmal ausgeführt, wenn die zu überprüfende Bedingung true
ergibt. Ergibt die zu überprüfende Bedingung false
, wird der Anweisungsblock übersprungen, und die Programmausführung setzt hinter dem Anweisungsblock fort.
#include <iostream> int main() { int i; std::cout << "Geben Sie eine Zahl ein: " << std::flush; std::cin >> i; if (i < 100) { std::cout << "Sie haben eine Zahl kleiner als 100 eingegeben." << std::endl; } else { std::cout << "Sie haben eine Zahl groesser gleich 100 eingegeben." << std::endl; } }
Eine if
-Kontrollstruktur lässt sich zu einer if
-else
-Kontrollstruktur ausbauen. Hinter dem if
-Anweisungsblock wird ein Schlüsselwort else
gesetzt, dem wiederum ein Anweisungsblock in geschweiften Klammern folgt. Der Anweisungsblock hinter else
wird genau dann und genau einmal ausgeführt, wenn die zu überprüfende Bedingung hinter dem vorherigen if
im Ergebnis false
ergab.
Der schematische Aufbau einer if
-else
-Kontrollstruktur sieht demnach wie folgt aus.
if (BEDINGUNG) { ANWEISUNGSBLOCK } else { ANWEISUNGSBLOCK }
Der else
-Block ist, wie Sie nun wissen, optional und kann jederzeit weggelassen werden.
Es ist möglich, if
-else
-Kontrollstrukturen zu verschachteln. Betrachten Sie folgendes Beispiel.
#include <iostream> int main() { int i; std::cout << "Geben Sie eine Zahl ein: " << std::flush; std::cin >> i; if (i < 100) { std::cout << "Sie haben eine Zahl kleiner als 100 eingegeben." << std::endl; } else { if (i < 200) { std::cout << "Sie haben eine Zahl kleiner als 200 eingegeben." << std::endl; } else { std::cout << "Sie haben eine Zahl groesser gleich 200 eingegeben." << std::endl; } } }
Innerhalb des else
-Anweisungsblockes befindet sich eine zweite if
-else
-Kontrollstruktur. Diese überprüft, ob die eingegebene Zahl in i kleiner als 200 ist und zeigt, wenn dies der Fall ist, eine entsprechende Meldung auf dem Bildschirm an. Andernfalls wird die Meldung ausgegeben, dass die eingegebene Zahl größer oder gleich 200 ist.
Die Verschachtelung von if
-else
-Kontrollstrukturen kann recht häufig notwendig sein. Eine kompaktere Schreibweise des Codes ist daher vorzuziehen.
#include <iostream> int main() { int i; std::cout << "Geben Sie eine Zahl ein: " << std::flush; std::cin >> i; if (i < 100) { std::cout << "Sie haben eine Zahl kleiner als 100 eingegeben." << std::endl; } else if (i < 200) { std::cout << "Sie haben eine Zahl kleiner als 200 eingegeben." << std::endl; } else { std::cout << "Sie haben eine Zahl groesser gleich 200 eingegeben." << std::endl; } }
Das Beispiel funktioniert genauso wie vorher. Es wird zuerst überprüft, ob die eingegebene Zahl kleiner als 100 ist. Wenn nicht, wird überprüft, ob die eingegebene Zahl kleiner als 200 ist. Ist dies auch nicht der Fall, werden die Anweisungen hinter else
ausgeführt.
Innerhalb einer Verzweigung können beliebig viele else if
-Überprüfungen stattfinden. Beginnen muss eine Verzweigung jedoch immer mit if
. Der else
-Block ist wie bereits erwähnt optional und kann jederzeit weggelassen werden. Wenn er jedoch verwendet wird, darf hinter else
keine nochmalige Überprüfung einer Bedingung mit else if
erfolgen.
Wenn der Anweisungsblock nur aus einer einzigen Anweisung besteht, können Sie die geschweiften Klammern weglassen. Gerade Anfängern in C++ wird jedoch empfohlen, immer die geschweiften Klammern zu setzen, um nicht versehentlich Anweisungen außerhalb eines if
-, else if
- oder else
-Anweisungsblockes zu schreiben.
Eine besondere Form der if
-else
-Kontrollstruktur ist die switch
-case
-Anweisung.
#include <iostream> int main() { int i; std::cout << "Geben Sie eine Zahl von 1 bis 3 ein: " << std::flush; std::cin >> i; switch (i) { case 1: { std::cout << "Sie haben 1 eingegeben." << std::endl; break; } case 2: { std::cout << "Sie haben 2 eingegeben." << std::endl; break; } case 3: { std::cout << "Sie haben 3 eingegeben." << std::endl; break; } default: { std::cout << "Sie haben keine Zahl von 1 bis 3 eingegeben." << std::endl; break; } } }
Der switch
-case
-Anweisung wird hinter dem Schlüsselwort switch
in runden Klammern eine Variable übergeben. Diese Variable - und das ist eine große Beschränkung von switch
-case
-Anweisungen - muss von einem intrinsischen Datentyp sein. Es darf sich hierbei auch um kein Array handeln.
Hinter der runden Klammer, die tatsächlich nur eine Variable enthält und keine Bedingung, folgt der Anweisungsblock, der wie gewöhnlich zwischen zwei geschweiften Klammern steht. Innerhalb dieses Anweisungsblocks stehen nun mehrere case
-Anweisungen. Hinter dem Schlüsselwort case
wird ein Wert angegeben, auf den die Variable überprüft werden soll, die in Klammern hinter switch
angegeben ist. Hinter dem Wert folgt ein Doppelpunkt.
Indem mehrere case
-Schlüsselwörter mit unterschiedlichen Werten innerhalb des Anweisungsblocks der switch
-case
-Anweisung angegeben werden, kann die Variable in Klammern auf mehrere Werte hin überprüft werden. Letztendlich entspricht dies nichts anderem als einer if
-else
-Kontrollstruktur, die in mehreren else if
-Anweisungen eine Variable auf Gleichheit mit unterschiedlichen Werten überprüft.
Hinter dem Doppelpunkt einer case
-Anweisung folgt wiederum ein Anweisungsblock. Es können die geschweiften Klammern in diesem Fall auch weggelassen und die Anweisungen direkt untereinander geschrieben werden. Der Anweisungsblock wird nämlich nicht durch eine geschlossene geschweifte Klammer beendet, sondern erst durch das Schlüsselwort break
. Wenn Sie das Schlüsselwort break
vergessen, wird am Ende eines Anweisungsblockes hinter einem case
der darauffolgende Anweisungsblock hinter dem nächsten case
durchlaufen. Dies kann ab und zu sinnvoll sein, handelt sich aber oft um einen Programmierfehler.
Trifft die Code-Ausführung auf break
, wird die switch
-case
-Kontrollstruktur abgebrochen, und die Programmausführung setzt hinter der Kontrollstruktur fort.
Innerhalb einer switch
-case
-Kontrollstruktur beginnen normalerweise alle Zweige mit einem case
-Schlüsselwort. Sie können jedoch auch mit dem Schlüsselwort default
einen eigenen Abschnitt einleiten. Hinter default
wird direkt der Doppelpunkt angegeben. Der Anweisungsblock hinter default
wird immer dann ausgeführt, wenn kein case
zutreffend war. default
entspricht also dem else
innerhalb einer if
-else
-Kontrollstruktur. Ebenso wie der else
-Anweisungsblock ist auch der default
-Anweisungsblock optional.
Möchten Sie einen Anweisungsblock ausführen, wenn verschiedene Werte zutreffen, können Sie folgendes schreiben.
#include <iostream> int main() { int i; std::cout << "Geben Sie eine Zahl von 1 bis 3 ein: " << std::flush; std::cin >> i; switch (i) { case 1: case 3: { std::cout << "Sie haben eine ungerade Zahl eingegeben." << std::endl; break; } case 2: { std::cout << "Sie haben eine gerade Zahl eingegeben." << std::endl; break; } default: { std::cout << "Sie haben keine Zahl von 1 bis 3 eingegeben." << std::endl; break; } } }
Die Meldung, dass eine ungerade Zahl eingegeben wurde, wird nun ausgegeben, wenn die Zahl 1 oder die Zahl 3 vom Anwender eingegeben wurde. Indem hinter case 1:
nämlich kein break
angegeben wird, wird der darauffolgende Anweisungsblock hinter case 3:
ausgeführt - bis die Programmausführung auf ein break
trifft und die Kontrollstruktur abbricht.
Während mit Hilfe einer if
-Kontrollstruktur unterschiedlicher Code genau einmal ausgeführt werden kann, kann mit Schleifen Code in Abhängigkeit einer Bedingung wiederholt ausgeführt werden. C++ stellt verschiedene Schleifentypen zur Verfügung.
#include <iostream> int main() { int i; std::cout << "Geben Sie eine Zahl groesser gleich 100 ein: " << std::flush; std::cin >> i; while (i < 100) { std::cout << "Geben Sie eine Zahl groesser gleich 100 ein: " << std::flush; std::cin >> i; } }
Eine while
-Schleife ist ähnlich wie eine if
-Kontrollstruktur aufgebaut: Zuerst kommt das Schlüsselwort, in diesem Fall while
, danach wird in runden Klammern eine Bedingung überprüft, dahinter folgt zwischen geschweiften Klammern ein Anweisungsblock. Abhängig von der Bedingung wird der Anweisungsblock ausgeführt, oder aber die Code-Ausführung setzt hinter dem Anweisungsblock fort.
Im Gegensatz zum if
wird jedoch nach einem Durchlauf des Anweisungsblocks die Bedingung in runden Klammern erneut überprüft. Ist sie wieder true
, wird der Anweisungsblock nochmal durchlaufen. Auch nach diesem Durchlauf findet erneut eine Überprüfung der Bedingung statt mit eventuell anschließendem erneuten Durchlauf des Anweisungsblocks. Dieses Spielchen wiederholt sich solange, bis die zu überprüfende Bedingung false
ergibt. Erst dann wird der Anweisungsblock übersprungen und das Programm danach fortgesetzt.
#include <iostream> int main() { int i; do { std::cout << "Geben Sie eine Zahl groesser gleich 100 ein: " << std::flush; std::cin >> i; } while (i < 100); }
Wenn Sie sich das Beispiel eben genau angesehen haben, haben Sie festgestellt, dass zwei Zeilen zweimal angegeben waren - einmal vor der Schleife, einmal innerhalb der Schleife. Wenn Sie anstatt einer while
-Schleife eine do
-while
-Schleife verwenden, können Sie wie im obigen Beispiel Ihren Code vereinfachen.
Im Gegensatz zu einer while
-Schleife findet bei einer do
-while
-Schleife die Überprüfung der Bedingung am Ende eines Schleifendurchgangs statt. Das bedeutet, dass der Anweisungsblock der Schleife auf alle Fälle einmal ausgeführt wird. Erst nach dieser einmaligen Ausführung wird entschieden, ob die Schleife nochmal durchlaufen werden muss. Während in einer while
-Schleife zuerst die Bedingung und dann die Schleife ausgeführt wird, wird in einer do
-while
-Schleife zuerst die Schleife durchlaufen und dann die Bedingung überprüft.
Beachten Sie, dass in einer do
-while
-Schleife hinter der Überprüfung der Bedingung ein Semikolon gesetzt werden muss.
#include <iostream> int main() { int i; for (int i = 0; i < 3; ++i) { std::cout << "Geben Sie eine Zahl ein: " << std::flush; std::cin >> i; } }
Der dritte Schleifentyp, der in C++ verwendet werden kann, ist eine Zählschleife. Sie wird for
-Schleife genannt.
Die for
-Schleife ist ähnlich aufgebaut wie die while
-Schleife: Zuerst wird das Schlüsselwort gesetzt, dann folgt eine runde Klammer, danach folgt der Anweisungsblock der Schleife. Im Gegensatz zur while
-Schleife besteht die runde Klammer jedoch in einer for
-Schleife nicht mehr nur aus der Überprüfung einer Bedingung, sondern aus drei verschiedenen Bereichen.
Eine for
-Schleife unterteilt die runde Klammer in genau drei Bereiche. Zur Abgrenzung der Bereiche werden Semikolons gesetzt. Der erste Bereich - von der geöffneten runden Klammer zum ersten Semikolon - ist der Initialisierungsbereich. Der zweite Bereich - vom ersten Semikolon zum zweiten Semikolon - ist die Schleifenbedingung. Der dritte Bereich - vom zweiten Semikolon zur geschlossenen runden Klammer - ist die Wertänderung.
Die schematische Darstellung der for
-Schleife sieht demnach wie folgt aus.
for (INITIALISIERUNG; BEDINGUNG; WERTÄNDERUNG) { ANWEISUNGSBLOCK }
Trifft die Programmausführung auf eine for
-Schleife, wird zuallererst der Initialisierungsbereich ausgeführt. Für gewöhnlich wird hier - daher der Name - eine Variable initialisiert, also auf einen bestimmten Wert gesetzt. Sie können hier auf eine bereits bestehende Variable zurückgreifen oder aber auch eine neue Variable definieren.
Ist der Initialisierungsbereich ausgeführt worden, wird die Bedingung überprüft. Diese besteht wie gewohnt meist aus einem Vergleich zweier Werte oder Variablen. Ist die Bedingung wahr - wird also das Ergebnis true
zurückgegeben - wird der Anweisungsblock der Schleife ausgeführt. Ist die Bedingung falsch, wird der Anweisungsblock ausgelassen, und die Programmausführung setzt hinter der for
-Schleife fort.
Wenn die Bedingung wahr war und der Anweisungsblock einmal ausgeführt wurde, wird anschließend der dritte Bereich in den runden Klammern der for
-Schleife ausgeführt - die Wertänderung. Hier wird normalerweise die Variable, die im Initialisierungsbereich auf einen bestimmten Wert gesetzt wurde, in- oder dekrementiert. An dieser Stelle kommt daher häufig der Inkrement- oder Dekrement-Operator zum Einsatz.
Nachdem die Wertänderung vorgenommen wurde, wird wieder die Bedingung im Schleifenkopf überprüft. Ist sie immer noch wahr, wird der Anweisungsblock erneut ausgeführt. Ist sie falsch, wird die Schleife beendet, und die Programmausführung setzt hinter der Schleife fort.
Die for
-Schleife wird normalerweise dann eingesetzt, wenn mehr oder weniger klar ist, wie oft der Anweisungsblock ausgeführt werden muss. Bei der while
- und do
-while
-Schleife ist das normalerweise nicht bekannt, so dass in diesem Fall auch keine Variable die Anzahl der Schleifendurchläufe mitzählt, sondern lediglich eine Bedingung überprüft wird. Dennoch lassen sich die Schleifen beliebig austauschen. Den richtigen Schleifentyp für bestimmte Programmiersituationen gibt es nicht.
In C++ stehen zwei Schlüsselwörter zur Verfügung, um eine laufende Code-Ausführung abzubrechen oder neu zu starten. Ein Schlüsselwort haben Sie bereits kennengelernt: break
.
Mit break
können nicht nur switch
-case
-Kontrollstrukturen beendet werden, sondern auch alle Schleifentypen. Betrachten Sie folgendes Beispiel.
#include <iostream> int main() { int i; do { std::cout << "Geben Sie eine Zahl groesser gleich 100 ein: " << std::flush; std::cin >> i; if (!std::cin.good()) break; } while (i < 100); }
Der Anwender wird innerhalb einer while
-Schleife aufgefordert, eine Zahl größer oder gleich 100 einzugeben. Die Schleifenbedingung ist erst dann falsch, wenn er dies getan hat. Solange er eine Zahl kleiner als 100 eingibt, wird die Schleife wiederholt ausgeführt.
Nach jeder Eingabe durch den Anwender erfolgt jedoch vor der Überprüfung der Schleifenbedingung innerhalb einer if
-Kontrollstruktur ein Test, ob die Standardeingabe std::cin in einem fehlerfreien Zustand ist. Sie ist dies nicht, wenn keine zum Datentyp der Variable i passende Eingabe durch den Anwender vorgenommen wurde. Gibt der Anwender zum Beispiel keine Zahl ein, sondern drückt einfach Enter, speichert std::cin diesen Fehler. Indem für std::cin die Methode good()
aufgerufen wird, kann überprüft werden, ob der aktuelle Zustand von std::cin fehlerfrei ist. good()
gibt true
oder false
zurück. Wenn im obigen Beispielprogramm false
zurückgegeben wird, ist die Bedindung aufgrund des NICHT-Operators wahr und die Schleife wird mit break
abgebrochen.
Das Schlüsselwort break
darf ausschließlich innerhalb von switch
-case
-Anweisungen und Schleifen verwendet werden. Ansonsten meldet der Compiler einen Fehler.
Das zweite Schlüsselwort, das in die Kategorie Kontrolltransferanweisungen fällt, ist continue
. Betrachen Sie hierzu folgendes Beispiel.
#include <iostream> int main() { int i; while (true) { std::cout << "Geben Sie eine negative Zahl ein: " << std::flush; std::cin >> i; if (i >= 0) continue; break; } }
Das Schlüsselwort continue
darf ausschließlich in Schleifen verwendet werden. Im obigen Beispiel steht es im Anweisungsblock einer while
-Schleife. Diese Schleife ist insofern bemerkenswert, als dass die Bedingung immer true
ergibt - genau das ist nämlich hinter dem Schlüsselwort while
in runden Klammern angegeben. Die Schleife würde demnach unendlich oft ausgeführt werden, wenn es keine andere Abbruchbedingung in der Schleife gibt.
Innerhalb des Anweisungsblocks der Schleife wird der Anwender aufgefordert, eine negative Zahl einzugeben. Die Eingabe wird daraufhin in einer if
-Kontrollstruktur überprüft, ob es sich tatsächlich um eine negative Zahl handelt. Ist dies nicht der Fall, wird der Anweisungsblock hinter if
ausgeführt, der aus dem Schlüsselwort continue
besteht. continue
bewirkt, dass der aktuelle Schleifendurchgang abgebrochen wird. Die Code-Ausführung setzt also am Schleifenbeginn fort, es wird demnach die Bedingung erneut überprüft. Nachdem diese im Beispiel immer true
ergibt, wird die Schleife neugestartet.
Gibt der Anwender hingegen eine negative Zahl ein, wird die Schleife nicht mit continue
neugestartet, sondern mit break
beendet. Somit ist sichergestellt, dass das Programm nicht in einer Endlosschleife hängenbleibt.
Obiges Beispielprogramm demonstriert lediglich die Funktion von continue
. Normalerweise könnte die Funktionalität der Anwendung besser und einfacher implementiert werden, ohne auf continue
und break
zurückgreifen zu müssen. Derartige Kontrolltransferanweisungen sollten nur eingesetzt werden, wenn eine andere Schreibweise das Programm zu kompliziert gestalten würde. In der Praxis werden continue
und break
jedenfalls nicht sehr häufig verwendet.
Sie können die Lösungen zu allen Aufgaben in diesem Buch als ZIP-Datei erwerben.
Entwickeln Sie eine C++-Anwendung, die den Anwender zur Eingabe einer vierstelligen Zahl auffordert. Das Programm soll daraufhin die Quersumme der Zahl mit Hilfe einer Schleife errechnen und das Ergebnis dann auf den Bildschirm ausgeben.
Erweitern Sie das Programm aus Aufgabe 1 derart, dass die Quersummer einer beliebigen Zahl errechnet wird.
Entwickeln Sie eine C++-Anwendung, die den Anwender zur Eingabe einer Zahl auffordert. Das Programm soll daraufhin errechnen, ob es sich um eine Primzahl handelt. Ist dies der Fall, soll eine entsprechende Meldung auf den Bildschirm ausgegeben werden. Andernfalls soll die Meldung ausgegeben werden, dass es sich um keine Primzahl handelt.
Entwickeln Sie eine C++-Anwendung, die die kleinste und größte Zahl von vier vorgegebenen Zahlen ermittelt, die in einem Array vom Typ int
gespeichert sind. Das Programm soll auf den Bildschirm die größte und die kleinste Zahl aus dem Array ausgeben. Testen Sie Ihr Programm, indem Sie im Array verschiedene Zahlen speichern und die größte und kleinste Zahl sich jeweils an verschiedenen Stellen im Array befindet.
Copyright © 2001-2010 Boris Schäling