Leçon 11 sur 20

Chapitre 11 — Fonctions et procédures

Décomposer un problème et construire des solutions réutilisables

 

Fiche pédagogique du chapitre

Objectifs d’apprentissage

À la fin de ce chapitre, l’étudiant devra être capable de :

  • expliquer le principe de la modularité et son intérêt dans la résolution de problèmes ;
  • décomposer un algorithme complexe en sous-programmes cohérents ;
  • déclarer et appeler une procédure avec ou sans paramètres ;
  • déclarer une fonction et utiliser sa valeur de retour dans une expression ;
  • distinguer une procédure d’une fonction ;
  • identifier les paramètres formels et les paramètres effectifs ;
  • expliquer le passage par valeur et le passage par référence ;
  • utiliser des paramètres d’entrée, de sortie et d’entrée-sortie ;
  • distinguer une variable locale d’une variable globale ;
  • raisonner sur la portée et la durée de vie des variables ;
  • tester indépendamment un sous-programme ;
  • concevoir un programme modulaire de gestion des notes.

Prérequis

  • maîtriser les variables, constantes et types de données ;
  • savoir utiliser les structures conditionnelles et répétitives ;
  • savoir manipuler les tableaux à une dimension ;
  • savoir écrire et tracer un algorithme complet ;
  • connaître les principes de test et de validation.

Plan du chapitre

11.1 Principe de la modularité

11.2 Procédures

11.3 Fonctions

11.4 Paramètres

11.5 Portée des variables

Applications, travaux dirigés, corrigés et synthèse

Organisation pédagogique indicative

Activité

Durée indicative

Objectif principal

Cours3 hComprendre la modularité, les sous-programmes et la portée.
Travaux dirigés3 hDécomposer des problèmes et tracer les appels.
Travaux pratiques3 hImplémenter fonctions et procédures dans un langage.
Travail personnel2 hRésoudre des exercices de conception modulaire.
Idée centrale : un sous-programme reçoit éventuellement des données, réalise une tâche précise et fournit un résultat ou un effet attendu. Il doit avoir une responsabilité claire et pouvoir être testé séparément.

Introduction à la modularité

Lorsqu’un algorithme devient long, il devient difficile à comprendre, à tester et à modifier. Une méthode efficace consiste à le décomposer en plusieurs sous-programmes. Chaque sous-programme réalise une tâche limitée : lire une valeur, calculer une moyenne, rechercher un maximum, afficher un tableau ou vérifier une condition.

Cette organisation est appelée modularité. Elle permet de construire progressivement une solution à partir de blocs simples. Les fonctions et les procédures constituent les principaux outils de cette décomposition en algorithmique structurée.

Un programme modulaire ne doit pas être une simple découpe arbitraire. Les modules doivent correspondre à des responsabilités cohérentes, posséder des interfaces explicites et limiter leurs dépendances avec le reste du programme.

Vocabulaire : les termes sous-programme, module, routine et sous-routine peuvent désigner une unité de traitement. Dans ce chapitre, nous utiliserons surtout fonction et procédure.

11.1 Principe de la modularité

11.1.1 Décomposition d’un problème complexe

Décomposer un problème consiste à identifier des sous-problèmes plus simples, puis à définir un sous-programme pour chacun d’eux. Le programme principal organise les appels et coordonne les résultats.

Par exemple, un programme de gestion des notes peut être décomposé en cinq tâches : saisir les notes, vérifier leur validité, calculer la moyenne, déterminer la meilleure note et afficher un bilan.

Problème global

Sous-problèmes possibles

Sous-programmes

Gestion des notesSaisir, valider, calculer, rechercher, afficherSaisirNotes, NoteValide, Moyenne, Maximum, AfficherBilan
Gestion d’un stockLire les produits, chercher, mettre à jour, afficherLireStock, ChercherProduit, ModifierQuantite, AfficherStock
Analyse d’un texteNettoyer, compter, rechercher, vérifierNettoyer, CompterMots, Rechercher, EstPalindrome
Méthode : pour chaque sous-problème, poser la question : quelles données faut-il fournir, quel résultat faut-il obtenir et quels effets sont autorisés ?

11.1.2 Réutilisation du code

Un traitement écrit une seule fois peut être appelé plusieurs fois avec des données différentes. Cette réutilisation évite la duplication du code et réduit le risque d’obtenir plusieurs versions incohérentes d’un même calcul.

Exemple de réutilisation d’une fonction

Fonction Carre(x : Réel) : Réel
Début
    Retourner x * x
FinFonction

aireDisque <- PI * Carre(rayon)
distance2 <- Carre(dx) + Carre(dy)

Dans cet exemple, la fonction Carre est définie une seule fois. Elle peut être utilisée dans plusieurs calculs sans réécrire l’expression x × x.

11.1.3 Lisibilité

Des noms de sous-programmes explicites rendent le programme principal proche d’une description du problème. Le lecteur peut comprendre l’enchaînement général sans connaître immédiatement tous les détails de calcul.

Version peu lisible

