Keuzes

In het leven zullen we keuzes moeten maken. Bij het programmeren is dat al niet anders.

In Pascal is er eigenlijk maar één manier om een keuze te maken, en dat is d.m.v een if-then-(else-)constructie.
Een afgeleide constructie is de case-constructie. Daarover later meer.

Aan de hand van een (onnozel) voorbeeld gaan we e.e.a. verduidelijken.
We gaan een programma schrijven dat om een hoek (in graden) vraagt en vervolgens de soort bepaalt:
De soorten en hun voorwaarden zijn:

Soort Voorwaarde
scherp (hoek > 0 en) hoek < 90
recht hoek = 90
stomp hoek > 90 en hoek < 180
gestrekt hoek = 180
overstrekt hoek > 180

Hier komt het programma:

program p5_1;

var
  hoek: integer;
  soort: string[40];

begin
  write(‘Geef een hoek in graden: ‘);
  readln(hoek);
  if hoek < 90 then
    soort := ‘scherp’;
  if hoek = 90 then
    soort := ‘recht’;
  if (hoek > 90) and (hoek < 180) then
    soort := ‘stomp’;
  if hoek = 180 then
    soort := ‘gestrekt’;
  if hoek > 180 then
    soort := ‘overstrekt’;
  writeln(‘Een hoek van ‘,hoek,’ graden is ‘,soort,’.’);
end.

De constructie is dus if [voorwaarde] then [statement] else [statement], waarbij de [voorwaarde] dus ook uit meerdere voorwaarden kan bestaan.
Kijk maar naar de regel: if (hoek > 90) and (hoek < 180) then, waarbij we moeten testen of de hoek tussen de 90 en 180 graden inligt.
Het is in dit geval zeer noodzakelijk om de twee voorwaarden tussen haken te zetten, omdat de and-operator (en hetzelfde geldt voor de or-operator) een hogere prioriteit heeft dan de groter-dan- en kleiner-dan-testen.
In voornoemde regel wordt nu eerst gekeken of de hoek groter is dan 90 en vervolgens of de hoek kleiner is dan 180. Als aan beide is voldaan dan pas is aan de gehele voorwaarde voldaan.
Zouden we de haken weglaten dan krijgen we het volgende: if hoek > 90 and hoek < 180 then, en nu zal Pascal dat als volgt duiden:
if hoek > (90 and hoek) < 180 then, waarbij dus nu eerst de voorwaarde 90 and hoek wordt ge-evalueerd, wat tot een foutmelding zal leiden, omdat er appels met peren wordt vergeleken. Overigens is de compiler al zo slim om te zien dat de laatste constructie niet juist is.

Een andere opmerking die ik hier moet plaatsen is waarom de constructie if 90 < hoek < 180 then niet is toegestaan. Het antwoord hierop is dat het moeilijk voor de compiler is in te zien dat beide voorwaarden (> 90 en < 180) bij één en dezelfde variabele horen. Wat wij mensen wiskundig volkomen logisch vinden is voor de compiler lang niet expliciet genoeg, omdat is toegestaan dat een voorwaarde complex mag zijn. Dat betekent dus ook dat er meerdere variabelen bij de voorwaarde betrokken mogen zijn.

Het bovenstaande programma kunnen we iets efficiënter coderen met behulp van een case-constructie:

program p5_2;

var
  hoek: integer;
  soort: string[40];

begin
  write(‘Geef een hoek in graden: ‘);
  readln(hoek);
  case hoek of
    0..89: soort := ‘scherp’;
    90: soort := ‘recht’;
    91..179: soort := ‘stomp’;
    180: soort := ‘gestrekt’;
    else soort := ‘overstrekt’;
  end;
  writeln(‘Een hoek van ‘,hoek,’ graden is ‘,soort,’.’);
end.

Een case-constructie kan alleen worden gebruikt als er slechts 1 variabele in het spel is, en de waardes die de variabele kan aannemen opsombaar zijn.
De case-constructie gaat dus als volgt:
case [variabele] of
[waarde1]: [opdracht];
[waarde2]..[waarde3]: [opdracht];
[waarde4], [waarde5], [waarde6]: [opdracht];
else [opdracht];
end;
 ,
waarbij [waarde1] een enkelvoudige waarde is, [waarde2]..[waarde3] alle waarden tussen [waarde2] en [waarde3] betreft, waarbij [waarde2] en [waarde3] meedoen, [waarde4], [waarde5], [waarde6] betekent [waarde4] of [waarde5] of [waarde6]. Indien geen van de waarden wordt aangenomen wordt de opdracht na else uitgevoerd. De else is niet verplicht.

Een if-constructie mag worden “genest”, dat betekent dat er binnen een if-constructie weer een if-constructie mag staan, en zo voort.
Laten we maar eens naar het volgende (totaal onzinnige) voorbeeld kijken:
Laat twee getallen geven. Als beide even zijn dan is het een super-duo. Als de eerste even is (de tweede dus niet) dan bijna-super-duo, en anders geen super-duo.

program p5_3;

var
  getal1, getal2: integer;

begin
  write(‘Geef eerste getal: ‘);
  readln(getal1);
  write(‘Geef tweede getal: ‘);
  readln(getal2);
  if getal1 mod 2 = 0 then
    if getal2 mod 2 = 0 then
      writeln(‘Super-duo.’)
    else
      writeln(‘Bijna …’)
  else
    writeln(‘Helaas …’);
end.

Aleen door het goed inspringen is het duidelijk welke else bij welke if hoort, om nog maar eens het belang van inspringen te onderstrepen.
Als je goed naar de code kijkt, valt nog iets op. Je ziet dat de regel voorafgaand aan de regel met else niet wordt afgesloten met een punt-komma (;). Je zou nu kunnen denken dat er wordt gezondigd tegen de (primaire) regels van Pascal. Dit is echter niet het geval. Het heeft te maken met de syntax van de if-constructie:
if [voorwaarde] then [opdracht] else [opdracht], waarbij je ziet dat er voor de else, na de eerste [opdracht], geen punt-komma staat. Vandaar.

Compound-statement ofwel samengestelde opdracht.

Het wordt nu tijd om te kijken naar de zogenaamde samengestelde opdracht. In de syntax van if (zie hierboven) staat [opdracht], wat impliceert dat het hier om 1 opdracht gaat. Dat is ook zo! In de syntax. Maar een [opdracht] in Pascal-syntax betekent zoveel als ofwel 1 statement ofwel een compound-statement (=samengestelde opdracht), die als 1 statement kan worden opgevat.
Een compound-statement maak je in Pascal door een aantal statements tussen begin en end te zetten. Alle statements tussen begin en end zijn een compound-statement, ofwel samengestelde opdracht.
Ter illustratie het volgende voorbeeld: in het programma wordt gevraagd naar je naam, en geslacht. Als je een man bent wordt ook je leeftijd gevraagd (dit vraag je nu eenmaal niet aan een vrouw). Hierna kan het met deze gegevens iets worden gedaan, wat in dit voorbeeld echter buiten beschouwing blijft.

program p5_4;

var
  Naam: string[40];
  Geslacht: char;
  Leeftijd: integer;

begin
  write(‘Geef uw naam: ‘);
  readln(Naam);
  write(‘Bent u een man (M) of een vrouw (V): ‘);
  readln(Geslacht);
  if (Geslacht = ‘M’) or (Geslacht = ‘m’) then
    begin
      write(‘Geef uw leeftijd: ‘);
      readln(Leeftijd);
    end;
  writeln;
  writeln(‘Doe iets met deze gegevens …’);
end.

[Variabelen (1)] <– –> [Lussen]