IV. Fonctions▲
Une fonction est une procédure qui renvoie un résultat, de manière à ce qu'on
puisse l'appeler dans une expression.
Exemple
y := cos(x) + 1
; c := chr(x + ord('0'
));
IV-1. Fonction sans paramêtre▲
IV-1-1. Principe▲
Syntaxe
FUNCTION
nom_fonction : type_resultat;
BEGIN
{ ... corps de la fonction ... }
{ Résultat de la fonction, du type type_resultat }
nom_fonction := expression;
END
;
La nouveauté par rapport à une procédure est que l'on < sort > le résultat de la
fonction nom_fonction en écrivant une affectation sur son nom.
Attention
- nom_fonction n'est pas une variable, et à l'intérieur de la fonction il ne faut surtout pas l'utiliser dans une expression, car cela provoquerait un appel récursif.
- Une fonction doit toujours avoir un résultat (i.e on ne peut pas le laisser indéterminé).
IV-1-2. Appel▲
PROGRAM
ex1;
VAR
x : type_resultat;
{ ici déclaration de la fonction }
BEGIN
{ appel fonction et stockage du résultat dans x }
x := nom_fonction;
END
.
IV-1-3. Variables locales▲
FUNCTION
nom_fonction : type_resultat;
VAR
locales : types_locales;
BEGIN
{ ... }
nom_fonction := expression; { du type type_resultat }
END
;
Bonne habitude
Passer par une variable locale res : on fait ce qu'on veut de res dans la fonction,
et à la fin de la fonction on écritnom_fonction := res;
FUNCTION
nom_fonction : type_resultat;
VAR
res : type_resultat;
BEGIN
{ ... dans le corps, on fait ce qu'on veut de res ...}
{ on dit que le résultat est res }
nom_fonction := res;
END
;
IV-2. Fonction avec paramètres▲
Syntaxe
FUNCTION
nom_fonction ( parametres : types_params ) : type_resultat;
VAR
locales : types_locales;
res : type_resultat;
BEGIN
{ ... }
nom_fonction := res;
END
;
Tout ce que l'on a dit sur le paramétrage des procédures reste valable pour les fonctions.
IV-2-1. Procédure vs fonction▲
Exemple du produit.
IV-2-2. Passage de types enregistrement▲
Exemple On veut savoir si un couple d'amis est assorti. On fixe les règles suivantes : le couple est assorti si ils ont moins de 10 ans d'écart, ou si le mari est agé et riche.
PROGRAM
assorti;
TYPE
humain_t = Record
age, taille : integer
;
riche : boolean
;
End
;
couple_t = Record
homme, femme : humain_t;
nb_enfant : integer
;
End
;
FUNCTION
difference_age (h, f : humain_t) : integer
;
VAR
res : integer
;
BEGIN
res := abs (h.age - f.age);
difference_age := res;
END
;
FUNCTION
couple_assorti (c : couple_t) : boolean
;
VAR
res : boolean
;
BEGIN
res := false
;
if
difference_age (c.homme, c.femme) < 10
then
res := true
;
if
(c.homme.age > 75
) and
c.homme.riche then
res := true
;
couple_assorti := res;
END
;
VAR
amis : couple_t;
BEGIN
{ ... }
write
('Ce couple avec '
, amis.nb_enfant, ' enfant(s) est '
);
if
couple_assorti (amis) then
writeln ('assorti.'
)
else
writeln ('non assorti.'
);
END
.
IV-3. Fonction avec plusieurs résultats▲
Il est fréquent que l'on écrive une fonction qui renvoie un booléen qui dit si tout
s'est bien passé, tandis que les vrais résultats sont passés dans les paramètres.
Exemple Une fonction qui prend une lettre, la met en majuscule ou renvoie une
erreur si le caractère n'est pas une lettre.
FUNCTION
maj_lettre ( lettre : char
;
var
maj : char
) : boolean
;
VAR
res : boolean
;
BEGIN
{ init }
maj := lettre;
res := true
; { pas d'erreur }
case
lettre of
'a'
.. 'z'
: maj := chr(ord(lettre) - ord('a'
) + ord('A'
));
'A'
.. 'Z'
, '_'
: ; { rien }
else
res := false
;
end
; { case lettre }
maj_lettre := res;
END
;
L'appel de cette fonction :
VAR
c, m : char
;
BEGIN
readln (c);
if
maj_lettre (c,m)
then
writeln ('La majuscule de '
, c, ' est '
, m)
else
writeln ('Le caractère '
, c, ' n''est pas une lettre'
);
END
.
Autre avantage : on fait tous les affichages et messages d'erreur en dehors de la
fonction.
Exemple [ non vu en cours faute de temps ]
On veut calculer or il risque d'y avoir des divisions par 0.
On écrit d'abord une fonction calc qui renvoie un booléen qui dit si le calcul de a pu se faire, tandis que le résultat numérique est passé en paramètre z.
FUNCTION
calc ( x : integer
;
y : real
;
var
z : real
) : boolean
;
VAR
ok : boolean
;
d : real
;
BEGIN
ok := true
; { init pas d'erreur }
d := cos (x-y);
if
d = 0
.0
then
ok := false
{ division par 0 }
else
z := (x+y) / d; { resultat numerique }
calc := ok;
END
;
On écrit ensuite une fonction somme qui appelle calc.
FUNCTION
somme ( a, b : integer
;
k : real
) : real
;
VAR
res, f : real
;
i : integer
;
BEGIN
res := 0
.0
; { init somme a O }
for
i := a to
b do
if
calc (i, k, f)
then
res := res + f;
somme := res;
END
;
L'appel de cette fonction :
VAR
ga, gb : integer
;
gk, gs : real
;
BEGIN
readln (ga, gb, gk);
gs := somme (ga, gb, gk);
writeln (gs);
END
.
Exercice
- Modifier la fonction somme pour que elle renvoie un booléen disant que tous les calculs de la somme ont pu se faire, tandis que le résultat numérique est passé en paramètre.
- Adapter le programme principal appelant somme.
IV-4. Gestion d'erreurs▲
[ non vu en cours, tombe un peu à plat .. ]
On veut généraliser l'usage de fonctions renvoyant un code d'erreur, et dont les
résultats sont passés en paramètres.
- Soient F1, F2, etc, de telles fonctions renvoyant un booléen.
- Soit ok un booléen.
- Soient I1, I2, etc, des instructions.
Considérons la séquence d'instruction suivante
I1;
ok := F1 ( ... );
I2;
ok := F2 ( ... );
I3;
ok := F3 ( ... );
I4;
{ ... }
On veut exécuter ce traitement, mais l'interrompre dès qu'il y a une erreur. On devrait normalement écrire :
I1;
if
F1 ( ... )
then
begin
I2;
if
F2 ( ... )
then
begin
I3;
if
F3 ( ... )
then
begin
I4;
{ ... }
end
;
end
;
end
;
C'est lourd, on se perd rapidement dans tous ces begin end. Il est beaucoup simple d'écrire
I1;
ok := F1 ( ... );
if
ok then
begin
I2;
ok := F2 ( ... );
end
;
if
ok then
begin
I3;
ok := F3 ( ... );
end
;
if
ok then
begin
I4;
{ ... }
end
;
Dés que ok est faux, plus aucun bloc suivant n'est exécut.