Version modulaire

Une longue suite de lectures, boucles et testsSaisirNotes(notes, n)
Calcul intégré au milieu du programmemoyenne <- CalculerMoyenne(notes, n)
Recherche répétée du maximummaxi <- MaximumTableau(notes, n)
Affichages dispersésAfficherBilan(moyenne, maxi)

11.1.4 Maintenance

La maintenance regroupe les corrections, améliorations et adaptations effectuées après la première version. Si chaque traitement est isolé dans un module, une modification locale influence moins le reste du programme.

  • Correction : une erreur dans le calcul de la moyenne est corrigée dans une seule fonction.
  • Évolution : une nouvelle règle d’admission peut être ajoutée dans une fonction dédiée.
  • Adaptation : l’affichage peut changer sans modifier les calculs.
  • Remplacement : un algorithme lent peut être remplacé en conservant la même interface.

11.1.5 Test indépendant

Chaque sous-programme doit pouvoir être testé avec des jeux d’essai spécifiques. Tester indépendamment réduit la difficulté du diagnostic : lorsqu’une fonction Maximum est correcte, on peut se concentrer sur les autres modules.

Sous-programme

Jeu d’essai

Résultat attendu

Maximum(4, 9)a = 4, b = 99
EstPremier(2)n = 2Vrai
EstPremier(15)n = 15Faux
Moyenne([10, 14, 16], 3)tableau de trois notes13,33 environ
Bonne pratique : un sous-programme doit être court, avoir une responsabilité principale et posséder un nom décrivant clairement son action.

11.1.6 Cohésion et dépendances

La cohésion mesure à quel point les instructions d’un module participent à une même tâche. Un module cohérent ne mélange pas la saisie, le calcul et l’affichage sans nécessité. Les dépendances doivent également être limitées : les données utiles sont transmises par paramètres plutôt que lues directement dans des variables globales.

Critère

Situation souhaitable

Situation à éviter

ResponsabilitéUne tâche clairement définiePlusieurs tâches sans lien direct
InterfacePeu de paramètres, bien nommésNombreux paramètres ambigus
DépendancesDonnées reçues explicitementUsage caché de variables globales
EffetsEffets annoncés et limitésModifications imprévues de données

11.2 Procédures

11.2.1 Définition

Une procédure est un sous-programme qui réalise une action. Elle peut recevoir des paramètres et modifier certaines données, mais elle ne fournit pas directement une valeur utilisable dans une expression.

Une procédure est adaptée à des actions comme afficher un message, remplir un tableau, échanger deux valeurs, modifier un enregistrement ou produire plusieurs résultats par paramètres de sortie.

11.2.2 Déclaration d’une procédure

Structure générale

Procédure NomProcedure(paramètres éventuels)
Variables
    déclarations locales
Début
    instructions
FinProcédure

La déclaration indique le nom de la procédure, ses paramètres éventuels, ses variables locales et les instructions exécutées lors de chaque appel.

11.2.3 Appel d’une procédure

Appeler une procédure signifie demander l’exécution de ses instructions. Une fois la procédure terminée, l’exécution reprend à l’instruction située immédiatement après l’appel.

Procédure sans paramètre et appels

Procédure AfficherLigne()
Début
     Écrire("--------------------")
FinProcédure

Algorithme Principal
Début
    AfficherLigne()
    Écrire("Résultats")
    AfficherLigne()
Fin

Étape

Instruction exécutée

Effet

1Premier appel à AfficherLigneAffiche une ligne.
2Écrire("Résultats")Affiche le titre.
3Deuxième appel à AfficherLigneAffiche une seconde ligne.

11.2.4 Procédure avec paramètres

Les paramètres rendent une procédure adaptable. Une même procédure peut produire des résultats différents selon les valeurs transmises lors de l’appel.

Exemple avec deux paramètres d’entrée

Procédure AfficherMessage(message : Chaîne, repetitions : Entier)
Variables
    i : Entier
Début
    Pour i allant de 1 à repetitions Faire
        Écrire(message)
    FinPour
FinProcédure

AfficherMessage("Bienvenue", 3)

11.2.5 Procédures avec ou sans paramètres

Forme

Exemple

Usage

Sans paramètreAfficherMenu()Action toujours identique ou dépendant de données internes contrôlées.
Avec entréeAfficherTableau(T, n)Action adaptée aux données reçues.
Avec sortieLireValeurs(a, b)Produit des résultats transmis au programme appelant.
Avec entrée-sortieEchanger(a, b)Modifie des données existantes.

11.2.6 Exemple : échange de deux variables

Une procédure d’échange modifie deux variables du programme appelant. Elle utilise donc des paramètres d’entrée-sortie transmis par référence.

Procédure d’échange

Procédure Echanger(EntréeSortie a : Réel, EntréeSortie b : Réel)
Variables
    temporaire : Réel
Début
    temporaire <- a
    a <- b
    b <- temporaire
FinProcédure

Avant l’appel

Appel

Après l’appel

