Programmierkurs: Delphi: Pascal: Verzweigungen

Aus Wikibooks

In diesem Kapitel wollen wir uns mit Verzweigungen beschäftigen. Dabei geht es darum, den Programmablauf anhand von Bedingungen zu steuern.

If-Abfrage (Wenn-Dann-Sonst)[Bearbeiten]

Aufbau[Bearbeiten]

Bisher hat der Computer auf jede Eingabe in gleicher Art reagiert. Nun wollen wir beispielsweise, dass der Computer nur Hugo begrüßt. Dazu brauchen wir eine so genannte „If-Abfrage“. Dabei überprüft der Computer, ob ein bestimmter Fall wahr (true) oder falsch (false) ist. Die Syntax sieht, da in Pascal ja alles im Englischen steht, so aus:

if Bedingung then Anweisung

Die Bedingung ist dabei eine Verknüpfung von Vergleichen, oder ein einzelner Wahrheitswert. Aber dazu später mehr. Erstmal wollen wir uns dem Vergleichen widmen:

Es gibt in Delphi die folgenden sechs Vergleichsoperatoren:

Operator(en) prüft, ob...
= die beiden Werte gleich sind.
> und < einer der Werte größer ist (bei Strings die Länge).
>= und <= einer der Werte größer oder gleich ist.
<> die beiden Werte unterschiedlich sind.


Tipp:

Die Abfrage a <> b ist dasselbe wie not (a = b)


Einfache if-Abfragen[Bearbeiten]

Nun aber erstmal wieder ein Beispiel, bevor wir zu den Verknüpfungen weitergehen:

Wir wollen jetzt nachsehen, ob Hugo seinen Namen eingegeben hat. Dazu setzen wir vor den Befehl Writeln('Hallo '+Vorname+'! Schoen, dass du mal vorbeischaust.'); die folgende If-Abfrage:

if Vorname = 'Hugo' then

Die Bedingung ist hier wahr, wenn der eingegebene Vorname „Hugo“ ist. Dabei steht Vorname nicht in Apostrophen, da es der Name der Variablen ist. Hugo ist jedoch der Wert, mit dem die Variable verglichen werden soll, so dass hier die Apostrophe zwingend sind.

Das gesamte Programm sieht jetzt also so aus:

program Eingabeerfassung;
  
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
var
  Vorname: string;

begin
  Writeln('Wie heisst du?');
  Readln(Vorname);
  if Vorname = 'Hugo' then
    Writeln('Hallo '+Vorname+'! Schoen, dass du mal vorbeischaust.');
  Readln;
end.

Erweiterte if-Abfragen mit „sonst“[Bearbeiten]

Wer dieses Programm einmal getestet hat, wird festgestellt haben, dass es keine weitere Ausgabe gibt, wenn der eingegebene Name ungleich „Hugo“ ist. Dies wollen wir nun ändern. Dazu erweitern wir unsere Syntax ein klein wenig:

if Bedingung then Anweisung else Anweisung

Die auf else folgende Anweisung wird dann aufgerufen, wenn die Bedingung der if-Abfrage nicht zutrifft (also false ist). Unser so erweitertes Programm sieht nun also in etwa so aus:

program Eingabeerfassung;
  
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
var
  Vorname: string;

begin
  Writeln('Wie heisst du?');
  Readln(Vorname);
  if Vorname = 'Hugo' then
    Writeln('Hallo '+Vorname+'! Schoen, dass du mal vorbeischaust.')
  else
    Writeln('Hallo '+Vorname+'! Du bist zwar nicht Hugo, aber trotzdem willkommen.');
  Readln;
end.

Zusammenhang mit dem Typ Boolean[Bearbeiten]

If-Abfragen hängen eng mit dem Typ Boolean zusammen: So können Booleans den Wahrheitswert der Abfrage speichern, indem ihnen die Bedingung (bzw. das Ergebnis einer Wahrheitsprüfung) „zugewiesen“ wird:

var
  IstHugo: Boolean;
  ...
begin
  ...
  IstHugo := Vorname = 'Hugo';
  ...
end.

Diese Variable kann jetzt wiederum in if-Abfragen verwendet werden:

if IstHugo then
  ...

Für Boolean-Variablen ist also kein Vergleich nötig, da sie bereits einen Wahrheitswert darstellen.

Verknüpfung von Bedingungen[Bearbeiten]

Wollen wir jetzt mehrere Bedingungen gleichzeitig abfragen, wäre es natürlich möglich, mehrere if-Abfragen zu schachteln:

program Eingabeerfassung2;
  
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
var
  Vorname, Nachname: string;
begin
  Writeln('Wie ist dein Vorname?');
  Readln(Vorname);
  Writeln('Wie ist dein Nachname?');
  Readln(Nachname);
  if Vorname = 'Hugo' then
    if Nachname = 'Boss' then
      Writeln('Hallo '+Vorname+' '+Nachname+'! Schoen, dass du mal vorbeischaust.');
  Readln;
