Die if-Verzweigung wird verwendet, wenn in Abhängigkeit von Bedingungen unterschiedliche Anweisungen auszuführen sind. Sie hat folgende Syntax:
if ([INIT;] AUSDRUCK)
ANWEISUNG1; // IF-Zweig
[else
ANWEISUNG2;] // ELSE-Zweig
Ergibt die Auswertung von AUSDRUCK true, wird die Anweisung ANWEISUNG1 ausgeführt und ansonsten der optionale else-Zweig oder nichts. Zusätzlich kann innerhalb der if-Klammer ein Ausdruck INIT stehen, der vor der Auswertung von AUSDRUCK ausgeführt wird.
AUSDRUCK kann auch aus mehreren Bedingungen bestehen, die mit den entsprechenden Logikoperatoren (&&, || und !) verknüpft werden.
Standardmäßig folgt auf ein if und else nur eine Anweisung. Um mehrere Anweisungen auszuführen, sind die Anweisungen in einen Block {...} einzuschließen.
// Pruefen ob eingelesener Wert kleiner, gleich oder
// groesser Null ist
#include <iostream>
int main()
{
// Einzulesender Wert
short val;
// Wert einlesen und pruefen ob Zahl positiv
std::cout << "Geben Sie bitte eine Integer-Zahl ein: ";
// Alternativ: Zahl einlesen und pruefen in einer Anweisung
// if (std::cin >> val; val>0)
std::cin >> val;
if (val>0)
std::cout << "Zahl ist positiv.\n";
else
{
// Pruefen ob Null eingegeben wurde
if (val == 0)
std::cout << "Sie haben 0 eingegeben.\n";
else
// Es wurde eine negative Zahl eingeben
std::cout << "Zahl ist negativ.\n";
}
}
Eine abgewandelte Form der if-Anweisung stellt der Bedingungsoperator dar, der folgende Syntax besitzt:
erg = (AUSDRUCK1) ? AUSDRUCK2 : AUSDRUCK3;
Liefert die Auswertung des Ausdrucks AUSDRUCK1 als Ergebnis true, wird AUSDRUCK2 ausgewertet und das Ergebnis der Variablen erg zugewiesen. Liefert AUSDRUCK1 dagegen false, wird das Ergebnis von AUSDRUCK3 der Variablen erg zugewiesen.
// Bilden des Absolutbetrags von einem int-Wert
#include <iostream>
#include <format>
int main()
{
// Variablen definieren
int inVal, outVal;
// int-Wert einlesen
std::cout << "Bitte einen Integer-Wert eingeben: ";
std::cin >> inVal;
// Absolutbetrag der Eingabe berechnen
outVal= (inVal<0) ? -inVal : inVal;
// Eingabe und Absolutbetrag ausgeben
std::cout << std::format("Eingabe war: {}, Ausgabe ist: {}\n",inVal,outVal);
}
Nur der Vollständigkeit halber sei an dieser Stelle noch erwähnt, dass C++ auch eine goto-Anweisung kennt. Sie wird hier aber nicht weiter betrachtet, da ein 'sauberes' Programm ohne goto auskommt.
Mithilfe der constexpr if Anweisung können alternativ vom Compiler zu übersetzende Anweisungen in Abhängigkeit von einer Bedingung defniert werden. D.h. der Compiler erzeugt nur dann den entsprechenden Code, wenn die Bedingung erfüllt ist.
if constexpr ([INIT;] BEDINGUNG)
ANWEISUNG1; // if-Zweig
[else
ANWEISUNG2;] // else-Zweig
Die Bedingung muss ein konstanter Ausdruck sein, der ein boolsches Ergebnis liefert. Sehen wir uns dies an einem Beispiel an. Je nach Wert der Konstanten DEBUG_LEVEL sollen während der Entwicklungsphase einer Anwendung verschiedene Ausgaben zur Verfolgung des Programmablaufs ausgegeben werden.
#include <iostream>
// Debug-Level festlegen
const int DEBUG_LEVEL = 1;
int main()
{
if constexpr (DEBUG_LEVEL == 1)
{
std::cout << "Einfache Debug-Ausgabe.\n";
}
if constexpr (DEBUG_LEVEL == 2)
{
std::cout << "Detaillierte Debug-Ausgabe!\n";
}
}
Sollen je nach Inhalt eines ganzzahligen oder char-Ausdrucks mehrere verschiedene Anweisungen durchlaufen werden, wird hierfür die switch-Verzweigung eingesetzt. Sie hat folgende Syntax:
switch ([INIT;] AUSDRUCK)
{
case K1:
AKTION1;
[break;]
...
case Kx:
AKTIONx;
[break;]
[default:
AKTIONy;]
}
Der Ablauf der switch-Verzweigung ist folgender:
Die break-Anweisung innerhalb eines switch-Blocks bewirkt ein unmittelbares Verlassen des Blocks, d.h. nach dem break wird als nächstes die Anweisung ausgeführt, die nach der geschweiften Klammer zu folgt. Ohne break-Anweisung werden alle nach der Einsprungsmarke (case Kx:) folgenden Anweisungen bis zum Ende des switch-Blocks oder bis zum Erreichen eines break ausführt.
Sollen für verschiedene Werte die gleichen Anweisungen ausgeführt werden, können mehrere case-Zweige unmittelbar aufeinanderfolgen. Die Reihenfolge der case-Anweisungen ist dabei beliebig.
#include <iostream>
int main()
{
// Variable fuer die Eingabe definieren
char inVal;
// Buchstaben einlesen
// Das Einlesen erfolgt im INIT-Ausdruck der switch-Anweisung
// Je nach Eingabe wird ein anderer Text ausgegeben, wobei
// nicht nach Klein-/Grossschreibung unterschieden wird
std::cout << "Bitte geben Sie einen Buchstaben ein: ";
switch (std::cin >> inVal; inVal)
{
case 'e':
case 'E':
std::cout << "Sie haben e oder E eingegeben!\n";
break;
case 'a':
case 'A':
std::cout << "Sie haben a oder A eingegeben.\n";
break;
default:
std::cout << "Sie haben weder ein a noch ein e eingegeben.\n";
}
}
Die for-Schleife wird hauptsächlich eingesetzt, wenn bereits vor dem Eintritt in die Schleife die Anzahl der Schleifendurchläufe bekannt ist. Sie hat folgende Syntax:
for (AUSRUCK1; AUSDRUCK2; AUSDRUCK3)
ANWEISUNG;
AUSDRUCK1 wird vor dem Eintritt in die Schleife ausgewertet und initialisiert i.d.R. einen Schleifenzähler. AUSDRUCK2 bestimmt das Abbruchkriterium und ist üblicherweise ein vergleichender Ausdruck. Ergibt die Auswertung von AUSDRUCK2 false, wird die Schleife beendet. AUSDRUCK3 wird nach dem Ausführen der Schleifenaktion ANWEISUNG ausgewertet; er inkrementiert bzw. dekrementiert für gewöhnlich den Schleifenzähler. Alle 3 Ausdrücke sind optional. So erzeugt eine for-Schleife ohne Abbruchkriterium eine Endlosschleife.
Die Schleifenaktion ANWEISUNG besteht standardmäßig ebenfalls aus einer Anweisung. Sollen mehrere Anweisungen in der Schleife ausgeführt werden, sind die Anweisungen in einem Block {...} einzuschließen.
// Berechnung der Fakultaet n! in einer for-Schleife
#include <iostream>
#include <format>
int main()
{
// Einzulesendes Datum
short val;
// Wert einlesen, dessen Faktualtaet berechnet werden soll
std::cout << "Wert eingeben (1...20): ";
std::cin >> val;
// Unzulaessige Eingabe abfangen
if ((val<1) || (val>20))
{
std::cout << "Nur Werte zwischen 1...20 zulaessig!\n";
}
else
{
// Ergebnis vorbelegen
unsigned long res = 1UL;
// Fakultaet berechnen 1*2*3..*val;
for (int index=1; index<=val; index++)
res *= index;
// Und Ergebnis ausgeben
std::cout << std::format("Fakultaet von {} ist {}\n",val,res);
}
}
Die while-Schleife wird in erster Linie eingesetzt, wenn sich die Abbruchbedingung für die Schleife erst während eines Schleifendurchlaufs ergibt. Sie hat folgende Syntax:
while (AUSDRUCK)
ANWEISUNG;
Die Schleife wird solange durchlaufen, wie die Auswertung von AUSDRUCK true ergibt. Und auch hier besteht die Schleifenaktion ANWEISUNG standardmäßig nur aus einer Anweisung. Mehrere Anweisungen sind ebenfalls in einem Block {...} einzuschließen.
// Zahlenraten
// Erraten werden soll eine zufaellige Zahl im Bereich 1..20
// Dabei wird bei jedem Versuch ausgegeben, ob die eingegebene
// Zahl kleiner oder groesser als die gesuchte Zahl ist
// Es sind maximal 4 Versuche erlaubt
#include <iostream>
#include <format>
// Header-Dateien fuer den Zufallszahlengenerator
#include <cstdlib>
#include <ctime>
int main()
{
// Zufallszahlengenerator initialisieren
std::srand(std::time(nullptr));
// Zufallszahl erzeugen und auf den Bereich 1..20 begrenzen
const unsigned int MAXVAL = 20;
unsigned int number = rand()%MAXVAL + 1;
// Merker, ob gesuchte Zahl gefunden wurde
bool found=false;
// Anzahl der maximalen Versuche und der aktuelle Versuch
const unsigned int MAXTRY = 4;
unsigned int shot = 1;
std::cout << std::format("Raten Sie eine Zahl zwischen 1...{}\n"
"Sie haben dazu maximal {} Versuche\n",
MAXVAL,MAXTRY);
// Rateschleife, wird beendet wenn gesuchte Zahl
// gefunden wurde (found=true) oder die maximale
// Anzahl der Rateversuche erreicht ist (MAXTRY>=shot)
while(!found && (MAXTRY >= shot))
{
// Einzulesende Zahl
unsigned int val;
// Zahl einlesen
std::cout << std::format("{}. Versuch: ",shot);
std::cin >> val;
// Eingabe pruefen ob zulaessig
if ((val<1) || (val>MAXVAL))
std::cout << "Eingabe ausserhalb des erlaubten Wertebereichs!\n";
else
{
// Falls Zahl gefunden, Schleife beenden (found=true)
if (val == number)
{
std::cout << "Sie haben die gesuchte Zahl gefunden!\n";
found = true;
}
else
{
// Meldung ausgeben, ob eingegebene Zahl zu klein
// oder zu gross ist
std::cout << "Leider nix. Ihre Zahl war zu ";
if (val < number)
std::cout << "klein.\n";
else
std::cout << "gross.\n";
// Anzahl der Versuche inkrementieren
shot++;
}
}
} // Ende while-Schleife
// Gesuchte Zahl ausgeben falls diese nicht gefunden wurde
if (!found)
std::cout << std::format("Die gesuchte Zahl war {}\n",number);
}
Auch diese Schleife wird zumeist verwendet, wenn sich die Abbruchbedingung erst während eines Schleifendurchlaufs ergibt. Sie hat folgende Syntax:
do
ANWEISUNG;
while (AUSDRUCK);
Auch hier wird die Schleife solange durchlaufen, wie die Auswertung von AUSDRUCK true ergibt und mehrere Anweisungen in der Schleife sind ebenfalls in einem Block {...} einzuschließen.
Der Unterschied zur vorherigen while-Schleife liegt darin, dass die Abbruchbedingung bei der while-Schleife vor dem Eintritt in die Schleife ausgewertet wird, während dies bei der do-while-Schleife erst nach einem Schleifendurchlauf erfolgt.
// Berechnung des gleitenden Mittelwerts von
// einzugebenden int-Daten. Die Eingabe wird
// beendet, wenn eine 0 eingegeben wird.
#include <iostream>
#include <format>
int main()
{
int sum; // Summe der eingegebenen Werte
int count = 0; // Anzahl der eingegebenen Werte
bool done; // Merker fuer Schleifenende
// Einlese-Schleife
do
{
int val; // Einzulesender Wert
std::cout << "Bitte einen Wert eingeben (0=Ende): ";
std::cin >> val;
// Fertig, wenn der Wert 0 eingegeben wurde
done = (val == 0);
// Wenn nicht fertig, Wert aufaddieren und
// Anzahl der Werte inkrementieren
if (!done)
{
sum += val;
count++;
}
} while(!done);
if (count != 0)
std::cout << std::format("Mittelwert: {}\n",sum/count);
else
std::cout << "Sie haben keine Werte eingegeben!\n";
}
Sehen wir uns noch die restlichen zwei Anweisungen an, die bei Schleifen zum Einsatz kommen können.
Die break-Anweisung darf nur innerhalb einer Schleife oder eines case-Zweigs in der switch-Verzweigung stehen. Sie bewirkt das sofortige Verlassen der Schleife bzw. der switch-Verzweigung.
Die continue-Anweisung ist nur innerhalb einer Schleife (for, while, do-while) gültig. Sie bewirkt, dass die restlichen, auf die continue-Anweisung folgenden Anweisungen, übersprungen werden. Die Schleife selbst wird aber nicht beendet. Allerdings sollte ein gut strukturiertes Programm ohne break- oder continue-Anweisungen auskommen, mit Ausnahme des break in der switch-Verzweigung.