Cours d'algorithmique - Fonctions et procédures

Fonctions et procédures

Certains problèmes conduisent à des programmes longs, difficiles à écrire et à comprendre. On les découpe en des parties appelées sous-programmes ou modules.
Les fonctions et les procédures sont des modules (groupe d'instructions) indépendants désignés par un nom. Elles ont plusieurs intérêts :
  • permettent de "factoriser" les programmes, càd de mettre en commun les parties qui se répètent
  • permettent une structuration et une meilleure lisibilité des programmes
  • facilitent la maintenance du code (il suffit de modifier une seule fois)
  • ces procédures et fonctions peuvent éventuellement être réutilisées dans d'autres programmes

Fonctions

Le rôle d'une fonction en programmation est similaire à celui d'une fonction en mathématique : elle retourne un résultat à partir des valeurs des paramètres 
Une fonction s'écrit en dehors du programme principal sous la forme :
Fonction nom_fonction (paramètres et leurs types) : type_fonction        
                      Instructions constituant le corps de la fonction

                      retourne … 

 FinFonction 
  • Pour le choix d'un nom de fonction il faut respecter les mêmes règles que celles pour les noms de variables 
  • type_fonction est le type du résultat retourné 
  • L'instruction retourne sert à retourner la valeur du résultat
Exemples : 
La fonction SommeCarre suivante calcule la somme des carrées de deux réels x et y :
Fonction SommeCarre (x : réel, y: réel ) : réel
variable z : réel
z ←x^2+y^2
retourne (z)
FinFonction
La fonction Pair suivante détermine si un nombre est pair :
Fonction  Pair (n : entier ) : booléen
retourne (n%2=0)
FinFonction 

Utilisation des fonctions

L'utilisation d'une fonction se fera par simple écriture de son nom dans le programme principale. Le résultat étant une valeur, devra être affecté ou être utilisé dans une expression, une écriture, ...
Exepmle : 
    Algorithme exepmleAppelFonction
variables     z : réel,  b : booléen
Début
          b ←Pair(3)
          z ←5*SommeCarre(7,2)+1
         écrire("SommeCarre(3,5)= ", SommeCarre(3,5))
Fin
Lors de l'appel Pair(3) le paramètre formel n  est remplacé par le paramètre effectif 3

Procèdures

Dans certains cas, on peut avoir besoin de répéter une tache dans plusieurs endroits du programme, mais que dans cette tache on ne calcule pas de résultats ou qu'on calcule plusieurs résultats à la fois
Dans ces cas on ne peut pas utiliser une fonction, on utilise une procédure 
Une procédure est un sous-programme semblable à une fonction mais qui ne retourne rien
Une procédure s'écrit en dehors du programme principal sous la forme :
Procédure nom_procédure (paramètres et leurs types)
Instructions constituant le corps de la procédure
FinProcédure
Remarque : une procédure peut ne pas avoir de paramètres

Appel d'une procédure

L'appel d'une procédure, se fait dans le programme principale ou dans une autre procédure par une instruction indiquant le nom de la procédure :
Procédure exemple_proc (…)

FinProcédure
Algorithme exepmleAppelProcédure
Début
exemple_proc (…)

Fin
Remarque : contrairement à l'appel d'une fonction, on ne peut pas affecter la procédure appelée ou l'utiliser dans une expression. L'appel d'une procédure est une instruction autonome

Paramètres d'une procédure

Les paramètres servent à échanger des données entre le programme principale (ou la procédure appelante) et la procédure appelée.
Les paramètres placés dans la déclaration d'une procédure sont appelés paramètres formels. Ces paramètres peuvent prendre toutes les valeurs possibles mais ils sont abstraits (n'existent pas réellement).
Les paramètres placés dans l'appel d'une procédure sont appelés  paramètres effectifs. ils contiennent les valeurs pour effectuer le traitement.
Le nombre de paramètres effectifs doit être égal au nombre de paramètres formels. L'ordre et le type des paramètres doivent correspondre.

Transmission des paramètres

Il existe deux modes de transmission de paramètres dans les langages de programmation  :
La transmission par valeur : les valeurs des paramètres effectifs sont affectées aux paramètres formels correspondants au moment de l'appel de la procédure. Dans ce mode le paramètre effectif ne subit aucune modification
La transmission par adresse (ou par référence) : les adresses des paramètres effectifs sont transmises à la procédure appelante. Dans ce mode, le paramètre effectif subit les mêmes modifications que le paramètre formel lors de l'exécution de la procédure
Remarque : le paramètre effectif doit être une variable (et non une valeur) lorsqu'il s'agit d'une transmission par adresse.
En pseudo-code, on va préciser explicitement le mode de transmission dans la déclaration de la procédure.