x = 4, y = 9Echanger(x, y)x = 9, y = 4
Attention : si a et b étaient transmis uniquement par valeur, l’échange serait effectué sur des copies locales et x et y resteraient inchangés.

11.3 Fonctions

11.3.1 Définition

Une fonction est un sous-programme qui calcule et retourne une valeur. Elle reçoit éventuellement des paramètres et possède un type de retour. La valeur produite peut être affectée à une variable, comparée, affichée ou intégrée dans une expression.

11.3.2 Déclaration d’une fonction

Structure générale

Fonction NomFonction(paramètres éventuels) : TypeRetour
Variables
    déclarations locales
Début
    instructions
    Retourner valeur
FinFonction

L’instruction Retourner termine la fonction et transmet une valeur au programme appelant. La valeur retournée doit être compatible avec le type annoncé.

11.3.3 Valeur de retour et type retourné

Fonction

Type retourné

Exemple de résultat

Maximum(a, b)Réel12,5
EstPair(n)BooléenVrai ou Faux
PremiereLettre(nom)Caractère'A'
NomComplet(prenom, nom)Chaîne"Sara Amrani"
NombreVoyelles(texte)Entier6
Règle : une fonction doit retourner une valeur dans tous les chemins d’exécution possibles. Les conditions doivent être organisées de manière à éviter un chemin sans Retourner.

11.3.4 Appel d’une fonction dans une expression

Exemples d’appels

m <- Maximum(a, b)
Écrire(Maximum(x, y))
Si EstPremier(n) Alors
    Écrire(n, " est premier")
FinSi

resultat <- 2 * Carre(x) + Carre(y)

L’appel est remplacé conceptuellement par la valeur retournée. Avant d’évaluer l’expression complète, le système exécute la fonction et récupère son résultat.

11.3.5 Fonction ou procédure ?

Critère

Fonction

Procédure

But principalCalculer une valeurRéaliser une action
Résultat directUne valeur retournéeAucune valeur directe
Utilisation dans une expressionOuiNon
Effets sur les paramètresÀ limiter en généralPossibles et souvent explicites
ExemplesMoyenne, Maximum, EstPremierAfficher, Remplir, Echanger

Certains langages représentent toutes les routines comme des fonctions, éventuellement sans valeur significative. En pseudo-code, la distinction reste utile pour clarifier l’intention.

11.3.6 Fonctions sans effet de bord

Une fonction sans effet de bord calcule son résultat uniquement à partir de ses paramètres et ne modifie aucune donnée externe. À paramètres identiques, elle retourne le même résultat. Ce comportement facilite les tests et le raisonnement.

Fonction recommandée

Fonction à éviter

CalculerMoyenne(T, n) retourne une valeurCalculerMoyenne modifie une variable globale moyenne
EstPremier(n) retourne Vrai ou FauxEstPremier affiche des messages et change n
Maximum(a, b) ne modifie pas a et bMaximum réordonne silencieusement les arguments

11.4 Paramètres

11.4.1 Paramètres formels et effectifs

Les paramètres formels apparaissent dans la déclaration du sous-programme. Ils décrivent les données attendues. Les paramètres effectifs, aussi appelés arguments, sont les valeurs ou variables fournies lors de l’appel.

Paramètres formels et effectifs

Fonction Maximum(a : Réel, b : Réel) : Réel
...

x <- 7
y <- 12
plusGrand <- Maximum(x, y)

Élément

Dans l’exemple

Rôle

Paramètres formelsa et bNoms locaux utilisés dans la fonction.
Paramètres effectifsx et yDonnées transmises lors de l’appel.
Valeur retournée12Résultat affecté à plusGrand.

11.4.2 Correspondance des paramètres

La correspondance se fait généralement selon l’ordre. Le premier argument est associé au premier paramètre formel, le second au second, etc. Le nombre et les types doivent être compatibles.

Appel

Validité

Explication

Maximum(4, 9)ValideDeux nombres transmis dans le bon ordre.
Maximum(x)InvalideUn argument manque.
Maximum("A", 9)InvalideType incompatible avec Réel.
AfficherMessage(3, "Bonjour")Invalide selon la déclarationOrdre des arguments inversé.

11.4.3 Passage par valeur

Lors d’un passage par valeur, le sous-programme reçoit une copie de la valeur. Une modification du paramètre formel ne modifie pas la variable originale du programme appelant.

Effet du passage par valeur

Procédure AjouterUn(Valeur x : Entier)
Début
    x <- x + 1
FinProcédure

a <- 5
AjouterUn(a)
Écrire(a)     // affiche 5

Moment

a dans le programme principal

x dans la procédure

Avant l’appel5Non créé
Pendant l’appel5Copie initialisée à 5 puis modifiée à 6
Après l’appel5Détruit

11.4.4 Passage par référence

Lors d’un passage par référence, le paramètre désigne la variable originale. Une modification effectuée dans le sous-programme est donc visible après l’appel. Ce mécanisme est utilisé pour les paramètres de sortie ou d’entrée-sortie.

Effet du passage par référence

