Cours Algorithmique L2 2023-2024
Cours Algorithmique L2 2023-2024
Sciences et Techniques
Cours d’Algorithmique
Proposé par Bienvenu ONDAMI ([email protected])
2023-2024
Table des matières
1. Avant-propos ........................................................................................................................................................... 4
Qu’est-ce qu’un algorithme ? En quoi l’étude des algorithmes est-elle utile ? Quel est le rôle des algorithmes
par rapport aux autres technologies informatiques ? Ce cours a pour objectif de répondre à ces questions....... 4
2. Introduction à l’algorithmique ................................................................................................................................ 4
2.1. Notions élémentaires ....................................................................................................................................... 4
2.1.1. Informatique ............................................................................................................................................. 4
2.1.2. Sofrware.................................................................................................................................................... 4
2.1.3. Hardware .................................................................................................................................................. 4
2.1.4. Algorithme ................................................................................................................................................ 4
2.2. L’algorithmique et programmation ................................................................................................................ 5
2.2.1. Définition .................................................................................................................................................. 5
2.2.2. Principe général ........................................................................................................................................ 6
2.3. Caractéristiques des algorithmes ................................................................................................................... 7
2.3.1. Structure générale ................................................................................................................................... 7
2.3.2. Convention d’écriture d’un algorithme .................................................................................................. 7
2.4. Les variables..................................................................................................................................................... 7
2.4.1. A quoi servent les variables.................................................................................................................... 7
2.4.2. Déclaration des variables ........................................................................................................................ 8
2.4.3. L’instruction d’affectation........................................................................................................................ 9
2.4.4. Expressions et opérateurs..................................................................................................................... 12
2.4.5. Remarques .............................................................................................................................................. 13
2.5. Lecture et écriture ......................................................................................................................................... 14
2.5.1. De quoi parle-t-on ? .............................................................................................................................. 14
2.5.2. Les instructions de lecture et d’écriture .............................................................................................. 14
2.6. Les tests ......................................................................................................................................................... 15
2.6.1. Structure d’un test ................................................................................................................................. 15
2.6.2. Qu’est-ce qu’une condition ? ................................................................................................................ 16
2.6.3. Conditions composées .......................................................................................................................... 17
2.6.4. Tests imbriqués ...................................................................................................................................... 18
2
2.6.5. Variables Booléennes ............................................................................................................................ 19
2.7. Les boucles..................................................................................................................................................... 20
2.7.1. A quoi ça sert ?...................................................................................................................................... 20
2.7.2. Boucler en comptant, ou compter en bouclant ................................................................................... 22
2.7.3. Des boucles dans des boucles ............................................................................................................. 24
2.7.4. Erreur à éviter ........................................................................................................................................ 25
2.8. Les tableaux ................................................................................................................................................... 26
2.8.1. Utilité des tableaux ................................................................................................................................ 26
2.8.2. Notation et utilisation algorithmique ................................................................................................... 27
2.8.3. Tableaux dynamiques ............................................................................................................................ 29
2.9. Procédures et fonctions ................................................................................................................................ 30
2.9.1. Fonctions personnalisées ...................................................................................................................... 30
2.9.2. Sous-Procédures .................................................................................................................................... 34
2.9.3. Variables publiques et privées ............................................................................................................. 37
3
1. Avant-propos
L'objectif de ce support est d’initier le lecteur à la résolution des problèmes par la programmation,
commençant par l’analyse du problème, la recherche de la solution ou la méthode pour résoudre ce
problème, l’écriture de cette solution sous forme d’un algorithme, et enfin la traduction de l’algorithme en
programme exécutable par la machine en utilisant un langage de programmation tel que le langage C++
qui fait l’objet d’un autre cours (Initiation à la programmation). Il s’agit d’un support pédagogique qui
couvre une partie fondamentale et essentielle de l’algorithmique constituant ainsi un prérequis important
pour la programmation. Il est destiné aux étudiants de L2.
Qu’est-ce qu’un algorithme ? En quoi l’étude des algorithmes est-elle utile ? Quel est le rôle des
algorithmes par rapport aux autres technologies informatiques ? Ce cours a pour objectif de répondre à
ces questions.
2. Introduction à l’algorithmique
2.1. Notions élémentaires
2.1.1. Informatique
L’informatique est la science du traitement automatique de l’information. Elle traite de deux aspects
complémentaires :
2.1.2. Sofrware
C’est un programme (ou ensemble de programmes) décrivant un traitement d’informations à réaliser par un
matériel informatique.
2.1.3. Hardware
C’est l’ensemble des éléments physiques (microprocesseur, mémoire, disques durs, ...) utilisés pour traiter les
informations.
2.1.4. Algorithme
✓ La notion d'algorithme est à la base de toute la programmation informatique. La définition la plus
simple que l’on peut associer à cette notion est qu’un algorithme est une suite ordonnée d’instructions
qui indique la démarche à suivre pour résoudre un problème ou effectuer une tâche.
4
✓ De façon informelle un algorithme est une procédure de calcul bien définie qui prend en entrée une
valeur, ou un ensemble de valeurs, et qui donne en sortie une valeur, ou un ensemble de valeurs. Un
algorithme est donc une séquence d’étapes de calcul qui transforment l’entrée en sortie.
✓ Un algorithme, est donc une suite d’instructions qui, une fois exécutée correctement, conduit à un
résultat donné. Si l’algorithme est juste, le résultat est le résultat voulu. Si l’algorithme est faux, le
résultat est, disons, aléatoire.
Pour fonctionner, un algorithme doit donc contenir uniquement des instructions compréhensibles par celui qui
devra l’exécuter.
Ce mode d’emploi précise comment faire un appel téléphonique. Il est composé d’une suite ordonnée
d’instructions (ouvrir, chercher/composez, appuyer) qui manipulent des données (téléphone, numéro, bouton)
pour réaliser la tâche d’appel.
La figure 1 ci-dessus illustre les deux phases nécessaires pour obtenir un code source :
✓ Phase d’algorithmique qui implique la recherche et l’écriture d’un algorithme.
5
✓ Phase de programmation qui consiste à traduire l’algorithme obtenu en un programme à l’aide d’un
langage de programmation (C/C++, Java, Python, …).
Dans la première phase, on doit définir les données qu’on dispose et les objectifs qu’on souhaite atteindre,
ainsi que prévoir des réponses à tous les cas possibles.
Apprendre l’algorithmique, c’est apprendre à manier la structure logique d’un programme informatique. Cette
dimension est présente quelle que soit le langage de programmation ; mais lorsqu’on programme dans un
langage (comme C++, Java, Python, ...) on doit en plus faire face aux problèmes de syntaxe, ou de types
d’instructions, propres à ce langage. Apprendre l’algorithmique de manière séparée, c’est donc sérier les
difficultés pour mieux les vaincre.
Supposons qu’on doit calculer la moyenne d’un étudiant pour un ensemble de matières. Donc, on doit :
✓ Définir le nombre des matières concernées ainsi que les notes et les coefficients.
✓ Réaliser les opérations suivantes :
- Multiplier chaque note d’une matière par son coefficient.
- Calculer la somme des résultats des multiplications.
- Diviser la somme obtenue par le total des coefficients,
✓ Afficher la moyenne de l’étudiant (résultat final).
Remarque
Lorsqu’on écrit un algorithme, les questions suivantes doivent être considérées :
✓ Quel est le résultat attendu ?
✓ Quelles sont les données nécessaires (informations requises) ?
✓ Comment faire (le traitement à réaliser) ?
6
2.3. Caractéristiques des algorithmes
2.3.1. Structure générale
Un algorithme se compose généralement de deux parties :
✓ Partie déclarative : appelée aussi entête de l’algorithme, elle contient généralement les déclarations
(des constantes, des variables, etc.).
✓ Partie corps de l’algorithme : constituée d’une ou plusieurs séquences d’instructions faisant appel à des
opérations de base à exécuter par l’ordinateur.
7
Les langages informatiques plus évolués (ce sont ceux que presque tout le monde emploie) se chargent
précisément, entre autres rôles, d’épargner au programmeur la gestion fastidieuse des emplacements mémoire
et de leurs adresses.
8
Nous n’emploierons pas ces types dans ce cours.
Ainsi,
9
Signifie que la valeur de Tutu est maintenant celle de Toto.
Notez bien que cette instruction n’a en rien modifié la valeur de Toto : une instruction d’affectation ne modifie
que ce qui est situé à gauche de la flèche.
Si Toto contenait 12, Tutu vaut maintenant 16. De même que précédemment, Toto vaut toujours 12.
Si Tutu valait 6, il vaut maintenant 7. La valeur de Tutu est modifiée, puisque Tutu est la variable située à
gauche de la flèche.
Pour revenir à présent sur le rôle des guillemets dans les chaînes de caractères et sur la confusion numéro 2
signalée plus haut, comparons maintenant deux algorithmes suivants :
La seule différence entre les deux algorithmes consiste dans la présence ou dans l’absence des guillemets lors
de la seconde affectation.
Dans l'exemple n°1, ce que l'on affecte à la variable Fifi, c'est la suite de caractères R – i – r - i. Et à la fin de
l’algorithme, le contenu de la variable Fifi est donc « Riri ».
Dans l'exemple n°2, en revanche, Riri étant dépourvu de guillemets, n'est pas considéré comme une suite de
caractères, mais comme un nom de variable. Le sens de la ligne devient donc : « affecte à la variable Fifi le
contenu de la variable Riri ». A la fin de l’algorithme n°2, la valeur de la variable Fifi est donc « Loulou ». Ici,
l’oubli des guillemets conduit certes à un résultat, mais à un résultat différent.
A noter, car c’est un cas très fréquent, que généralement, lorsqu’on oublie les guillemets lors d’une affectation
de chaîne, ce qui se trouve à droite du signe d’affectation ne correspond à aucune variable précédemment
déclarée et affectée. Dans ce cas, l’oubli des guillemets se solde immédiatement par une erreur d’exécution.
Ceci est une simple illustration. Mais elle résume l’ensemble des problèmes qui surviennent lorsqu’on oublie la
règle des guillemets aux chaînes de caractères.
Il est clair que dans le premier cas la valeur finale de A est 12, dans l’autre elle est 34.
Exercice 1.
10
Exercice 2.
Exercice 3.
Exercice 4
Exercice 5.
Exercice 6.
11
Exercice 7.
… sont des expressions valides, pour peu que Toto et Riri soient bien des nombres. Car dans le cas contraire,
la quatrième expression n’a pas de sens. En l’occurrence, les opérateurs employés sont l’addition (+) et la
soustraction (-).
Revenons pour le moment sur l’affectation. Une condition supplémentaire (en plus des deux précédentes) de
validité d’une instruction d’affectation est que :
✓ L’expression située à droite de la flèche soit du même type que la variable située à gauche. C’est très
logique : on ne peut pas ranger convenablement des outils dans un sac à provision, ni des légumes
dans une trousse à outils… sauf à provoquer un résultat catastrophique.
Si l’un des trois points énumérés ci-dessus n’est pas respecté, la machine sera incapable d’exécuter
l’affectation, et déclenchera une erreur (est-il besoin de dire que si aucun de ces points n’est respecté, il y aura
aussi erreur !).
Les opérateurs possibles dépendent du type des valeurs qui sont en jeu.
12
✓ + : addition.
✓ - : soustraction.
✓ * : multiplication.
✓ / : division.
Enfin, on a le droit d’utiliser les parenthèses, avec les mêmes règles qu’en mathématiques. La multiplication et
la division ont « naturellement » priorité sur l’addition et la soustraction. Les parenthèses ne sont ainsi utiles
que pour modifier cette priorité naturelle.
Cela signifie qu’en informatique, 12 * 3 + 5 et (12 * 3) + 5 valent strictement la même chose, à savoir 41.
Pourquoi dès lors se fatiguer à mettre des parenthèses inutiles ?
Exemple.
Exercice 8.
Exercice 9.
2.4.5. Remarques
13
Les « variables » x et y satisfaisant à l’équation existent en nombre infini (graphiquement, l’ensemble des
solutions à cette équation dessine une droite). Lorsqu’on écrit : ax² + bx + c = 0.
La « variable » x désigne les solutions à cette équation, c’est-à-dire zéro, une ou deux valeurs à la fois.
En informatique, une variable possède à un moment donné une valeur et une seule. A la rigueur, elle peut ne
pas avoir de valeur du tout (une fois qu’elle a été déclarée, et tant qu’on ne l’a pas affectée. A signaler que
dans certains langages, les variables non encore affectées sont considérées comme valant automatiquement
zéro). Mais ce qui est important, c’est que cette valeur justement, ne « varie » pas à proprement parler. Du
moins ne varie-t-elle que lorsqu’elle est l’objet d’une instruction d’affectation.
Dans l’autre sens, d’autres instructions permettent au programme de communiquer des valeurs à l’utilisateur
en les affichant à l’écran. Cette opération est l’écriture.
Remarque : Un algorithme, c’est une suite d’instructions qui programme la machine, pas l’utilisateur ! Donc
quand on dit à la machine de lire une valeur, cela implique que l’utilisateur va devoir écrire cette valeur. Et
quand on demande à la machine d’écrire une valeur, c’est pour que l’utilisateur puisse la lire. Lecture et
écriture sont donc des termes qui comme toujours en programmation, doivent être compris du point de vue de
la machine qui sera chargée de les exécuter.
14
Dès lors, aussitôt que la touche Entrée (Enter) a été frappée, l’exécution reprend. Dans le sens inverse, pour
écrire quelque chose à l’écran, c’est aussi simple que :
Avant de Lire une variable, il est très fortement conseillé d’écrire des libellés à l’écran, afin de prévenir
l’utilisateur de ce qu’il doit. Par exemple :
Lecture et Écriture sont des instructions algorithmiques qui ne présentent pas de difficultés particulières, une
fois qu’on a bien assimilé ce problème du sens du dialogue (homme|machine, ou machine | homme).
Exercice 10 :
Exercice 11.
Ecrire un pseudo code qui demande un nombre à l’utilisateur, puis qui calcule et affiche le carré de ce nombre.
Exercice 12.
Ecrire un pseudo code qui lit le prix HT d’un article, le nombre d’articles et le taux de TVA, et qui fournit le prix
total TTC correspondant. Faire en sorte que des libellés apparaissent clairement.
Exercice 13
Ecrire un algorithme utilisant des variables de type chaîne de caractères, et affichant quatre variantes possibles
de la célèbre « belle marquise, vos beaux yeux me font mourir d’amour ». On ne se soucie pas de la
ponctuation, ni des majuscules.
15
Ceci appelle quelques explications :
Un booléen est une expression dont la valeur est VRAI ou FAUX. Cela peut donc être (il n’y a que deux
possibilités) :
La structure d’un test est relativement claire. Arrivé à la première ligne (Si…Alors) la machine examine la valeur
du booléen. Si ce booléen a pour valeur VRAI, elle exécute la série d’instructions 1. Cette série d’instructions
peut être très brève comme très longue, cela n’a aucune importance. A la fin de cette série d’instructions, au
moment où elle arrive au mot « Sinon », la machine saute directement à la première instruction située après le «
Finsi ». De même, au cas où le booléen a comme valeur « Faux », la machine saute directement à la première
ligne située après le « Sinon » et exécute l’ensemble des « instructions 2 ».
La forme simplifiée correspond au cas où l’une des deux « branches » du Si est vide. Dès lors, plutôt qu’écrire «
sinon ne rien faire du tout », il est plus simple de ne rien écrire.
Exemple.
Cette définition est essentielle ! Elle signifie qu’une condition est composée de trois éléments :
✓ Une valeur.
✓ Un opérateur de comparaison.
✓ Une autre valeur.
Les valeurs peuvent être a priori de n’importe quel type (numériques, caractères…). Mais si l’on veut que la
comparaison ait un sens, il faut que les deux valeurs de la comparaison soient du même type !
16
✓ = : égal à… ;
✓ <> : différent de… ;
✓ < : strictement plus petit que… ;
✓ > : strictement plus grand que… ;
✓ =< : plus petit ou égal à… ;
✓ >= : plus grand ou égal à…
L’ensemble des trois éléments constituant la condition constitue donc, si l’on veut, une affirmation qui, à un
moment donné, est VRAIE ou FAUSSE.
A noter que ces opérateurs de comparaison peuvent tout à fait s’employer avec des caractères. Ceux-ci sont
codés par la machine dans l’ordre alphabétique, les majuscules étant systématiquement placées avant les
minuscules.
Remarque.
En formulant une condition dans un algorithme, il faut se méfier de certains raccourcis du langage courant, ou
de certaines notations valides en mathématiques, mais qui mènent à des non-sens informatiques. Prenons par
exemple la phrase « Toto est compris entre 5 et 8 ». On peut être tenté de la traduire par : 5 < Toto < 8.
Or, une telle expression, qui a du sens en français, comme en mathématiques, ne veut rien dire en
programmation. En effet, elle comprend deux opérateurs de comparaison, soit un de trop, et trois valeurs, soit
là aussi une de trop. On va voir dans un instant comment traduire convenablement une telle condition.
Exercice 14
Comme on l’a évoqué plus haut, l’informatique met à notre disposition quatre opérateurs logiques : ET, OU,
NON, et XOR.
✓ Le ET a le même sens en informatique que dans le langage courant. Pour que : Condition1 ET
Condition2 soit VRAI, il faut impérativement que Condition1 soit VRAI et que Condition2 soit VRAI.
✓ Il faut se méfier un peu plus du OU. Pour que : Condition1 OU Condition2 soit VRAI, il suffit que
Condition1 soit VRAIE ou que Condition2 soit VRAIE. Le point important est que si Condition1 est
VRAIE et que Condition2 est VRAIE aussi, Condition1 OU Condition2 est VRAIE. Le OU informatique ne
veut donc pas dire « ou bien » (sauf dans certaines formes rares, dénommées OU exclusif et notées
XOR).
17
✓ Le XOR (ou OU exclusif) fonctionne de la manière suivante. Pour que Condition1 XOR Condition2 soit
VRAI, il faut que Condition1 soit VRAI, ou bien que Condition2 soit VRAI. Mais si toutes les deux sont
fausses, ou que toutes les deux sont VRAI, alors le résultat global est considéré comme FAUX.
Nous insistons sur le fait que le XOR est une rareté, dont il n’est pas strictement indispensable de s’encombrer
en programmation.
✓ Enfin, le NON inverse une condition : NON(Condition1) est VRAI si Condition1 est FAUX, et il sera FAUX
si Condition1 est VRAI.
Vous vous demandez peut-être à quoi sert ce NON. Après tout, plutôt qu’écrire NON(Prix > 20), il serait plus
simple d’écrire tout bonnement Prix=<20. Dans ce cas, c’est évident qu’on se complique inutilement la vie
avec le NON.
Exercice 15.
Ecrire un algorithme qui demande deux nombres à l’utilisateur et l’informe ensuite si leur produit est négatif
ou positif (on laisse de côté le cas où le produit est nul). Attention toutefois : on ne doit pas calculer le produit
des deux nombres.
Exercice 16.
Ecrire un algorithme qui demande trois noms à l’utilisateur et l’informe ensuite s’ils sont rangés ou non dans
l’ordre alphabétique.
Vous constaterez que c’est un peu laborieux. Les conditions se ressemblent plus ou moins, et surtout on
oblige la machine à examiner trois tests successifs alors que tous portent sur une même chose, la température
(la valeur de la variable Temp). Il serait ainsi bien plus rationnel d’imbriquer les tests de cette manière :
18
Nous avons fait des économies : au lieu de devoir taper trois conditions, dont une composée, nous n’avons
plus que deux conditions simples. Mais aussi, et surtout, nous avons fait des économies sur le temps
d’exécution de l’ordinateur. Si la température est inférieure à zéro, celui-ci écrit dorénavant « C’est de la glace »
et passe directement à la fin, sans être ralenti par l’examen d’autres possibilités (qui sont forcément fausses).
Cette deuxième version n’est donc pas seulement plus simple à écrire et plus lisible, elle est également plus
performante à l’exécution.
Les structures de tests imbriqués sont donc un outil indispensable à la simplification et à l’optimisation des
algorithmes.
Exercice 17.
Ecrire un algorithme qui demande un nombre à l’utilisateur, et l’informe ensuite si ce nombre est positif ou
négatif (on inclut cette fois le traitement du cas où le nombre vaut zéro).
Exercice 18.
Ecrire un algorithme qui demande deux nombres à l’utilisateur et l’informe ensuite si le produit est négatif ou
positif (on inclut cette fois le traitement du cas où le produit peut être nul). Attention toutefois, on ne doit pas
calculer le produit !
Exercice 19.
Ecrire un algorithme qui demande l’âge d’un enfant à l’utilisateur. Ensuite, il l’informe de sa catégorie :
• « Poussin » de 6 à 7 ans.
• « Pupille » de 8 à 9 ans.
• « Minime » de 10 à 11 ans.
• « Cadet » après 12 ans
Peut-on concevoir plusieurs algorithmes équivalents menant à ce résultat ?
A priori, cette technique ne présente guère d’intérêt : on a alourdi plutôt qu’alléger l’algorithme de départ, en
ayant recours à deux variables supplémentaires. Mais :
19
✓ Souvenons-nous : une variable booléenne n’a besoin que d’un seul bit pour être stockée. De ce point
de vue, l’alourdissement n’est donc pas considérable.
✓ Dans certains cas, notamment celui de conditions composées très lourdes (avec plein de ET et de OU
tout partout) cette technique peut faciliter le travail du programmeur, en améliorant nettement la
lisibilité de l’algorithme. Les variables booléennes peuvent également s’avérer très utiles pour servir de
flag, technique dont on reparlera plus loin.
Alors, dans tout programme un tant soit peu sérieux, on met en place ce qu’on appelle un contrôle de saisie,
afin de vérifier que les données entrées au clavier correspondent bien à celles attendues par l’algorithme.
C’est impeccable. Du moins tant que l’utilisateur a le bon goût de ne se tromper qu’une seule fois, et d’entrer
une valeur correcte à la deuxième demande. Si l’on veut également bétonner en cas de deuxième erreur, il
faudrait rajouter un SI. Et ainsi de suite, on peut rajouter des centaines de SI, et écrire un algorithme aussi
lourd qu’une blague des Grosses Têtes, on n’en sortira pas, il y aura toujours moyen qu’un acharné flanque le
programme par terre.
La solution consistant à aligner des SI… en pagaille est donc une impasse. La seule issue est donc de flanquer
une structure de boucle, qui se présente ainsi :
Le principe est simple : le programme arrive sur la ligne du TantQue. Il examine alors la valeur du booléen (qui,
rappelons-le, peut-être une variable booléenne ou, plus fréquemment, une condition). Si cette valeur est VRAI,
le programme exécute les instructions qui suivent, jusqu’à ce qu’il rencontre la ligne FinTantQue. Il retourne
ensuite sur la ligne du TantQue, procède au même examen, et ainsi de suite. Le manège enchanté ne s’arrête
que lorsque le booléen prend la valeur FAUX.
20
Illustration avec notre problème de contrôle de saisie. Une première approximation de la solution consiste à
écrire :
Là, on a le squelette de l’algorithme correct. Mais de même qu’un squelette ne suffit pas pour avoir un être
vivant viable, il va nous falloir ajouter quelques muscles et organes sur cet algorithme pour qu’il fonctionne
correctement.
Son principal défaut est de provoquer une erreur à chaque exécution. En effet, l’expression booléenne qui
figure après le TantQue interroge la valeur de la variable Rep. Malheureusement, cette variable, si elle a été
déclarée, n’a pas été affectée avant l’entrée dans la boucle. On teste donc une variable qui n’a pas de valeur,
ce qui provoque l’arrêt immédiat de l’exécution. Pour éviter ceci, on n’a pas le choix : il faut que la variable Rep
ait déjà été affectée avant qu’on en arrive au premier tour de boucle. Pour cela, on peut faire une première
lecture de Rep avant la boucle. Dans ce cas, celle-ci ne servira qu’en cas de mauvaise saisie lors de cette
première lecture. L’algorithme devient alors :
Une autre possibilité, fréquemment employée, consiste à ne pas lire, mais à affecter arbitrairement la variable
avant la boucle. Arbitrairement ? Pas tout à fait, puisque cette affectation doit avoir pour résultat de provoquer
l’entrée obligatoire dans la boucle. L’affectation doit donc faire en sorte que le booléen soit mis à VRAI pour
déclencher le premier tour de la boucle. Dans notre exemple, on peut donc affecter Rep avec n’importe quelle
valeur, hormis « O » et « N » : car dans ce cas, l’exécution sauterait la boucle, et Rep ne serait pas du tout lue
au clavier. Cela donnera par exemple :
Cette manière de procéder est à connaître, car elle est employée très fréquemment.
Il faut remarquer que les deux solutions (lecture initiale de Rep en dehors de la boucle ou affectation de Rep)
rendent toutes deux l’algorithme satisfaisant, mais présentent une différence assez importante dans leur
structure logique.
21
En effet, si l’on choisit d’effectuer une lecture préalable de Rep, la boucle ultérieure sera exécutée uniquement
dans l’hypothèse d’une mauvaise saisie initiale. Si l’utilisateur saisit une valeur correcte à la première demande
de Rep, l’algorithme passera sur la boucle sans entrer dedans.
En revanche, avec la deuxième solution (celle d’une affectation préalable de Rep), l’entrée de la boucle est
forcée, et l’exécution de celle-ci, au moins une fois, est rendue obligatoire à chaque exécution du programme.
Du point de vue de l’utilisateur, cette différence est tout à fait mineure ; et à la limite, il ne la remarquera
même pas. Mais du point de vue du programmeur, il importe de bien comprendre que les cheminements des
instructions ne seront pas les mêmes dans un cas et dans l’autre.
Pour terminer, remarquons que nous pourrions peaufiner nos solutions en ajoutant des affichages de libellés
qui font encore un peu défaut. Ainsi, si l’on est un programmeur zélé, la première solution (celle qui inclut deux
lectures de Rep, une en dehors de la boucle, l’autre à l’intérieur) pourrait devenir :
Exercice 20.
Ecrire un algorithme qui demande à l’utilisateur un nombre compris entre 1 et 3 jusqu’à ce que la réponse
convienne.
Exercice 21
Ecrire un algorithme qui demande un nombre compris entre 10 et 20, jusqu’à ce que la réponse convienne. En
cas de réponse supérieure à 20, on fera apparaître un message : « Plus petit ! », et inversement, « Plus grand !
» si le nombre est inférieur à 10.
Exercice 22
Ecrire un algorithme qui demande un nombre de départ, et qui ensuite affiche les dix nombres suivants. Par
exemple, si l'utilisateur entre le nombre 17, le programme affichera les nombres de 18 à 27.
22
La structure « Pour … Suivant » n’est pas du tout indispensable ; on pourrait fort bien programmer toutes les
situations de boucle uniquement avec un « Tant Que ». Le seul intérêt du « Pour » est d’épargner un peu de
fatigue au programmeur, en lui évitant de gérer lui-même la progression de la variable qui lui sert de compteur
(on parle d’incrémentation, encore un mot qui fera forte impression).
Dit d’une autre manière, la structure « Pour … Suivant » est un cas particulier de TantQue : celui où le
programmeur peut dénombrer à l’avance le nombre de tours de boucles nécessaires.
Il faut noter que dans une structure « Pour … Suivant », la progression du compteur est laissée à votre libre
disposition. Dans la plupart des cas, on a besoin d’une variable qui augmente de 1 à chaque tour de boucle.
On ne précise alors rien à l’instruction « Pour » ; celle-ci, par défaut, comprend qu’il va falloir procéder à cette
incrémentation de 1 à chaque passage, en commençant par la première valeur et en terminant par la
deuxième.
Naturellement, quand on stipule un pas négatif dans une boucle, la valeur initiale du compteur doit être
supérieure à sa valeur finale si l’on veut que la boucle tourne ! Dans le cas contraire, on aura simplement écrit
une boucle dans laquelle le programme ne rentrera jamais.
Nous pouvons donc maintenant donner la formulation générale d’une structure « Pour ». Sa syntaxe générale
est :
Les structures TantQue sont employées dans les situations où l’on doit procéder à un traitement systématique
sur les éléments d’un ensemble dont on ne connaît pas d’avance la quantité, comme :
23
✓ La lecture des enregistrements d’un fichier.
Les structures Pour sont employées dans les situations où l’on doit procéder à un traitement systématique sur
les éléments d’un ensemble dont on connaît d’avance la quantité.
Dans cet exemple, le programme écrira une fois « il est passé par ici » puis six fois de suite « il repassera par-
là », et ceci quinze fois en tout. A la fin, il y aura donc eu 15 x 6 = 90 passages dans la deuxième boucle (celle
du milieu), donc 90 écritures à l’écran du message « il repassera par-là ». Notez la différence marquante avec
cette structure :
Ici, il y aura quinze écritures consécutives de « il est passé par ici », puis six écritures consécutives de « il
repassera par-là », et ce sera tout.
Des boucles peuvent donc être imbriquées (cas n°1) ou successives (cas n°2). Cependant, elles ne peuvent
jamais, au grand jamais, être croisées. Cela n’aurait aucun sens logique, et de plus, bien peu de langages vous
autoriseraient ne serait-ce qu’à écrire cette structure aberrante.
Pourquoi imbriquer des boucles ? Pour la même raison qu’on imbrique des tests. La traduction en bon français
d’un test, c’est un « cas ». Eh bien un « cas » (par exemple, « est-ce un homme ou une femme ? ») peut très bien
se subdiviser en d’autres cas (« a-t-il plus ou moins de 18 ans ? »).
De même, une boucle, c’est un traitement systématique, un examen d’une série d’éléments un par un (par
exemple, « prenons tous les employés de l’entreprise un par un »). Eh bien, on peut imaginer que pour chaque
élément ainsi considéré (pour chaque employé), on doive procéder à un examen systématique d’autre chose («
prenons chacune des commandes que cet employé a traitées »). Voilà un exemple typique de boucles
24
imbriquées : on devra programmer une boucle principale (celle qui prend les employés un par un) et à
l’intérieur, une boucle secondaire (celle qui prend les commandes de cet employé une par une).
Dans la pratique de la programmation, la maîtrise des boucles imbriquées est nécessaire, même si elle n’est
pas suffisante.
Vous remarquerez que nous faisons ici gérer « en double » la variable Truc, ces deux gestions étant
contradictoires. D’une part, la ligne « Pour… » augmente la valeur de Truc de 1 à chaque passage. D’autre part
la ligne « Truc ← Truc * 2 » double la valeur de Truc à chaque passage. Il va sans dire que de telles
manipulations perturbent complètement le déroulement normal de la boucle, et sont causes, sinon de
plantages, tout au moins d’exécutions erratiques.
Exercice 23
Exercice 24
Exercice 25
Exercice 26
25
Exercice 27
Exercice 28
Exercice 29
26
un peu simplifiée, par exemple N1, N2, N3, etc. Mais cela ne change pas fondamentalement notre problème,
car arrivé au calcul, et après une succession de douze instructions « Lire » distinctes, cela donnera
obligatoirement une atrocité du genre :
Si par exemple on a une centaine ou quelques milliers de valeurs à traiter, le traitement sera très laborieux à
faire. Si en plus on est dans une situation on l’on ne peut pas savoir d’avance combien il y aura de valeurs à
traiter, on tombe dans le cas limite impossible à traiter de cette manière.
C’est pourquoi la programmation nous permet de rassembler toutes ces variables en une seule, au sein de
laquelle chaque valeur sera désignée par un numéro. En bon français, cela donnerait donc quelque chose du
genre « la note numéro 1 », « la note numéro 2 », « la note numéro 8 ». C’est largement plus pratique.
Un ensemble de valeurs portant le même nom de variable et repérées par un nombre, s’appelle un tableau, ou
encore une variable indicée. Le nombre qui, au sein d’un tableau, sert à repérer chaque valeur s’appelle
l’indice. Chaque fois que l’on doit désigner un élément du tableau, on fait figurer le nom du tableau, suivi de
l’indice de l’élément, entre parenthèses.
Un tableau doit être déclaré comme tel, en précisant le plus grand indice et le type de valeurs qu’il contiendra.
Comme nous venons de voir que les indices commencent à zéro, conséquence imparable, si on veut 12
emplacements, le plus grand indice sera 11 (au début, ça déroute, mais avec le temps, on se fait à tout).
On peut créer des tableaux contenant des variables de tous types : tableaux de numériques, bien sûr, mais
aussi tableaux de caractères, tableaux de booléens, tableaux de tout ce qui existe dans un langage donné
comme type de variables. Cependant, hormis dans quelques rares langages, on ne peut pas faire un mixage de
types différents de valeurs au sein d’un même tableau.
L’énorme avantage des tableaux, c’est qu’on va pouvoir les traiter en faisant des boucles. Par exemple, pour
effectuer notre calcul de moyenne, cela donnera par exemple :
27
NB : On a fait deux boucles successives pour plus de lisibilité, mais on aurait tout aussi bien pu n’en écrire
qu’une seule dans laquelle on aurait tout fait d’un seul coup.
Remarque générale : l’indice qui sert à désigner les éléments d’un tableau peut être exprimé directement
comme un nombre en clair, mais il peut être aussi une variable, ou une expression calculée.
✓ Être égale au moins à 0 (dans quelques rares langages, le premier élément d’un tableau porte l’indice
1). Mais nous avons choisi ici de commencer la numérotation des indices à zéro, comme c’est le cas en
langage C/C++ et en Visual Basic. Donc attention, Truc (6) est le septième élément du tableau Truc.
Pensez aux suites numériques mathématiques.
✓ Être un nombre entier. Quel que soit le langage, l’élément Truc(3,1416) n’existe jamais. i.e. pas de
chiffre décimal en indice.
✓ Être inférieure ou égale au nombre d’éléments du tableau (moins 1, si l’on commence la numérotation
à zéro). Si le tableau Bidule a été déclaré comme ayant 25 éléments, la présence dans une ligne, sous
une forme ou sous une autre, de Bidule(32) déclenchera automatiquement une erreur.
NB : Si l’on est dans un langage où les indices commencent à zéro, il faut en tenir compte à la déclaration :
Créera en fait un tableau de 13 éléments, le plus petit indice étant 0 et le plus grand 12.
Remarque : ne pas confondre l’indice d’un élément d’un tableau avec le contenu de cet élément. La troisième
maison de la rue n’a pas forcément trois habitants, et la vingtième vingt habitants. En notation algorithmique,
il n’y a aucun rapport entre i et truc(i).
Exercice 30
Ecrire un algorithme qui déclare et remplisse un tableau de 7 valeurs numériques en les mettant toutes à zéro.
Exercice 31
Ecrire un algorithme qui déclare et remplisse un tableau contenant les six voyelles de l’alphabet latin.
Exercice 32
Ecrire un algorithme qui déclare un tableau de 9 notes, dont on fait ensuite saisir les valeurs par l’utilisateur.
Exercice 33
Exercice 34
28
Exercice 35
Aussi, pour parer à ce genre de situation, a-t-on la possibilité de déclarer le tableau sans préciser au départ
son nombre d’éléments. Ce n’est que dans un second temps, au cours du programme, que l’on va fixer ce
nombre via une instruction de redimensionnement : Redim. Notez que tant qu’on n’a pas précisé le nombre
d’éléments d’un tableau, d’une manière ou d’une autre, ce tableau est inutilisable.
Exemple : on veut faire saisir des notes pour un calcul de moyenne, mais on ne sait pas combien il y aura de
notes à saisir. Le début de l’algorithme sera quelque chose du genre :
Cette technique n’a rien de sorcier, mais elle fait partie de l’arsenal de base de la programmation en gestion.
29
Exercice 36
Ecrivez la fin de l’algorithme 6.3 afin que le calcul de la moyenne des notes soit effectué et affiché à l’écran.
Exercice 37
Ecrivez un algorithme permettant à l’utilisateur de saisir un nombre quelconque de valeurs, qui devront être
stockées dans un tableau. L’utilisateur doit donc commencer par entrer le nombre de valeurs qu’il compte
saisir. Il effectuera ensuite cette saisie. Enfin, une fois la saisie terminée, le programme affichera le nombre de
valeurs négatives et le nombre de valeurs positives.
Exercice 38
Ecrivez un algorithme calculant la somme des valeurs d’un tableau (on suppose que le tableau a été
préalablement saisi).
Exercice 39
Ecrivez un algorithme constituant un tableau, à partir de deux tableaux de même longueur préalablement
saisis. Le nouveau tableau sera la somme des éléments des deux tableaux de départ.
Exemple :
Tableau 1 : 4–8–7–9–1–5–4–6
Tableau 2 : 7–6–5–2–1–3–7–4
Tableau à constituer : 11 – 14 – 12 – 11 – 2 – 8 – 11 – 10
Exercice 40
Toujours à partir de deux tableaux précédemment saisis, écrivez un algorithme qui calcule le schtroumpf des
deux tableaux. Pour calculer le schtroumpf, il faut multiplier chaque élément du tableau 1 par chaque élément
du tableau 2, et additionner le tout.
Exemple :
Tableau 1 : 4 – 8 – 7 - 12
Tableau 2 : 3–6
Le Schtroumpf :
3*4 + 3*8 + 3*7 + 3*12 + 6*4 + 6*8 + 6*7 + 6*12 = 279
Exercice 41
Ecrivez un algorithme qui permette la saisie d’un nombre quelconque de valeurs, sur le principe de l’ex 6.8.
Toutes les valeurs doivent être ensuite augmentées de 1, et le nouveau tableau sera affiché à l’écran.
Exercice 42
Ecrivez un algorithme permettant, toujours sur le même principe, à l’utilisateur de saisir un nombre déterminé
de valeurs. Le programme, une fois la saisie terminée, renvoie la plus grande valeur en précisant quelle
position elle occupe dans le tableau. On prendra soin d’effectuer la saisie dans un premier temps, et la
recherche de la plus grande valeur du tableau dans un second temps.
Exercice 43
Toujours et encore sur le même principe, écrivez un algorithme permettant, à l’utilisateur de saisir les notes
d'une classe. Le programme, une fois la saisie terminée, renvoie le nombre de ces notes supérieures à la
moyenne de la classe.
30
choses, c'est bien entendu de répéter le code correspondant autant de fois que nécessaire. Apparemment, on
ne se casse pas la tête : quand il faut que la machine interroge l'utilisateur, on recopie presque mot à mot les
lignes de codes voulues. Mais en procédant de cette manière, la pire qui soit, on se prépare des lendemains
qui déchantent...
D'abord, parce que si la structure d'un programme écrit de cette manière peut paraître simple, elle est en
réalité inutilement lourde. Elle contient des répétitions, et pour peu que le programme soit long, il peut
devenir parfaitement illisible. Or, c'est un critère essentiel pour un programme informatique, qu'il soit
facilement modifiable donc lisible, y compris - et surtout - par ceux qui ne l'ont pas écrit ! Dès que l'on
programme non pour soi-même, mais dans le cadre d'une organisation (entreprise ou autre), cette nécessité se
fait sentir de manière aiguë.
En plus, à un autre niveau, une telle structure pose des problèmes considérables de maintenance : car en cas
de modification du code, il va falloir traquer toutes les apparitions de ce code pour faire convenablement la
modification ! Et si l'on en oublie une, on a laissé un bug.
Il faut donc opter pour une autre stratégie, qui consiste à séparer ce traitement du corps du programme et à
appeler ces instructions (qui ne figurent donc plus qu’en un seul exemplaire) à chaque fois qu’on en a besoin.
Ainsi, la lisibilité est assurée ; le programme devient modulaire, et il suffit de faire une seule modification au
bon endroit, pour que cette modification prenne effet dans la totalité de l’application.
Le corps du programme s’appelle alors la procédure/fonction principale, et ces groupes d’instructions auxquels
on a recours s’appellent des fonctions et des sous-procédures (nous verrons un peu plus loin la différence
entre ces deux termes).
Reprenons un exemple de question à laquelle l’utilisateur doit répondre par oui ou par non.
On le voit bien, il y a là une répétition quasi identique du traitement à accomplir. A chaque fois, on demande
une réponse par Oui ou Non, avec contrôle de saisie. La seule chose qui change, c'est le nom de la variable
dans laquelle on range la réponse. Alors, il doit bien y avoir un truc.
La solution consiste à isoler les instructions demandant une réponse par Oui ou Non, et à appeler ces
instructions à chaque fois que nécessaire. Ainsi, on évite les répétitions inutiles, et on a découpé notre
problème en petits morceaux autonomes.
Nous allons donc créer une fonction dont le rôle sera de renvoyer la réponse (oui ou non) de l'utilisateur. Ce
mot de "fonction", en l'occurrence, ne doit pas nous surprendre : c’est comme la notion de fonction en
mathématique. Si on appelle cette fonction par RepOuiNon, le pseudo-code de cette fonction peut être :
31
On remarque au passage l’apparition d’un nouveau mot-clé : Renvoyer, qui indique quelle valeur doit prendre
la fonction lorsqu'elle est utilisée par le programme.
Une fonction s'écrit toujours en-dehors de la procédure/programme principale. Selon les langages, cela peut
prendre différentes formes. Mais ce qu'il faut comprendre, c'est que ces quelques lignes de codes sont en
quelque sorte des satellites, qui existent en dehors du traitement lui-même. Simplement, elles sont à sa
disposition, et il pourra y faire appel chaque fois que nécessaire. Si l'on reprend notre exemple, une fois notre
fonction RepOuiNon écrite, le programme principale comprendra les lignes :
On a ainsi évité les répétitions inutiles, et si d'aventure, il y avait un bug dans notre contrôle de saisie, il
suffirait de faire une seule correction dans la fonction RepOuiNon pour que ce bug soit éliminé de toute
l'application.
Toutefois, les plus sagaces d'entre vous auront remarqué, tant dans le titre de la fonction, que dans chacun
des appels, la présence de parenthèses. Celles-ci, dès qu'on crée ou qu'on appelle une fonction, sont
obligatoires. Et si vous avez bien compris tout ce qui précède, vous devez avoir une petite idée de ce qu'on va
pouvoir mettre dedans...
✓ Lorsqu’on appelle la fonction, on doit lui préciser quel message elle doit afficher avant de lire la
réponse.
✓ La fonction doit être « prévenue » qu’elle recevra un message, et être capable de le récupérer pour
l’afficher.
En langage algorithmique, on dira que le message devient un argument de la fonction. Cela n'est certes pas
une découverte pour vous : nous avons longuement utilisé les arguments à propos des fonctions prédéfinies.
32
Eh bien, quitte à construire nos propres fonctions, nous pouvons donc construire nos propres arguments.
Voilà comment l’affaire se présente...
La fonction sera dorénavant déclarée comme suit :
Il y a donc maintenant entre les parenthèses une variable, Msg, dont on précise le type, et qui signale à la
fonction qu’un argument doit lui être envoyé à chaque appel. Quant à ces appels, justement, ils se simplifieront
encore dans la procédure principale, pour devenir :
Une remarque importante : là, on n'a passé qu’un seul argument en entrée. Mais bien entendu, on peut en
passer autant qu’on veut, et créer des fonctions avec deux, trois, quatre, etc. arguments ; Simplement, il faut
éviter d'être gourmands, et il suffit de passer ce dont on a besoin, ni plus, ni moins !
Dans le cas que l'on vient de voir, le passage d'un argument à la fonction était élégant, mais pas
indispensable. La preuve, cela marchait déjà très bien lors de la première version. Nous allons voir maintenant
une situation où il faut absolument passer deux arguments à une fonction si l'on veut qu'elle puisse remplir sa
tâche.
Imaginons qu'à plusieurs reprises au cours du programme, on ait à calculer la moyenne des éléments de
différents tableaux. Plutôt que répéter le code à chaque fois, on va donc créer une fonction Moy, chargée
spécialement de calculer cette moyenne. Voyons voir un peu de quoi cette fonction a besoin :
✓ Du tableau, bien sûr. Comment calculer la moyenne de ses éléments sans cela ?
✓ Mais il faut également le nombre d'éléments du tableau, ou, au choix, l'indice maximal du tableau.
Enfin, quelque chose qui permette à la fonction de savoir combien de tours de boucle elle devra faire.
Voilà donc une situation où la fonction a absolument besoin de deux arguments. Ecrivons-la, juste histoire de
vérifier qu'on est bien d'accord :
33
Quant aux différents appels dans la procédure principale, si on a un tableau Riri de 43 éléments, un tableau
Fifi de 5 éléments et un tableau Loulou de k éléments, et qu’on range respectivement les moyennes dans les
variables M1, M2 et M3, cela donnera :
Le plus important, c'est d'acquérir le réflexe de constituer systématiquement les fonctions adéquates quand on
doit traiter un problème donné.
Cette partie de la réflexion s'appelle d'ailleurs l'analyse fonctionnelle d'un problème, et c'est toujours par là
qu'il faut commencer : en gros, dans un premier temps, on découpe le traitement en modules, et dans un
deuxième temps, on écrit chaque module. Cependant, avant d'en venir là, il nous faut découvrir un dernier
outil, qui prend le relais là où les fonctions deviennent incapables de nous aider.
Exercice 44
Ecrivez une fonction qui renvoie la somme de cinq nombres fournis en argument.
Exercice 45
Ecrivez une fonction qui renvoie le nombre de voyelles contenues dans une chaîne de caractères passée en
argument. Au passage, notez qu'une fonction a tout à fait le droit d'appeler une autre fonction.
Exercice 46
Réécrivez la fonction Trouve, vue précédemment, à l’aide des fonctions Mid et Len (comme quoi, Trouve, à la
différence de Mid et Len, n’est pas une fonction indispensable dans un langage).
2.9.2. Sous-Procédures
Les fonctions, c'est bien, mais dans certains cas, ça ne nous rend guère service.
Il peut en effet arriver que dans un programme, on ait à réaliser des tâches répétitives, mais que ces tâches
n'aient pas pour rôle de générer une valeur particulière, ou qu'elles aient pour rôle d'en générer plus d'une à la
fois. Prenons deux exemples.
Premier exemple. Imaginons qu'au cours de notre application, on ait plusieurs fois besoin d'effacer l'écran et de
réafficher un bidule comme un petit logo en haut à gauche. On pourrait se dire qu'il faut créer une fonction
pour faire cela. Mais quelle serait la valeur renvoyée par la fonction ? Aucune ! Effacer l'écran, ce n'est pas
produire un résultat stockable dans une variable, et afficher un logo non plus. Voilà donc une situation où on a
besoin de répéter du code, mais où ce code n'a pas comme rôle de produire une valeur.
Deuxième exemple. Au cours de notre application, on doit plusieurs fois faire saisir un tableau d'entiers (mais à
chaque fois, un tableau différent). Là encore, on serait tenté d'effectuer toutes ces saisies de tableaux dans une
seule fonction. Mais problème, une fonction ne peut renvoyer qu'une seule valeur à la fois. Elle ne peut donc
renvoyer un tableau, qui est une série de valeurs distinctes.
Alors, dans ces deux cas, faute de pouvoir traiter l'affaire par une fonction, devra-t-on en rester au code
répétitif dont nous venons de dénoncer si vigoureusement les faiblesses ? Vous vous doutez bien que non.
Heureusement, tout est prévu, il y a une solution. Et celle-ci consiste à utiliser des sous-procédures.
34
En fait, les fonctions - que nous avons vues - ne sont qu'un cas particulier des sous-procédures - que nous
allons voir : celui où doit être renvoyé vers la procédure appelante une valeur et une seule. Dans tous les
autres cas, il faut donc avoir recours non à la forme particulière et simplifiée (la fonction), mais à la forme
générale (la sous-procédure). Parlons donc de ce qui est commun aux sous-procédures et aux fonctions, mais
aussi de ce qui les différencie. Voici comment se présente une sous-procédure :
1. Alors qu'une fonction se caractérisait par les mots-clés Fonction ... Fin Fonction, une sous-procédure est
identifiée par les mots-clés Procédure ... Fin Procédure. Oui, c'est un peu trivial comme remarque, mais on ne
sait jamais.
2. Lorsqu'une fonction était appelée, sa valeur (retournée) était toujours affectée à une variable. L'appel à une
procédure, lui, est au contraire toujours une instruction autonome. "Exécute la procédure Bidule" est un ordre
qui se suffit à lui-même.
3. Toute fonction devait, pour cette raison, comporter l'instruction "Renvoyer". Pour la même raison,
l'instruction "Renvoyer" n'est jamais utilisée dans une sous-procédure. La fonction est une valeur calculée, qui
renvoie son résultat vers la procédure principale. La sous-procédure, elle, est un traitement ; elle ne "vaut" rien.
4. Même une fois qu'on a bien compris les trois premiers points, on n'est pas au bout de nos peines.
En effet, il nous reste à examiner ce qui peut bien se trouver dans les parenthèses, à la place des points de
suspension, aussi bien dans la déclaration de la sous-procédure que dans l'appel.
Dans une fonction, les valeurs qui circulaient depuis la procédure (ou la fonction) appelante jusqu'à la fonction
portaient le nom d'arguments. Là, les valeurs qui circulent depuis la procédure (ou la fonction) appelante vers
la sous- procédure appelée se nomment des paramètres en entrée de la sous-procédure. Mais seul le nom
change : « paramètres en entrée » pour les procédures ou « arguments » pour les fonctions, on parle en fait
exactement de la même chose.
Inversement, dans une fonction, la valeur retournée par la fonction portait le nom de la fonction elle-même, et
elle faisait l'objet d'une instruction spéciale (« renvoyer »). Avec une sous-procédure, les valeurs retournées,
quand il y en a, s'appellent des paramètres en sortie de la sous-procédure, qui doivent être déclarés
explicitement comme tels.
35
Ceci nous permet de reformuler en termes un peu différents la vérité fondamentale apprise un peu plus haut :
toute sous-procédure possédant un et un seul paramètre en sortie peut également être écrite sous forme
d'une fonction (et entre nous, c'est préférable car un peu plus facile).
Remarque : dans la plupart des langages, on ne parlera pas de paramètres « en entrée » ou « en sortie », mais
de paramètres transmis :
On peut également imaginer le cas d’un paramètre qui serait passé à une procédure à la fois en entrée et en
sortie : on envoie une variable à une procédure, afin qu’elle la traite et la renvoie modifiée. Dans ce cas, le
paramètre aura également le statut d’une transmission par référence (qui peut le plus peut le moins).
Tout cela peut sembler un tantinet compliqué. Mais sur le principe, c'est en réalité assez simple, et dès que
vous aurez pratiqué un peu, vous ferez cela les yeux fermés. Reprenons le cas d'un programme au cours
duquel on a plusieurs tableaux d'entiers à faire saisir par l'utilisateur. Puisqu'un tableau comporte plusieurs
valeurs, nous savons qu'il ne peut, par définition, être renvoyé par une fonction. Mais une sous-procédure, elle,
comporte autant de paramètres en sortie qu'on veut. Elle peut donc sans problème renvoyer un tableau vers la
procédure qui l'appelle. Ecrivons donc notre sous-procédure :
Et son appel :
La seule chose à remarquer, c'est que les variables manipulées par la sous-procédure (notamment le tableau T)
ne sont pas celles qui sont manipulées dans la procédure appelante (les tableaux Truc et Machin).
Ceci n'est pas une obligation : on pourrait imaginer une architecture où ce seraient les mêmes variables qui
seraient triturées dans la procédure appelante et dans la sous-procédure (ces variables porteraient alors le
même nom). Mais une telle architecture, si elle est possible, doit rester l'exception à laquelle on n'a recours
qu'en cas de besoin très particulier. En effet, pour qu'une telle chose soit possible, il faut que la variable ait la
capacité de conserver sa valeur d'une procédure à l'autre ; en quelque sorte, qu'elle survive même si la
procédure qui la manipulait se termine. Ce genre de variable dopée à l'EPO existe, on en reparlera dans un
36
instant, mais elle est très gourmande en ressources mémoire. Donc, comme toujours, vous connaissez la
chanson, on applique le principe de l'économie de moyens.
Conclusion : une sous-procédure est un morceau de code qui comporte éventuellement des paramètres en
entrée (transmis par valeur) et des paramètres en sortie (transmis par référence). La sous-procédure manipule
donc des variables qui lui sont propres, et la procédure appelante agit de même. La présence des paramètres
dans l'appel à la sous-procédure et dans le titre de celle-ci assure le fait que la valeur des uns sera recopiée
dans les autres (transmission par valeur) et qu'en retour, celle des autres sera recopiée dans les uns
(transmission par référence).
✓ Comme privée, ou locale (c’est neuf fois sur dix l’option par défaut). Cela signifie que la variable
disparaît (et sa valeur avec) dès que prend fin la procédure ou elle a été créée.
✓ Comme publique, ou globale. Ce qui signifie qu’une telle variable est conservée intacte pour toute
l’application, au-delà des ouvertures et fermetures de procédures. La variable conserve sa valeur et
peut être traitée par différentes procédures du programme.
La manière dont ces déclarations doivent être faites est évidemment fonction de chaque langage de
programmation. En pseudo-code algorithmique, vous pourrez utiliser le mot-clé Publique pour déclarer une
variable publique :
La manière dont ces déclarations doivent être faites est évidemment fonction de chaque langage de
programmation. En pseudo-code algorithmique, vous pourrez utiliser le mot-clé Publique pour déclarer une
variable publique :
Comment choisir de déclarer une variable en Public ou en Privé ? C’est très simple : les variables globales
consomment énormément de ressources en mémoire. En conséquence, le principe qui doit présider au choix
entre variables publiques et privées doit être celui de l’économie de moyens : on ne déclare comme publiques
que les variables qui doivent absolument l’être. Et chaque fois que possible, lorsqu’on crée une sous-
procédure, on utilise le passage de paramètres plutôt que des variables publiques.
37