Transmission des paramètres : Exemple

Procédure incrementer1 (x : entier par valeur,  y : entier par adresse)
x ← x+1
y ← y+1
FinProcédure
Algorithme Test_incrementer1
variables     n, m : entier
Début
n ← 3
m ← 3
               incrementer1(n, m)
               écrire (" n= ", n, " et m= ", m)
               n=3 et m=4
Fin
Remarque : l'instruction x ← x+1 n'a pas de sens avec un passage par valeur

Transmission par valeur, par adresse : exemples

Procédure qui calcule la somme et le produit de deux entiers :
Procédure SommeProduit (x,y: entier par valeur, som, prod : entier par adresse)
som ← x+y
prod ← x*y
FinProcédure 
Procédure qui échange le contenu de deux variabales :
Procédure Echange (x : réel par adresse,  y : réel par adresse)
variables     z : réel
z ← x
x ← y
y ← z
FinProcédure 

Variables locales et globales (1)

On peut manipuler  2 types de variables dans un module (procédure ou fonction) : des variables locales et des variables globales. Elles se distinguent par ce qu'on appelle leur portée (leur "champ de définition",  leur "durée de vie")
Une variable locale n'est connue qu'à l'intérieur du module ou elle a été définie. Elle est créée à l'appel du module et détruite à la fin de son exécution
Une variable globale est connue par l'ensemble des modules et le programme principale. Elle est définie durant toute l’application et peut être utilisée et modifiée par les différents modules du programme

Variables locales et globales (2)

La manière de distinguer la déclaration des variables locales et globales diffère selon le langage
En général, les variables déclarées à l'intérieur d'une fonction ou procédure sont considérées comme variables locales
En pseudo-code, on va adopter cette règle pour les variables locales et on déclarera les variables globales dans le programme principale
Conseil : Il faut utiliser autant que possible des variables locales plutôt que des variables globales. Ceci permet d'économiser la mémoire et d'assurer l'indépendance de la procédure ou de la fonction

Récursivité

Un module (fonction ou procédure) peut s'appeler lui-même: on dit que c'est un module récursif
Tout module récursif doit posséder un cas limite (cas trivial) qui arrête la récursivité
Exemple : Calcul du factorielle
Fonction  fact (n : entier ) : entier
Si (n=0)  alors
retourne (1)
Sinon
               retourne (n*fact(n-1))
Finsi
FinFonction 

Fonctions récursives : exercice

Ecrivez une fonction récursive (puis itérative) qui calcule le terme n de la suite de Fibonacci définie par :
U(0)=U(1)=1
U(n)=U(n-1)+U(n-2)
Fonction  Fib (n : entier ) : entier
Variable res : entier
Si (n=1 OU n=0)  alors
res ←1
Sinon 
res ← Fib(n-1)+Fib(n-2)
Finsi
retourne (res)
FinFonction 

Fonctions récursives : exercice (suite)

Une fonction  itérative pour le calcul de la suite de Fibonacci  :
Fonction  Fib (n : entier ) : entier
      Variables i, AvantDernier, Dernier, Nouveau : entier
Si (n=1 OU n=0)  alors
                        retourne (1)
Finsi
                 AvantDernier  ←1, Dernier  ←1
              Pour i allant de 2 à n
                     Nouveau← Dernier+ AvantDernier
                      AvantDernier  ←Dernier
Dernier  ←Nouveau
FinPour
retourne (Nouveau)
FinFonction 
Remarque: la solution récursive est plus facile à écrire

Procédures récursives : exemple 

Une procédure récursive qui permet d'afficher la valeur binaire d'un entier n
Procédure  binaire (n : entier )
Si (n<>0)  alors        
                  binaire (n/2)
               écrire (n mod 2)
Finsi
FinProcédure 

Cours d'algorithmique - Instructions itératives: les boucles

Instructions itératives: les boucles

Les boucles servent à répéter l'exécution d'un groupe d'instructions  un certain nombre de fois
On distingue trois sortes de boucles en langages de programmation :
Les boucles tant que : on y répète des instructions tant qu'une certaine condition est réalisée
Les boucles jusqu'à : on y répète des instructions jusqu'à ce qu'une certaine condition soit réalisée
Les boucles pour ou avec compteur : on y répète des instructions en faisant évoluer un compteur (variable particulière) entre une valeur initiale et une valeur finale 