Procédure AjouterUn(Référence x : Entier)
Début
    x <- x + 1
FinProcédure

a <- 5
AjouterUn(a)
Écrire(a)     // affiche 6
 
Précaution : le passage par référence crée un effet sur le programme appelant. Cet effet doit être annoncé clairement par le mode du paramètre et par le nom du sous-programme. 

11.4.5 Paramètres d’entrée, de sortie et d’entrée-sortie

Mode

Valeur initiale utilisée ?

Modifié par le module ?

Exemple

EntréeOuiNonCalculerMoyenne(T, n)
SortieNon nécessaireOuiLireCoordonnees(x, y)
Entrée-sortieOuiOuiEchanger(a, b)

Procédure produisant deux résultats

Procédure DivisionEuclidienne(Entrée a : Entier,
                              Entrée b : Entier,
                              Sortie quotient : Entier,
                              Sortie reste : Entier)
Début
    quotient <- a div b
    reste <- a mod b
FinProcédure

11.4.6 Paramètres tableaux

Un tableau peut être transmis comme paramètre. Sa taille logique doit généralement être transmise séparément lorsque le tableau possède une capacité supérieure au nombre d’éléments utilisés.

Fonction recevant un tableau

Fonction SommeTableau(Entrée T : Tableau de Réels,
                        Entrée n : Entier) : Réel
Variables
    i : Entier
    somme : Réel
Début
    somme <- 0
    Pour i allant de 1 à n Faire
        somme <- somme + T[i]
    FinPour
    Retourner somme
FinFonction
 
Convention : dans ce cours, un tableau utilisé seulement en lecture est un paramètre d’entrée. Un tableau rempli ou modifié est un paramètre de sortie ou d’entrée-sortie. 

11.4.7 Validation des paramètres

Un sous-programme doit préciser les conditions nécessaires à son fonctionnement. Ces conditions sont parfois appelées préconditions. Par exemple, une fonction de moyenne suppose n > 0, et une division suppose un diviseur non nul.

Sous-programme

Précondition

Réaction possible

Moyenne(T, n)n > 0Refuser l’appel ou retourner une indication d’erreur.
Racine(x)x ≥ 0Contrôler x avant le calcul.
Division(a, b)b ≠ 0Demander un nouveau diviseur.
Acces(T, i)1 ≤ i ≤ nVérifier les bornes.

11.5 Portée des variables

11.5.1 Variable locale

Une variable locale est déclarée dans un sous-programme. Elle est accessible uniquement à l’intérieur de ce sous-programme. Elle sert aux calculs intermédiaires et disparaît généralement lorsque l’appel se termine.

La variable resultat est locale

Fonction Carre(x : Réel) : Réel
Variables
    resultat : Réel
Début
    resultat <- x * x
    Retourner resultat
FinFonction

Le programme principal ne peut pas utiliser directement resultat. Cette limitation protège les détails internes de la fonction.

11.5.2 Variable globale

Une variable globale est déclarée en dehors des sous-programmes et peut être accessible par plusieurs modules. Elle peut sembler pratique, mais elle crée des dépendances cachées : un module peut modifier une donnée utilisée ailleurs sans que l’appel l’indique.

Exemple d’accès à une variable globale

Variables globales
    compteur : Entier

Procédure IncrementerCompteur()
Début
    compteur <- compteur + 1
FinProcédure

11.5.3 Durée de vie d’une variable

Catégorie

Création

Destruction habituelle

Accessibilité

Variable localeAu début de l’appelÀ la fin de l’appelDans le module concerné
ParamètreAu début de l’appelÀ la fin de l’appelDans le module concerné
Variable globaleAu lancement du programmeÀ la fin du programmeDans plusieurs modules selon les règles

11.5.4 Masquage de noms

Si une variable locale porte le même nom qu’une variable globale, elle peut masquer la variable globale dans le sous-programme. Cette situation rend la lecture ambiguë et doit être évitée.

Exemple de masquage

Variable globale
    total : Réel

Fonction Exemple(x : Réel) : Réel
Variables
    total : Réel     // masque la variable globale
Début
    total <- x + 1
    Retourner total
FinFonction

11.5.5 Risques liés aux variables globales

  • modification involontaire depuis plusieurs sous-programmes ;
  • difficulté à savoir quelle instruction a changé la valeur ;
  • tests indépendants plus complexes ;
  • dépendances cachées entre les modules ;
  • réutilisation limitée dans un autre programme ;
  • risques supplémentaires lors d’exécutions simultanées.

Approche fragile

Approche recommandée

Une fonction lit directement le tableau global NotesLe tableau Notes est transmis en paramètre
Une procédure modifie une variable globale moyenneLa moyenne est retournée par une fonction
Le nombre d’éléments est impliciten est transmis explicitement
Plusieurs modules écrivent dans le même étatUn module contrôle chaque modification
Recommandation : privilégier les variables locales et les paramètres. Réserver les variables globales à des constantes ou à des états réellement partagés et contrôlés.


 

 

