erstellt von: Dr. Erhard Henkes (e.henkes@gmx.net)  (Stand: 03.11.2003)
 

zurück zur Startseite

C++ - Kontrollstrukturen

Das A und O der Programmierung sind Kontrollstrukturen.
Diese erlauben Verzweigungen und Schleifen.

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
 else 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;
 }
 
 
 
 

zurück zur Startseite