end.

Hier fallen aber gleich mehrere Probleme auf:

  • Für komplizierte Abfragen wird dies sehr unübersichtlich
  • Wollten wir eine Nachricht an alle abgeben, die nicht „Hugo Boss“ heißen, müssten wir für jede der if-Abfragen einen eigenen else-Zweig erstellen.

Um diese Probleme zu lösen, wollen wir die beiden Abfragen in eine einzelne umwandeln. Dazu bietet Delphi den and-Operator, mit dem wir zwei Vergleiche mit „und“ verknüpfen können. Alles was wir tun müssen, ist um jeden der Vergleiche Klammern und ein „and“ dazwischen zu setzen:

  ...
  if (Vorname = 'Hugo') and (Nachname = 'Boss') then
    Writeln('Hallo '+Vorname+' '+Nachname+'! Schoen, dass du mal vorbeischaust.')
  else
    Writeln('Hallo '+Vorname+' '+Nachname+'! Du bist zwar nicht Hugo Boss, aber trotzdem willkommen.')
  ...

and ist nicht der einzige Operator:

Operator Funktion
and beide Bedingungen müssen erfüllt sein
or mindestens eine Bedingung muss erfüllt sein
xor genau eine Bedingung muss erfüllt sein
not kehrt das Ergebnis um (Boolean)


Fallunterscheidung (case)[Bearbeiten]

If-Abfragen können schnell unübersichtlich werden, wenn man mehrere Werte unterschiedlich behandeln möchte. Für solche Fälle steht eine mehrfache Verzweigung zur Verfügung, also eine Fallunterscheidung – die Case-Abfrage. Mit ihrer Hilfe wird nur einmal der Wert einer Variablen abgerufen und das Programm springt dann direkt an die Stelle, die für den entsprechenden Wert ausgeführt werden soll. Eine Case-Abfrage ist folgendermaßen aufgebaut:

case <Variable> of
  Wert1:
    <Anweisung>
  Wert2:
    <Anweisung>
  Wert3, Wert4:
    <Anweisung>
  ...
else
  <Anweisung>
end;

Mehrere Anweisungen können in einen begin...end Block eingeschlossen werden.

Sollen bei verschiedenen Werten die gleichen Aktionen ausgeführt werden, können diese Werte mit Kommata von einander getrennt werden. Ebenfalls möglich ist die Angabe eines ganzen Wertebereichs in der Form Wert1..Wert4. Hierbei ist jedoch zu beachten, dass immer nur ein einzelner Wert einer einzelnen Variablen ausgewertet wird. Eine Verknüpfung wie bei der If-Abfrage ist so nicht möglich, dies ginge nur in einer weiteren verschachtelten Case- oder If-Abfrage.

Die Angabe eines else-Abschnitts ist optional. Besitzt die Variable einen Wert, der nicht angegeben wurde, werden die Anweisungen hinter else ausgeführt. Fehlt else, wird die Abfrage ohne weitere Aktionen verlassen.

Ein anderer (großer) Nachteil der Case-Abfrage liegt darin, dass diese nur Aufzählungsdatentypen verarbeiten kann. Der sehr häufig abgefragte Datentyp string kann nicht mit case verwendet werden. Unser obiges Beispiel lässt sich daher nicht auf Case-Abfragen umstellen, wir nehmen also ein neues: Die Auswertung von Zeichen.

var
  Zeichen: Char;

begin
  Write('Geben Sie bitte ein Zeichen ein: ');
  Readln(Zeichen);

  Write('Das Zeichen war ');
  case Zeichen of
    #0..#31:
      Writeln('ein Steuerzeichen.');
    'a'..'z':
      Writeln('ein Kleinbuchstabe.');
    'A'..'Z':
      Writeln('ein Grossbuchstabe.'); 
    '0', '2', '4', '6', '8':
      Writeln('eine gerade Ziffer.');
    '1', '3', '5', '7', '9':
      Writeln('eine ungerade Ziffer.');
    '.':
      Writeln('ein Punkt.');
    ',':
      Writeln('ein Komma.');
  else
    Writeln('eines, auf das ich nicht programmiert bin.');
  end;
  Readln;
end.

Das Programm fordert wieder zur Eingabe auf und erwartet diesmal ein einzelnes Zeichen. Sollte mehr eingegeben werden, „ignoriert“ Readln einfach den Rest. Bei der anschließenden Auswertung springt das Programm nun an die entsprechende Stelle der Case-Abfrage. Ist dort das eingegebene Zeichen nicht aufgelistet, wird der Text unter else ausgegeben.

Zu den Aufzählungstypen zählt neben Ganzzahlen und Zeichen im Übrigen auch Boolean. Solche Variablen können Sie daher auch in einer Case-Abfrage verarbeiten.


Pascal: Input und Output Inhaltsverzeichnis Pascal: Schachtelungen