Applications guidées

Application 1 — Fonction calculant le maximum

Concevoir une fonction qui retourne la plus grande de deux valeurs réelles. En cas d’égalité, la valeur commune est retournée.

Solution

Fonction Maximum(a : Réel, b : Réel) : Réel
Début
    Si a >= b Alors
        Retourner a
    Sinon
        Retourner b
    FinSi
FinFonction

a

b

Condition a ≥ b

Résultat

712Faux12
93Vrai9
55Vrai5
-2-8Vrai-2

Pour obtenir le maximum de trois valeurs, on peut réutiliser la fonction précédente :

Réutilisation

Fonction Maximum3(a : Réel, b : Réel, c : Réel) : Réel
Début
    Retourner Maximum(Maximum(a, b), c)
FinFonction

Application 2 — Fonction vérifiant si un nombre est premier

Un entier n est premier s’il est supérieur ou égal à 2 et s’il possède exactement deux diviseurs positifs : 1 et lui-même. Il suffit de rechercher un diviseur entre 2 et la racine carrée de n.

Solution

Fonction EstPremier(n : Entier) : Booléen
Variables
    d : Entier
Début
    Si n < 2 Alors
        Retourner Faux
    FinSi

    d <- 2
    TantQue d * d <= n Faire
        Si n mod d = 0 Alors
            Retourner Faux
        FinSi
        d <- d + 1
    FinTantQue

    Retourner Vrai
FinFonction


 

 

n

Diviseurs testés

Résultat

Justification

1AucunFauxInférieur à 2.
2AucunVraiPremier.
153Faux15 mod 3 = 0.
172, 3, 4VraiAucun diviseur trouvé.
492 à 7Faux49 mod 7 = 0.
Optimisation : tester jusqu’à d × d ≤ n évite d’examiner tous les nombres jusqu’à n − 1.

Application 3 — Procédure affichant un tableau

La procédure reçoit un tableau et son nombre d’éléments. Elle affiche chaque valeur précédée de son indice.

Solution

Procédure AfficherTableau(Entrée T : Tableau de Réels,
                           Entrée n : Entier)
Variables
    i : Entier
Début
    Pour i allant de 1 à n Faire
        Écrire("T[", i, "] = ", T[i])
    FinPour
FinProcédure

Entrée

Affichage produit

T = [12, 8, 15], n = 3T[1] = 12 ; T[2] = 8 ; T[3] = 15
T = [4,5], n = 1T[1] = 4

Le paramètre T est un paramètre d’entrée : la procédure lit les valeurs sans les modifier.

Application 4 — Fonction calculant la moyenne d’un tableau

La fonction calcule la somme des n valeurs, puis la divise par n. La précondition n > 0 doit être respectée.

Solution

Fonction MoyenneTableau(Entrée T : Tableau de Réels,
                          Entrée n : Entier) : Réel
Variables
    somme : Réel
    i : Entier
Début
    somme <- 0
    Pour i allant de 1 à n Faire
        somme <- somme + T[i]
    FinPour
    Retourner somme / n
FinFonction

T

n

Somme

Moyenne

[10, 12, 14]33612
[8, 15, 11, 6]44010
[13,5]113,513,5
Cas limite : si n = 0, la division est impossible. Le programme principal doit empêcher l’appel ou une stratégie d’erreur doit être définie.

Application 5 — Programme modulaire de gestion des notes

On souhaite saisir les notes d’une classe, calculer la moyenne, déterminer la meilleure note, compter les étudiants admis et afficher un bilan. Une note est valide si elle appartient à l’intervalle [0, 20]. Un étudiant est admis si sa note est supérieure ou égale à 10.

a) Décomposition proposée

Module

Nature

Responsabilité

NoteValideFonctionVérifier qu’une note appartient à [0, 20].
SaisirNotesProcédureRemplir le tableau en répétant les saisies invalides.
MoyenneTableauFonctionCalculer la moyenne des notes.
MaximumTableauFonctionRetourner la meilleure note.
CompterAdmisFonctionCompter les notes supérieures ou égales à 10.
AfficherBilanProcédurePrésenter les résultats.

b) Validation et saisie

Modules de saisie

Fonction NoteValide(note : Réel) : Booléen
Début
    Retourner note >= 0 ET note <= 20
FinFonction

Procédure SaisirNotes(Sortie Notes : Tableau de Réels,
                      Entrée n : Entier)
Variables
    i : Entier
Début
    Pour i allant de 1 à n Faire
        Répéter
            Écrire("Note ", i, " : ")
            Lire(Notes[i])
        JusquÀ NoteValide(Notes[i])
    FinPour
FinProcédure

c) Calculs

Fonctions de traitement

Fonction MaximumTableau(T : Tableau de Réels, n : Entier) : Réel
Variables
    i : Entier
    maxi : Réel
Début
    maxi <- T[1]
    Pour i allant de 2 à n Faire
        Si T[i] > maxi Alors
            maxi <- T[i]
        FinSi
    FinPour
    Retourner maxi
FinFonction