Les boucles Tant que

Syntaxe Générale
            TantQue     (condition)
                      instructions
            FinTantQue

la condition (dite condition de contrôle de la boucle) est évaluée avant chaque itération
si la condition est vraie, on exécute instructions (corps de la boucle), puis, on retourne tester la condition.
Si elle est encore vraie, on répète l'exécution, …
si la condition est fausse, on sort de la boucle et on exécute l'instruction  qui est après FinTantQue

Les boucles Tant que : remarques

Le nombre d'itérations dans une boucle TantQue n'est pas connu au moment d'entrée dans la boucle. Il dépend de l'évolution de la valeur de condition
Une des instructions du corps de la boucle doit absolument changer la valeur de condition de vrai à faux (après un certain nombre d'itérations), sinon le programme tourne indéfiniment
Attention aux boucles infinies

Exemple de boucle infinie : 

i ← 2
TantQue   (i > 0)
i ←  i+1        (attention aux erreurs de frappe : + au lieu de -)
FinTantQue

Boucle Tant que : Exemple1

Contrôle de saisie d'une lettre majuscule jusqu’à ce que le caractère entré soit valable
Variable C : caractère
Debut
            Ecrire (" Entrez une lettre majuscule ")
Lire (C)
TantQue (C < 'A' ou C > 'Z')
                           Ecrire ("Saisie erronée. Recommencez")
                           Lire (C)
           FinTantQue
          Ecrire ("Saisie valable")
Fin

Boucle Tant que : Exemple2 (version 1)

Un algorithme qui détermine le premier nombre entier N tel que la somme de 1 à N dépasse strictement 100
Variables som, i : entier
 Debut
i ← 0
som← 0
TantQue (som <=100)
    i ←  i+1
som ←  som+i
FinTantQue
         Ecrire (" La valeur cherchée est N=  ", i)
Fin

Boucle Tant que : exemple2  (version2)

Un algorithme qui détermine le premier nombre entier N tel que la somme de 1 à N dépasse strictement 100
version 2: attention à l'ordre des instructions et aux valeurs initiales
Variables som, i : entier
 Debut
            som ← 0
          i ← 1
           TantQue (som <=100)
                    som ← som + i
                    i ←  i+1
FinTantQue
Ecrire (" La valeur cherchée est N=  ", i-1)
Fin

Les boucles Pour

Syntaxe Générale
Pour compteur allant de  valeur initiale à finale par pas valeur du pas
           instructions
FinPour


Remarque : le nombre d'itérations dans une boucle Pour est connu avant le début de la boucle
Compteur est une variable de type entier (ou caractère). Elle doit être déclarée
Pas est un entier qui peut être positif ou négatif. Pas peut ne pas être mentionné, car par défaut sa valeur est égal à 1. Dans ce cas, le nombre d'itérations est égal à finale - initiale+ 1
valeur initiale et finale peuvent être des valeurs, des variables définies avant le début de la boucle ou des expressions de même type que compteur 

Déroulement des boucles Pour

La valeur initiale est affectée à la variable compteur
On compare la valeur du compteur et la valeur de finale :
  • Si la valeur du compteur est > à la valeur finale dans le cas d'un pas positif (ou si compteur est <  à finale pour un pas négatif), on sort de la boucle et on continue avec l'instruction qui suit FinPour
  • Si compteur est <= à finale dans le cas d'un pas positif (ou si compteur est >=  à finale pour un pas négatif), instructions seront exécutées
Ensuite, la valeur de compteur est incrémentée de la valeur du pas  si pas est positif (ou décrémenté si pas est négatif)
On recommence l'étape 2 : La comparaison entre compteur et finale est de nouveau effectuée, et ainsi de suite  …

Boucle Pour : exemple1

Calcul de x à la puissance n où x est un réel non nul et n un entier positif ou nul
Variables x, puiss : réel
                        n, i : entier
Debut
                Ecrire (" Entrez la valeur de x ")
Lire (x)
Ecrire (" Entrez la valeur de n ")
Lire (n)
puiss ← 1 Pour i allant de 1 à n
    puiss← puiss*x
                FinPour
Ecrire (x, " à la puissance  ", n, "  est égal à  ", puiss)
Fin

Boucle Pour : exemple1 (version 2)

Calcul de x à la puissance n où x est un réel non nul et n un entier positif ou nul (version 2 avec un pas négatif)
Variables x, puiss : réel
                       n, i : entier
Debut
                Ecrire (" Entrez respectivement les valeurs de x et n ")
Lire (x, n)
puiss ← 1 Pour i allant de n à 1 par pas -1
    puiss← puiss*x
                FinPour
                Ecrire (x, " à la puissance  ", n, "  est égal à  ", puiss)
Fin

Boucle Pour : remarque

Il faut éviter de modifier la valeur du compteur (et de finale) à l'intérieur de la boucle. En effet, une telle action :
  • perturbe le nombre d'itérations prévu par la boucle Pour
  • rend difficile la lecture de l'algorithme
  • présente le risque d'aboutir à une boucle infinie
Exemple : 
   Pour i allant de 1 à 5
      i ← i -1
           écrire(" i =  ", i)
Finpour

Lien entre Pour et TantQue

La boucle Pour est un cas particulier de Tant Que (cas où le nombre d'itérations est connu et fixé) . Tout ce qu'on peut écrire avec Pour peut être remplacé avec TantQue (la réciproque est fausse)
  Pour compteur allant de initiale à finale par pas valeur du pas
                          instructions          
   FinPour
peut être remplacé par :
compteur ← initiale
(cas d'un pas positif)
TantQue   compteur <= finale
instructions
compteur ←  compteur+pas
FinTantQue

Lien entre Pour et TantQue : exemple

Calcul de x à la puissance n où x est un réel non nul et n un entier positif ou nul (version avec TantQue)
Variables x, puiss : réel
                        n, i : entier
Debut
                Ecrire (" Entrez la valeur de x ")
Lire (x)
Ecrire (" Entrez la valeur de n ")
Lire (n)
puiss ← 1
  i ← 1
TantQue (i<=n)
    puiss← puiss*x
                        i ← i+1
FinTantQue
Ecrire (x, " à la puissance  ", n, "  est égal à  ", puiss)
Fin

Boucles imbriquées

Les instructions d'une boucle peuvent être des instructions itératives. Dans ce cas, on aboutit à des boucles imbriquées
Exemple :
Pour i allant de 1 à 5
    Pour j allant de 1 à i
                            écrire("O")
  FinPour
écrire("X")
FinPour
Exécution
OX
    OOX
OOOX
  OOOOX
  OOOOOX

Les boucles Répéter … jusqu’à …

Syntaxe Générale
Répéter
           instructions
Jusqu'à condition

Condition est évaluée après chaque itération
les instructions entre Répéter et jusqu’à sont exécutées au moins une fois et leur exécution est répétée jusqu’à ce que condition soit vrai (tant qu'elle est fausse)

Boucle Répéter  jusqu’à  : exemple

Un algorithme qui détermine le premier nombre entier N tel que la somme de 1 à N dépasse strictement 100 (version avec répéter jusqu'à)
Variables som, i : entier
        Debut
                 som ← 0
               i ← 0                
                 Répéter
    i ←  i+1
som ←  som+i
Jusqu'à ( som > 100)
Ecrire (" La valeur cherchée est N=  ", i)
Fin

Choix d'un type de boucle

Si on peut déterminer le nombre d'itérations avant l'exécution de la boucle, il est plus naturel d'utiliser la boucle Pour
S'il n'est pas possible de connaître le nombre d'itérations avant l'exécution de la boucle, on fera appel à l'une des boucles TantQue ou répéter jusqu'à
Pour le choix entre TantQue et jusqu'à :
  • Si on doit tester la condition de contrôle avant de commencer les instructions de la boucle, on utilisera  TantQue
  • Si la valeur de la condition de contrôle dépend d'une première exécution des instructions de la boucle, on utilisera répéter jusqu'à 

Cours d'algorithmique - Test : Instructions conditionnelles

Tests: instructions conditionnelles

Les instructions conditionnelles servent à n'exécuter une instruction ou une séquence d'instructions que si une condition est vérifiée
On utilisera la forme suivante:
Si condition alors
              instruction ou suite d'instructions1
Sinon
              instruction ou suite d'instructions2
Finsi
la condition ne peut être que vraie ou fausse
  • si la condition est vraie, se sont les instructions1 qui seront exécutées
  • si la condition est fausse, se sont les instructions2 qui seront exécutées
la condition peut être une condition simple ou une condition composée de plusieurs conditions
La partie Sinon n'est pas obligatoire, quand elle n'existe pas et que la condition est fausse, aucun traitement n'est réalisé

On utilisera dans ce cas la forme simplifiée suivante:
Si condition alors
 instruction ou suite d'instructions1
Finsi 

Exemples

Exemple (Si…Alors…Sinon)

Algorithme AffichageValeurAbsolue (version1)
Variable x : réel
Début
             Ecrire (" Entrez un réel : “)
             Lire (x)
             Si (x < 0) alors
                       Ecrire ("la valeur absolue de ", x, "est:",-x)
             Sinon
                      Ecrire ("la valeur absolue de ", x, "est:",x)
             Finsi
Fin

Exemple (Si…Alors)

Algorithme AffichageValeurAbsolue (version2)
Variable x,y : réel
Début
             Ecrire (" Entrez un réel : “)
             Lire (x)
             y← x
             Si (x < 0) alors
                         y ← -x
             Finsi
                        Ecrire ("la valeur absolue de ", x, "est:",y)
Fin

Exercice 

Écrire un algorithme qui demande un nombre entier à l'utilisateur, puis qui teste et affiche s'il est divisible par 3
Algorithme Divsible_par3
Variable n : entier
Début                      
                         Ecrire " Entrez un entier : "
         Lire (n)
         Si (n%3=0) alors                                   
                                  Ecrire (n," est divisible par 3")
         Sinon
                                 Ecrire (n," n'est pas divisible par 3")
         Finsi
        Fin

Conditions composées 

Une condition composée est une condition formée de plusieurs conditions simples reliées par des opérateurs logiques:
ET, OU, OU exclusif (XOR) et NON

Exemples : 

- x compris entre 2 et 6 : (x > 2) ET (x < 6)
- n divisible par 3 ou par 2 : (n%3=0) OU (n%2=0)
- deux valeurs et deux seulement sont identiques parmi a, b et c :
(a=b) XOR (a=c) XOR (b=c)
L'évaluation d'une condition composée se fait selon des règles présentées généralement dans ce qu'on appelle tables de vérité

Tables de vérité


Tests imbriqués

Les tests peuvent avoir un degré quelconque d'imbrications
  Si condition1 alors
Si condition2 alors
instructionsA
Sinon
instructionsB
           Finsi
Sinon
Si condition3 alors
instructionsC
Finsi
Finsi

Tests imbriqués: exemple (version 1)

Variable n : entier
  Début
Ecrire ("entrez un nombre : ")
Lire (n)
  Si (n < 0) alors
                      Ecrire ("Ce nombre est négatif")
         Sinon
                   Si (n = 0) alors
                                Ecrire ("Ce nombre est nul")
Sinon
                                Ecrire ("Ce nombre est positif")
Finsi
  Finsi
Fin

Tests imbriqués: exemple (version 2)

Variable n : entier
Début
        Ecrire ("entrez un nombre : ")
        Lire (n)
        Si (n < 0) alors Ecrire ("Ce nombre est négatif")
        Finsi
        Si (n = 0) alors Ecrire ("Ce nombre est nul")
        Finsi
        Si (n > 0) alors Ecrire ("Ce nombre est positif")
        Finsi
 Fin
Remarque : dans la version 2 on fait trois tests systématiquement alors que dans la version 1, si le nombre est négatif on ne fait qu'un seul test
Conseil :  utiliser les tests imbriqués pour limiter le nombre de tests et placer  d'abord les conditions les plus probables

Tests imbriqués: exercice

Le prix de photocopies dans une reprographie varie selon le nombre demandé:  0,5 DH la copie pour un nombre de copies inférieur à 10, 0,4DH pour un nombre compris entre 10 et 20 et 0,3DH au-delà.
Ecrivez un algorithme qui demande à l’utilisateur le nombre de photocopies effectuées, qui calcule et affiche le prix à payer

Tests imbriqués: corrigé de l'exercice

Variables copies : entier
                prix : réel
 Début
         Ecrire ("Nombre de photocopies : ")
Lire (copies)
Si (copies < 10) Alors
                          prix ← copies*0.5
Sinon Si (copies) < 20
                                 prix ← copies*0.4
                        Sinon
                                 prix ← copies*0.3
                        Finsi
Finsi                    
       Ecrire (“Le prix à payer est : ”, prix)
Fin