Les sous-programmes avec paramètres

Procédures avec paramètres

L'utilisation des paramètres fait les sous-programmes plus indépendants et plus flexibles. On n'est pas limité d'utiliser des noms de variables globales fixes. La forme générale d'une procédure avec paramètres est:

et donne lieu à la déclaration:
Procedure NomDeAction(var pv:type; pc:type; var pr:type);
         {global v1,v2,v3;
                 c1,c2,c3;
          res r1,r2,r3;}
Var
 l1,l2,l3 : type;
Begin {NomDeAction}
 Traduction de l'agorithme
End{NomDeAction};

Un appel de cette procédure doit être de la forme:
NomDeAction(pe1,pe2,pe3);

Les paramètres pv, pc et pr de la déclaration sont appelés paramètres formels. Comme les variables globales ils ont un mode de communication: pv est variable, pc est consulté et pr est un résultat. Le nombre des paramètres formels n'est pas limité et leur ordre est arbitraire et défini par le programmeur.

Le Pascale impose de définir chaque paramètre formel par son nom, type et mode de communication. Le type doit être indiqué seulement par un nom de type. Il y a 2 modes de communication:

Les paramètres pe1, pe2 et pe3 de l'appel sont appelés des paramètres effectifs. Ils doivent être du même nombre que les paramètres formels et leur correspondent par leurs positions. Chaque paramètre effectif doit être en accord avec le paramètre formel correspondant tant de point de vue du type que du mode. Si le paramètre formel est appelé par adresse le paramètre effectif doit être une variable du même type (identique). Si le paramètre formel est appelé par valeur le paramètre effectif doit être une expression d'un type compatible vis à vis l'affectation avec le type du paramètre formel.

Mécanisme d'un appel de procédure avec paramètres

  1. Un enregistrement d'activation avec la structure montrée est créé et placé dans la pile (les variables locales commencent à exister). Il contient les variables locales, les paramètres appelés par valeur comme des variables locales et de place pour les adresses des paramètres effectifs correspondants aux paramètres formels appelés par adresse.
  2. Tous les paramètres sont évalués suivant leur mode de communication:
  3. Les expressions correspondant aux paramètres appelés par valeur sont calculées et les valeurs sont affectées aux variables locales définies par les paramètres formels.
  4. Les variables correspondant aux paramètres appelés par adresse sont cherchées; les adresses des paramètres effectifs sont rangées dans l'enregistrement d'activation. C'est à dire que les paramètres effectifs seront utilisés au lieu des paramètres formel durant toute l'exécution de la procédure.
  5. Les instructions de la procédure sont exécutées; toute instruction décrite comme agissant sur un paramètre formel appelé par valeur agit sur la variable avec ce nom de l'enregistrement d'activation; toute instruction décrite comme agissant sur un paramètre formel appelé par adresse agit sur la variable définie par le paramètre effectif au moment d'appel;
  6. L'enregistrement d'activation est détruit (les variables locales n'existent plus).

Exemple 1: Une procédure qui ajoute 1 à son paramètre entier:

Procedure Incr(var p:integer);
Begin
 p := p+1;
End;

Supposons que les variables globales aient été déclarées:
t: Array[1..10] of integer; i : integer;
et que ses valeurs soient
i = 2 et t[1] = 10, t[2] =9 ... t[10] = 1
avant l'appel incr (t[2*i+1]);
La valeur de t[5] après l'appel sera 5.

Exemple 2: On peut modifier la procédure SommeN.

Procedure Ajout(var p:integer; v:integer);
Begin
 p := p+ v;
End;

Si les mêmes variables sont déclarées dans le programme principal quel sera le résultat de l'appel:
Ajout(t[2*i-1],t[2*i+1]);

Exemple 3: Ecrire une procédure qui trouve l'élément maximal d'un tableau et son indice et en l'utilisant trie le tableau par sélection directe.

Program Tri_selection;
const
 Nmax = 20;
Type
 Tableau = Array[1..Nmax] of Real;
Var
 A : Tableau;
 N: integer;

Procedure LireA(var N:integer; var A:Tableau);
 var i : integer;
Begin {LireA}
 Repeat
  Write ('Entrez le nombre des elements: ');
  Readln(N);
 Until (N > 0) And (N <= Nmax);
 Writeln ('Entrez ', N, ' nombres reeles:');
 For i := 1 To N Do Read(A[i]);
 Readln;
End;{LireA}
Procedure MaxA(var A:Tableau; N:Integer; var                 max:real; var imax:integer);
var i : integer;
Begin {MaxA}
 max := A[1]; imax := 1;
 for i := 2 To N Do
  If
max < A[i] Then
  Begin
   max := A[i]; imax := i;
  End;
End; {MaxA}
Procedure SortA(var A:Tableau; N:Integer);
      var k,im : integer; m:Real;
Begin {SortA}
 For k := N Downto 2 Do
 Begin
  MaxA
(A,k,m,im);
  if im <> k Then
  Begin
   A[im] := A[k]; A[k] := m;
  End;
 End;
End;{SortA}
Procedure AffichA(var A: Tableau; N: integer);
var i : integer;
Begin {AffichA}
 For i := 1 To N Do Write(A[i]:8:2);
  Writeln;
 End; {AffichA}
Begin {programme}
 LireA(N,A);{Lire les donnees}
 SortA(A,N);{Tri}
 {affichage}
 Write ('Apres le tri');
 AffichA(A,N);
End.{programme}

Les Fonctions avec paramètres

La seule différence avec les procédures est qu'elles donnent un résultat d'un type simple. La forme générale est:

et donne lieu à une déclaration:
Function NomDeFonction(var pv:type; pc:type; var pr:type) :                                        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};