Fonction CompterAdmis(T : Tableau de Réels, n : Entier) : Entier
Variables
    i, compteur : Entier
Début
    compteur <- 0
    Pour i allant de 1 à n Faire
        Si T[i] >= 10 Alors
            compteur <- compteur + 1
        FinSi
    FinPour
    Retourner compteur
FinFonction

d) Affichage du bilan

Procédure d’affichage

Procédure AfficherBilan(moyenne : Réel,
                         meilleure : Réel,
                         admis : Entier,
                         n : Entier)
Début
    Écrire("Moyenne de la classe : ", moyenne)
    Écrire("Meilleure note : ", meilleure)
    Écrire("Nombre d’admis : ", admis, " sur ", n)
FinProcédure

e) Programme principal

Programme principal

Algorithme GestionNotes
Constantes
    CAPACITE <- 100
Variables
    Notes : Tableau[1..CAPACITE] de Réels
    n, admis : Entier
    moyenne, meilleure : Réel
Début
    Répéter
        Écrire("Nombre d’étudiants : ")
        Lire(n)
    JusquÀ n >= 1 ET n <= CAPACITE

    SaisirNotes(Notes, n)
    moyenne <- MoyenneTableau(Notes, n)
    meilleure <- MaximumTableau(Notes, n)
    admis <- CompterAdmis(Notes, n)
    AfficherBilan(moyenne, meilleure, admis, n)
Fin

Notes

Moyenne

Meilleure

Admis

[12, 8, 15, 10, 5]10153 sur 5
[14, 16, 11]13,67 environ163 sur 3
[4, 7, 9]6,67 environ90 sur 3
Lecture du programme : le programme principal décrit l’enchaînement global. Les détails de validation, de parcours et de calcul sont confiés à des modules indépendants.

Traçage des appels de sous-programmes

Lors d’un appel, les paramètres sont initialisés, les variables locales sont créées, le corps du module s’exécute, puis la valeur éventuelle est retournée. Le contexte du programme appelant est ensuite repris.

Exemple à tracer

x <- 4
y <- 9
z <- Maximum(x, y)
Écrire(z)

Étape

Contexte actif

État ou action

1Programme principalx = 4, y = 9
2Appel de Maximuma reçoit 4, b reçoit 9
3Fonction Maximuma ≥ b est Faux
4Fonction MaximumRetourner b, donc 9
5Programme principalz reçoit 9
6Programme principalAffichage de 9

Dans le cas d’appels imbriqués, la fonction la plus interne est évaluée en premier. Par exemple, Maximum(Maximum(3, 7), 5) commence par calculer Maximum(3, 7), puis appelle Maximum(7, 5).

Erreurs fréquentes et bonnes pratiques

Erreur fréquente

Conséquence

Correction

Oublier Retourner dans une fonctionAucune valeur exploitableRetourner une valeur dans chaque chemin.
Confondre procédure et fonctionAppel invalide dans une expressionChoisir selon l’intention du module.
Nombre d’arguments incorrectErreur d’appelRespecter l’interface.
Type d’argument incompatibleErreur ou conversion risquéeVérifier les types.
Modifier un paramètre d’entréeEffet inattenduUtiliser une variable locale.
Utiliser trop de variables globalesDépendances cachéesTransmettre les données par paramètres.
Créer un module trop longLisibilité faibleDécomposer en responsabilités plus petites.
Donner un nom vagueIntention incompréhensibleEmployer un verbe ou un nom précis.

Règles de nommage

  • Fonctions booléennes : utiliser une question comme EstPremier, NoteValide ou Contient.
  • Fonctions de calcul : utiliser un nom comme Moyenne, Maximum ou NombreVoyelles.
  • Procédures d’action : utiliser un verbe comme Afficher, Saisir, Trier ou Echanger.
  • Paramètres : choisir des noms liés à leur rôle et éviter a, b, c lorsque le contexte est complexe.
  • Variables locales : préférer somme, compteur, indice et maximum à des noms génériques.
Interface claire : la déclaration d’un sous-programme doit suffire à comprendre les données attendues, les données modifiées et le résultat produit.


 

 

Travaux dirigés

Exercice 1 — Valeur absolue

Écrire une fonction ValeurAbsolue(x) qui retourne la valeur absolue d’un réel. Proposer des jeux d’essai contenant une valeur positive, une valeur négative et zéro.

Exercice 2 — Pair ou impair

Écrire une fonction EstPair(n) qui retourne Vrai lorsque n est divisible par 2. Utiliser cette fonction dans un programme qui compte les nombres pairs d’un tableau.

Exercice 3 — Conversion de température

Écrire une fonction CelsiusVersFahrenheit(c) utilisant la formule f = 1,8 × c + 32. Écrire ensuite une procédure AfficherConversion(c) qui affiche les deux températures.

Exercice 4 — Minimum et position

Écrire une procédure MinimumEtPosition(T, n, minimum, position) qui produit la plus petite valeur du tableau et sa première position. Identifier le mode de chaque paramètre.

