Beginnen wir mit der Selektion (if/else und switch/case):
if/else
Die einfache Gabelung eines
Programmflusses
in zwei Richtungen erfolgt mittels
if/else-Struktur. Die allgemeine
Syntax lautet:
if
( expression ) statement
bzw. if
( expression ) statement
|
Untersuchen wir ein erstes Beispiel:
if ( i
> 0
)
{
a = b;
c = d;
}
else
{
a = b + 1;
c = d + 1;
}
Hier wird aufgrund des Ausdrucks i>0
eine Entscheidung getroffen.
Ist dieser Ausdruck "wahr", dann wird
der if-Zweig ausgeführt, ist der Ausdruck "falsch",
dann wird der else-Zweig, falls vorhanden,
ausgeführt.
Der else-Zweig ist optional.
Eine if-Kontrollstruktur ohne else könnte z.B. Folgendes sein:
if ( i
> 0
)
{
a = b;
}
Ist der Ausdruck i>0
"wahr" (true), wird der if-Zweig ausgeführt, ansonsten (false)
wird er nicht
ausgeführt.
Man kann die geschweiften Klammern in
diesem einfachen Fall auch weglassen:
if ( i
> 0
) a = b;
Was ist das?
if ( i ) a = b;
Dies ist ein
häufig
anzutreffender Fall, der Anfänger irritieren kann.
Gehen wir logisch
vor. Wenn i ungleich 0 ist, ist der Ausdruck in Klammern "wahr" (true
!= 0; false == 0).
Wenn der Ausdruck
in Klammern wahr ist, wird die Anweisung bzw. der Anweisungsblock im
if-Zweig
ausgeführt.
Wollen wir das Gegenteil, dann schreiben wir:
if ( i == 0 ) a = b;
oder negiert (das Ausrufezeichen ist der NOT-Operator):
if ( !i ) a = b;
Achten Sie
unbedingt
auf das doppelte Gleichheitszeichen, wenn die Prüfung
auf
Gleichheit gemeint ist.
Das einfache Gleichheitszeichen ist der
Zuweisungsoperator.
Was passiert, wenn wir das doppelte Gleichheitszeichen vergessen?
if ( i = 0 ) a = b;
Hier wird i der
Wert
0 zugewiesen. Damit ist i gleich 0, und der Klammerausdruck wird
"unwahr" (false == 0).
Also wird der
if-Zweig
nicht ausgeführt. Das ist genau das Gegenteil dessen, was wir
beabsichtigen.
Solche Fälle
kann der Compiler nicht eindeutig als Fehler erkennen, da der Code
sprachlichkorrekt ist.
Dies ist eine typische "logische" Falle!
Es ist Aufgabe des Programmierers, derartige logische Programmfehler zu vermeiden.
Manche Compiler geben hier auch eine Warnung aus.
Daher gut einprägen:
a == b prüft auf Gleichheit, Ausdruck kann true oder false sein.
a = b weist den Wert der rechten Seite der linken Seite zu, Ausdruck ist immer true.
Es gibt auch noch das eingeschobene Konstrukt else if:
if (...)
{ ...
}
else if (...)
{ ...
}
else
{ ...
}
Nachfolgend ein einfaches
Beispiel:
#include
<iostream>
#include <string>
#include <conio.h>
using namespace std;
int main ()
{
string name, ort, gefuehl;
int alter;
cout << "Hi, wie heisst Du?" << endl;
cin >> name;
cout << "Ah, hi " << name << ", wie alt
bist Du?" << endl;
cin >> alter;
cout << "Oh, " << alter << " Jahre alt
bist Du schon, und woher kommst Du?" << endl;
cin >> ort;
cout << "Aus " << ort << " kommst Du
also " << name << ", und wie geht's Dir gerade so?"
<< endl;
cin >> gefuehl;
if
(gefuehl
== "gut")
{
cout << "Fein, dass es Dir gut geht."
<< endl;
}
else if (gefuehl
==
"schlecht")
{
cout << "Hm, was bedrueckt Dich denn?"
<< endl;
}
else
{
cout << "Ach so." << endl;
}
getch();
};
switch/case
Während if/else optimal für eine Gabelung in zwei Richtungen ausgelegt ist, realisiert man eine Auswahl aus einer Vielfalt von Möglichkeiten entweder mit einer geschachtelten if/else-Struktur oder besser mit einer switch/case-Kontrollstruktur:
Die allgemeine Syntax lautet:
switch
( expression )
{ case const1: statement; break; case const2: statement; break; case const3: statement; break; ... ... default: statement } |
Der Ausdruck in
der
Klammer nach switch muß von ganzzahligem Typ sein.
const1, const2,
const3 stehen hier für vom Typ her ganzzahlige und voneinander
verschiedene
Konstanten.
Stimmt der Wert
von expression mit einer Konstante hinter dem case-Label überein,
so wird statement ausgeführt.
Die optionale
break-Sprunganweisung
sorgt dafür, dass die switch-Kontrollstruktur verlassen wird.
Existiert keine
Übereinstimmung mit einer Konstanten nach case, so wird die
optionale
default-Anweisung ausgeführt.
Eine bekannte
Anwendung
der switch-Kontrollstruktur ist die Auswertung von Nachrichten bei der
Win-API-Programmierung.
Nachfolgend ein
minimales Beispiel:
switch
(message)
{
case
WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
TextOut (hdc, ...);
EndPaint (hwnd, &ps);
return 0;
case
WM_DESTROY:
PostQuitMessage (0);
return 0;
}
Der Abbruch
erfolgt
hier nicht durch break, sondern durch return 0.
Die
Windows-Nachrichten
sind von ganzzahligem Typ.
Man kann einer
Anweisung
auch mehrere case-Labels zuordnen.
Nehmen wir z.B.
an, dass man sowohl Klein- als auch Großschreibung bei a, b, c
...
abfragen will,
so kann man
case-Labels
kombinieren:
switch (
expression
)
{
case
'a':
case
'A':
statement_a;
break;
case
'b':
case
'B':
statement_b;
break;
case
'c':
case
'C':
statement_c;
break;
...
...
default:
statement_def;
}