Un appel de cette fonction doit être de la forme:
NomDeFonction(pe1,pe2,pe3)
et se trouve dans une expression où la valeur du type du résultat de la fonction est acceptable. Les règles de correspondance et de transfert entre les paramètres effectifs et formels sont les mêmes que celles des procédures.

Exemple 1: Sommer les éléments d'un tableau réel. (L'arbre programmatique est à la page précédente).

Function SommeA(var A:Tableau; N:integer):Real;
Var s:Real; i : integer;
Begin {SommeA}
 s:=0;
 For i := 1 To N Do s := s+ A[i];
 SommeA := s;
End; {SommeA}

Si dans le programme principal sont déclarés:
var B : Tableau ; somme : Real;
on peut appeler la fonction:
somme := SommeA(B,10);

Exemple 2:

Function ppcm(a,b:integer):integer;
Var
 ma,mb : Integer;
Begin
 ma := a; mb := b;
 While ma <> mb Do
  If
ma < mb Then
   ma := ma + a
  Else
   mb := mb + b;
 ppcm := ma;
End;

Paramètres - noms de sous-progammes

Exemple : Tabulation d'une fonction réelle avec un argument réel.

En Turbo Pascal on doit définir avant un type sous-program et lui donner un nom et puis définir le type de paramètre par ce nom. De plus on utilise la directive {$F+} quand on compile un tel programme. Le paramètre effectif doit être un nom de sous-programme du même type (procédure ou fonction) avec le même nombre et type des paramètres formels et le même type du résultat (pour les fonctions).

{$F+}
Program Tabulations;
type
 func : Function (x:real) : real;
Procedure Tabul(xi,xf,dx:real; f: func);
var x : real;
Begin {Tabul}
 x := xi;
 While x <= xf Do
 Begin
  writeln(x:6:2,f(x):8:2);
  x := x+dx;
 End;
End; {Tabul}
Function f1(x:real):real;
   {la première fonction}
Begin
 f1 := 3*x - sqr(x);
End;
Function f2(y:real) : real;
   {la seconde fonction}
Begin
 f2 := y + sin(y) - cos(y);
End;
Begin {Progamme}
 Tabul(0,1,0.1,f1);
 Tabul(-0.5,0.5,0.05,f2);
End.

En Pascal standard le paramètre formel - nom d'un sous-progamme doit être défini par son plein titre dans la liste des paramètres. On ne doit que changer le titre de la procédure Tabul :
Procedure Tabul(xi,xf,dx:real; f: Function (x:real) : real);

Exercice : Faire une procédure qui trie les éléments d'un tableau avec des éléments réels dont l'ordre est défini par une fonction bouléen (paramètre) qui est vrai si ces deux paramètres sont en ordre et fausse s'ils ne sont pas.