Exercice 5 — Normalisation de notes

Écrire une procédure LimiterNotes(T, n) qui remplace toute note inférieure à 0 par 0 et toute note supérieure à 20 par 20. Le tableau doit-il être transmis en entrée ou en entrée-sortie ? Justifier.

Exercice 6 — Puissance entière

Écrire une fonction Puissance(x, n) qui calcule x puissance n pour n entier positif ou nul, sans utiliser d’opérateur de puissance.

Exercice 7 — Statistiques d’un tableau

Décomposer le calcul du minimum, du maximum, de la somme et de la moyenne en plusieurs fonctions. Écrire une procédure AfficherStatistiques qui utilise ces fonctions.

Exercice 8 — Analyse d’un identifiant

Écrire une fonction IdentifiantValide(texte) qui retourne Vrai si la chaîne contient entre 5 et 12 caractères, commence par une lettre et ne contient que des lettres, des chiffres ou le caractère souligné.

Exercice 9 — Portée des variables

Analyser un pseudo-code contenant une variable globale total et une variable locale portant le même nom. Expliquer quelle variable est utilisée dans chaque instruction et proposer une version sans masquage.

Exercice 10 — Mini-projet modulaire

Concevoir un programme de gestion de cinq produits : saisie des prix, validation, calcul du prix moyen, recherche du prix maximal et affichage des produits dont le prix est supérieur à la moyenne. Proposer les fonctions et procédures nécessaires.

Corrigés indicatifs

Corrigé 1 — Valeur absolue

Fonction ValeurAbsolue(x : Réel) : Réel
Début
    Si x < 0 Alors
        Retourner -x
    Sinon
        Retourner x
    FinSi
FinFonction

x

Résultat attendu

55
-3,23,2
00

Corrigé 2 — Pair ou impair

Fonction EstPair(n : Entier) : Booléen
Début
    Retourner n mod 2 = 0
FinFonction

Fonction CompterPairs(T : Tableau d’Entiers, n : Entier) : Entier
Variables
    i, compteur : Entier
Début
    compteur <- 0
    Pour i allant de 1 à n Faire
        Si EstPair(T[i]) Alors
            compteur <- compteur + 1
        FinSi
    FinPour
    Retourner compteur
FinFonction

Corrigé 3 — Conversion de température

Fonction CelsiusVersFahrenheit(c : Réel) : Réel
Début
    Retourner 1.8 * c + 32
FinFonction

Procédure AfficherConversion(c : Réel)
Variables
    f : Réel
Début
    f <- CelsiusVersFahrenheit(c)
    Écrire(c, " °C = ", f, " °F")
FinProcédure

Corrigé 4 — Minimum et position

Procédure MinimumEtPosition(Entrée T : Tableau de Réels,
                            Entrée n : Entier,
                            Sortie minimum : Réel,
                            Sortie position : Entier)
Variables
    i : Entier
Début
    minimum <- T[1]
    position <- 1
    Pour i allant de 2 à n Faire
        Si T[i] < minimum Alors
            minimum <- T[i]
            position <- i
        FinSi
    FinPour
FinProcédure

Corrigé 5 — Normalisation de notes

Procédure LimiterNotes(EntréeSortie T : Tableau de Réels,
                       Entrée n : Entier)
Variables
    i : Entier
Début
    Pour i allant de 1 à n Faire
        Si T[i] < 0 Alors
            T[i] <- 0
        SinonSi T[i] > 20 Alors
            T[i] <- 20
        FinSi
    FinPour
FinProcédure

Le tableau est un paramètre d’entrée-sortie, car ses valeurs initiales sont lues puis éventuellement modifiées.

Corrigé 6 — Puissance entière

Fonction Puissance(x : Réel, n : Entier) : Réel
Variables
    i : Entier
    resultat : Réel
Début
    resultat <- 1
    Pour i allant de 1 à n Faire
        resultat <- resultat * x
    FinPour
    Retourner resultat
FinFonction

La précondition est n ≥ 0. Pour n = 0, la boucle ne s’exécute pas et la fonction retourne 1.

Corrigé 7 — Statistiques d’un tableau

Une solution modulaire comporte les fonctions SommeTableau, MinimumTableau, MaximumTableau et MoyenneTableau. La procédure AfficherStatistiques appelle ces fonctions et affiche leurs résultats. La fonction MoyenneTableau peut réutiliser SommeTableau afin d’éviter la duplication.

Fonction MoyenneTableau(T : Tableau de Réels, n : Entier) : Réel
Début
    Retourner SommeTableau(T, n) / n
FinFonction

Procédure AfficherStatistiques(T : Tableau de Réels, n : Entier)
Début
    Écrire("Minimum : ", MinimumTableau(T, n))
    Écrire("Maximum : ", MaximumTableau(T, n))
    Écrire("Moyenne : ", MoyenneTableau(T, n))
FinProcédure

Corrigé 8 — Analyse d’un identifiant

