Les Sous-programmes

Le sous-programme est une partie de programme presque indépendante qui a un nom et peut être appelée d'un autre sous-programme ou du programme principal. Il y a deux sortes de sous-programmes - procédures et fonctions.

Les procédures sans paramètres.

Exemple: Sommer une liste des nombres lus, jusqu'un nombre égal à 0 soit lu.

Program somme6;
Var
 n,s : Integer;
Procedure LireNombre;
Begin
 Writeln('Entrez un nombre entier (0 pour           terminer):');
 Readln(n);
End;
Begin
 s:=0;
 While n<>0 Do
 Begin
  s := s+n;
  LireNombre;
 End;
 Writeln('La somme est:',s);
End.

Il est clair que LireNombre et le reste du programme (surtout l'addition) doivent communiquer par une variable contenant le nombre lu qui doit être additionné. Nous donnons le nom n à cette variable et elle sera de type entier. Cette variable commun à deux ou plusieurs parties sera dite "globale".

Indication des variables globales et locales dans un pavé.

Les variables locales ne seront indiquées que dans un pavé immédiatement suivi de sa définition (comme le pavé du programme principal). Elles sont écrit sous le nom de l'action du pavé.

Les variables globales peuvent être indiquées dans un pavé non suivi de sa définition. Elles doivent être indiquées dans le pavé principal. Il y a trois sortes de variables globales:

  1. celles qui sont seulement consultées par l'action du pavé sans en changer la valeur; on la souligne;
  2. celles qui reçoivent un résultat des actions définies en dessous et dont les actions n'utilisent pas l'éventuelle valeur initiale; on les surligne;
  3. celles dont les actions situées en dessous utilisent la valeur initiale et la changent éventuellement; elles ne sont ni soulignées ni surlignées.

Des exemples sont dessinés.

En Pascal la seule façon d'introduire les variables locales est d'utilise les procédures ou les fonctions. Une procédure correspond à un sous-arbre avec des variables globales et locales. Une procédure doit toujours avoir un nom déclaré dans la partie des déclarations. Ce nom est associé à l'algorithme défini par le sous-arbre. Chaque fois que dans le programme on veut utiliser cet algorithme, il faut le faire par une instruction d'appel qui est simplement constituée du nom de la procédure.

donne lieu à la déclaration de procédure:
Procedure NomDeAction;
 {global v1,v2,v3;
         c1,c2,c3;
     res r1,r2,r3;}
Var
  l1,l2,l3 : type;
Begin {NomDeAction}
 Traduction de l'algorithme
End{NomDeAction};

Exemple: On peut considérer séparativement tous les parties de l'algorithme pour sommer tous les éléments d'un tableau:

Program Somme_N;
Const Nmax = 10;
Type
 Tableau = Array[1..Nmax] Of Real;
Var
 A : Tableau;
 s : Real; N: integer;
Procedure LireA;
    { res A,N;}
Var i : integer;
Begin {LireA}
 Repeat
  Write('Entrez N: '); Readln(N);
 Until (N>0) And (N<=Nmax);
 For i:=1 To N Do Begin
  Write('Entrez A[',i,']: ');
  Readln(A[i]);
 End;
End {LireA};
Procedure SommerA;
   { A,N; res s;}
Var i : integer;
Begin {SommerA}
 s:=0;{Initialisation}
 For i:=1 To N Do s := s+A[i];
End;
Procedure AffishageS;
   { s; }
Begin
 Writeln('La somme est =',s:10:3);
End;
Begin
 LireA;
 SommerA
 AffichageS;
End.

Exécution d'un appel de procédure

  1. Un enregistrement d'activation avec la structure montrée est créé et placé dans la pile (les variables locales commencent à exister);
  2. Les instructions de la procédure sont exécutées;
  3. L'enregistrement d'activation est détruit (les variables locales n'existent plus).

En Pascal, non seulement les variables locales ne sont pas accessibles de dehors mais elles n'existent que pendant l'exécution de la procédure.
Exemple formel:

Program p;
 Var i,j,k,t : integer;
 Procédure p1;
  Var i,j,n : integer;
  Procedure p2;
   Var i,k.r :real;
   Begin
    corps de p2;
   end;
  Begin
   corps de p1;
  end;
 Procedure p3;
  Var j,h : integer;
 Begin
  corps de p3;
 End;
Begin {programme}
 corps du programme;
End.
Dans le corps du programme seuls les variables i,j,k et t et les procédures p1 et p3 sont accessibles. La procédure p2 est locale à p1 et ne peut être appelée depuis le programme.

Dans le corps de p1 les variables locales i,j et n et les variables globales k et t du programme p sont accessibles. Les variables i et j du programme principal sont cachées par les variables locales de même nom. La procédure p2 peut être appelée (et p1 aussi). Mais p3 n'est pas accessible car elle est déclarée plus loin.

Dans le corps de p2 les variables locales à p2 i,k et r ainsi que j et n locales à p1 et t globale p sont accessibles. p1 et p2 peuvent être appelées (appels récursifs).

Dans le corps de p3 les variables locales à p2 i et h ainsi que les variables globales i,k et t p sont accessibles. Les procédures p1 et p3 peuvent être appelées.

En résumé: Dans un bloc on a accès à tout ce qui est accessible dans un bloc juste plus grand à condition que cela a été déclaré avant et ne soit pas caché par quelque chose de local et de même nom. En aucun cas on peut avoir accès de l'extérieur d'un bloc à ce qui est déclaré à l'intérieur de ce bloc.

Les fonctions sans paramètres

Les fonctions sont des sortes des sous-programmres dont l'effet est de produire une valeur appelée résultat. Par exemple la procédure SommerA a un résultat simple - la somme qui est rangée dans la variable globale s. On peut la définir comme une fonction:

Function SommeA: real;
{ A,N;}
Var i : integer; s: real;
Begin {SommerA}
  For i:=1 To N Do s := s+A[i];
    Somme A := s;
End;

Cette fonction donne un résultat réel et la valeur de ce résultat est précisée par l'instruction:
SommeA := s;

Cette instruction a la forme d'une instruction d'affectation mais SommeA n'est pas une variable et cette instruction veut seulement dire que l'évaluation de l'expression à droite du signe := donne le résultat de la fonction. Cette fonction est dite "instruction résultat". Le résultat peut être de n'importe quel type simple.

la fonction doit contenir au moins une instruction résultat; de plus chaque exécution de la fonction doit contenir au moins une instruction résultat. la dernière de ces instructions exécutées donne le résultat final.

la fonction peut utiliser des variables globales. Une pure fonction ne doit que consulter ces variables. Une fonction qui modifie les variables globales est dite à "effets de bord'. Ces effets doivent être évités.

La forme générale d'une fonction sans paramètres est montrée par l'arbre:

Function NomDeFonction : type simple;
    {global v1,v2,v3;
            c1,c2,c3;
       res r1,r2,r3;}
Var
 l1,l2,l3 : type;
Begin {NomDeFonction}
 Traduction de l'algorithme
End {NomDeFonction};

Comme les procédures les fonctions peuvent contenir des définitions de sous-programmes locales. Les règles de portées et d'accessibilité des noms sont les mêmes que pour les procédures. Une fonction est appelée par citant son nom. Car la fonction produit un résultat d'un certain type, un appel de fonction ne doit apparaître qu'en un point du programme où une expression du type de résultat est acceptable. Par exemple l'appel de la fonction SommeA ne peut apparaître que là où une expression réelle est acceptable.

Si au lieu de la procédure SommerA on utilise la fonction SommeA on doit changer les définitions est le corps du programme principal va prendre la forme;

Begin
 LireA;
 s :=SommeA;
 AffichageS;
End.

Exécution d'un appel de fonction contenue dans une expression

  1. Un enregistrement d'activation avec la structure montrée est créé et placé dans la pile (les variables locales commencent à exister);
  2. Les instructions de la procédure sont exécutées; elles contiennent au moins une instruction résultat.
  3. L'enregistrement d'activation est détruit (les variables locales n'existent plus).
  4. L'expression continue d'être évaluée avec le résultat de la fonction à la place d'appel.