In de vorige paragraven hebben we gekeken naar procedures. In deze paragraaf gaan we kijken naar functies.
Het essentiële verschil tussen een procedure en een functie is dat een functie altijd een waarde moet teruggeven.
De syntax voor een functie is als volgt:
function [naam][(parameter-lijst)]: [type];
[var-declaratie(s)]
begin
[statement(s)];
end;
Uiteraard zijn er grote overeenkomsten met de opzet van een procedure. Een functie moet echter van een bepaald type zijn, omdat de functie een waarde retourneerd.
De vraag is hoe een functie een waarde retourneerd. In Pascal gaat dat door de uiteindelijke waarde terug te geven waarde toe te kennen aan de naam van de functie.
Misschien klink dit alles wat abstract, dus laten we maar snel naar een voorbeeld gaan. We gaan kijken naar de procedure telop van program p8_2. Hier gebruikte we een var-parameter s om de som van a en b te retourneren. We gaan deze procedure ombouwen naar een functie:
function telop(a,b: integer): integer;
begin
telop := a + b;
end;
De var-parameter s hebben we niet meer nodig, want de functie telop krijgt nu de waarde van a + b. Dit gebeurt bij de implementatie door a + b toe te kennen aan telop (de naam van de functie).
De aanroep van telop wordt nu ook anders. Daar telop een waarde retourneert moet je die ergens aan toe kennen.
De aanroep wordt nu: som := telop(getal1,getal2);.
Een bijkomend voordeel van functies is dat je ze mag nesten, iets wat bij procedures onmogelijk is.
Met onze functie telop kunnen we nu bv. de volgende constructie maken: x := telop(2,telop(telop(3,4),telop(5,6)));, wat resulteert in x=20.
Nog wat voorbeeldjes:
function aantal_letters(s: s[80]): byte;
var x,a: integer;
begin
a := 0;
for x := 1 to length(s) do
if ((s[x] >= ‘a’) and (s[x] <= ‘z’)) or ((s[x] >= ‘a’) and (s[x] <= ‘z’)) then
a := a + 1;
aantal_letters := a;
end;
Met deze functie wordt het aantal letters geteld dat in de string s zit. Het type s80 moet al eerder gedeclareerd zijn.
Met de constructie s[x] wordt het x-de karakter van s bedoeld. Nadere uitleg over deze constructie vindt u bij gestructureerde types.
function JaNee(vraag: s80): boolean;
var k: char;
begin
write(vraag+’ [J/N]: ‘);
repeat
read(kbd,k);
until k in [‘j’,’J’,’n’,’N’,#13];
if (k = #13) or (k = ‘j’) then
k = ‘J’;
writeln(k);
JaNee := (k = ‘J’);
end;
Met deze functie kunt u een Ja/Nee-vraag stellen en kijken of er Ja is geantwoord. De functie is van het type boolean en geeft dus de waarde true of false terug.
Verder vind je in deze functie de constructie read(kbd,k);, waarmee het toetsenbord wordt gescand. Deze opdracht zit in een repeat-until-lus die pas wordt verlaten als de gebruiker op de j(J) van ja of de n(N) van nee heeft gedrukt. Wanneer de gebruiker op de Enter-toets(#13) drukt wordt dat geinterpreteerd als een J. De constructie until k in [‘j’,’J’,’n’,’N’,#13]; is ook erg handig en kunt u letterlijk vertalen met: totdat k in de verzameling {‘j’,’J’,’n’,’N’,Enter} zit.
Voorbeeld van het gebruik van bovenstaande functie:
repeat
[statements];
until JaNee(‘Wilt u stoppen?’);
of
repeat
[statements];
until not JaNee(‘Wilt u nog een keer?’);
Let even op het subtiele verschil tussen beide voorbeelden.
Oefeningen.
9.1
De rij van Fibonacci is beroemd. Wanneer u daar het fijne van wilt weten, dan moet u maar even googelen.
De rij gaat als volgt: 1, 1, 2, 3, 5, 8, 13, 21, …; de n-de term is de som van de voorgaande twee termen. De eerste twee termen zijn 1.
Schrijf een functie FibIter(n: byte): integer; die de n-e term van de rij van Fibonacci geeft. Dus FibIter(12) moet 144 opleveren. [Antwoord]
9.2
Schrijf een functie UCase(s: s80): s80; die alle kleine letters in s omzet naar hoofdletters, waarbij s80 een string-type van maximaal 80 karakters is.
Hierbij kunt (moet?) je gbruik maken van twee standaard-functies: ord en chr.
Met ord([karakter]) krijgt u de ascii-waarde van [karakter]. Met chr([nummer]) krijgt u het karakter met ascii-waarde [nummer].
De ascii-waardes van resp a en A zijn: 97 en 65. Hiermee moet je het kunnen doen. [Antwoord]
[Parameters en Type-declaratie] <– –> [Bestanden]