La fonction vérifie d’abord la longueur, puis le premier caractère, puis parcourt tous les caractères. Les fonctions auxiliaires EstLettre et EstChiffre peuvent être réutilisées.

Fonction IdentifiantValide(texte : Chaîne) : Booléen
Variables
    i : Entier
    c : Caractère
Début
    Si Longueur(texte) < 5 OU Longueur(texte) > 12 Alors
        Retourner Faux
    FinSi
    Si NON EstLettre(texte[1]) Alors
        Retourner Faux
    FinSi
    Pour i allant de 1 à Longueur(texte) Faire
        c <- texte[i]
        Si NON EstLettre(c) ET NON EstChiffre(c) ET c <> "_" Alors
            Retourner Faux
        FinSi
    FinPour
    Retourner Vrai
FinFonction

Corrigé 9 — Portée des variables

Lorsqu’un nom local masque un nom global, les instructions du sous-programme utilisent la variable locale. Pour supprimer l’ambiguïté, il faut renommer la variable locale ou, mieux, transmettre la donnée nécessaire par paramètre et éviter la variable globale.

Corrigé 10 — Mini-projet modulaire

Module proposé

Nature

Rôle

PrixValideFonctionVérifier qu’un prix est positif ou nul.
SaisirPrixProcédureRemplir le tableau avec validation.
MoyennePrixFonctionCalculer le prix moyen.
MaximumPrixFonctionRechercher le prix maximal.
AfficherSuperieursProcédureAfficher les prix supérieurs à la moyenne.

Le programme principal lit le nombre de produits, appelle SaisirPrix, calcule la moyenne et le maximum, puis appelle AfficherSuperieurs. Chaque module peut être testé indépendamment.


 

 

Synthèse du chapitre

Notion

À retenir

ModularitéDécomposer un problème en sous-programmes cohérents.
ProcédureRéalise une action sans retourner directement une valeur.
FonctionRetourne une valeur compatible avec un type annoncé.
Paramètre formelNom déclaré dans l’interface du module.
Paramètre effectifValeur ou variable fournie lors de l’appel.
Passage par valeurLe module travaille sur une copie.
Passage par référenceLe module peut modifier la variable originale.
EntréeDonnée lue mais non modifiée.
SortieDonnée produite par le module.
Entrée-sortieDonnée lue puis modifiée.
Variable localeVisible uniquement dans son module.
Variable globaleAccessible plus largement, mais à utiliser avec prudence.

Checklist de conception d’un sous-programme

  • Le sous-programme réalise-t-il une seule tâche principale ?
  • Son nom décrit-il clairement son rôle ?
  • Les paramètres nécessaires sont-ils explicitement déclarés ?
  • Le mode entrée, sortie ou entrée-sortie est-il correct ?
  • La fonction retourne-t-elle une valeur dans tous les cas ?
  • Les variables locales sont-elles correctement initialisées ?
  • Les préconditions sont-elles vérifiées ?
  • Le module évite-t-il les variables globales inutiles ?
  • Peut-il être testé indépendamment avec plusieurs jeux d’essai ?
  • Son interface permet-elle une réutilisation dans un autre contexte ?

Glossaire

Terme

Définition

Sous-programmeBloc nommé regroupant des instructions pour une tâche déterminée.
ModularitéOrganisation d’un programme en modules indépendants et cohérents.
ProcédureSous-programme réalisant une action sans valeur de retour directe.
FonctionSous-programme retournant une valeur.
AppelInstruction qui déclenche l’exécution d’un sous-programme.
InterfaceNom, paramètres, modes et type de retour visibles par l’appelant.
Paramètre formelParamètre déclaré dans la définition du module.
Paramètre effectifArgument fourni au moment de l’appel.
Passage par valeurTransmission d’une copie de la donnée.
Passage par référenceTransmission d’un accès à la donnée originale.
PortéeZone du programme dans laquelle un nom est accessible.
Durée de viePériode pendant laquelle une variable existe en mémoire.
Effet de bordModification d’un état extérieur au résultat retourné.
PréconditionCondition qui doit être satisfaite avant l’appel.

Auto-évaluation

Pour chaque affirmation, indiquer : acquis, en cours d’acquisition ou à revoir.

Je suis capable de…

Auto-évaluation

décomposer un problème en sous-problèmes cohérents ; 
choisir entre une fonction et une procédure ; 
écrire la déclaration et l’appel d’une procédure ; 
écrire une fonction avec un type et une valeur de retour ; 
distinguer les paramètres formels des paramètres effectifs ; 
expliquer le passage par valeur et le passage par référence ; 
identifier les paramètres d’entrée, de sortie et d’entrée-sortie ; 
expliquer la portée et la durée de vie d’une variable ; 
éviter les variables globales inutiles ; 
tester indépendamment un sous-programme ; 
construire un programme modulaire utilisant un tableau ; 
Conclusion : les fonctions et les procédures transforment un algorithme long en une organisation de modules compréhensibles, testables et réutilisables. La qualité d’un programme modulaire dépend autant de la clarté de ses interfaces que de la correction de ses calculs.