Vous êtes sur la page 1sur 267

1

Algorithmique orientée objet




Saint-Jean DJUNGU
2
3

A Donel, Amel et Henriette DJUNGU


4

Du même auteur

1. Outils et langages du Web n.0, Edition Médiaspaul, Kinshasa, R.D. Congo, 2013 – ISBN
978-2-7414-0764-5.
2. Conception et mise en œuvre parallèle d'algorithmes de PageRanking, Editions
Universitaires Européennes, Allemagne, 2014 – ISBN 978-3-8417-3138-8.
3. Réseaux par la pratique, Edition CRIA, Kinshasa, R.D. Congo, 2014 – ISBN 978-99951-
776-0-9.
4. Génie logiciel, Edition Médiaspaul, Kinshasa, R.D. Congo, 2017 – ISBN 978-27414-1073-7.
5. Calcul parallèle et distribué, Editions Universitaires Européennes, Allemagne, 2018 – ISBN
978-6-2022-7472-2.

6. A-B-C des Systèmes d’exploitation, Edition UNILU-PRINT, Lubumbashi, R.D. Congo, 2019
– ISBN 978-99951-776-1-4.
5

Table des matières

Du même auteur ......................................................................................................................... 4


Avant-propos ............................................................................................................................ 11
Chapitre 1 : Notions de base .................................................................................................... 15
1.1. Qu’est-ce qu’un algorithme ? ........................................................................................ 15
1.1.1. Définition ........................................................................................................... 15
1.1.2. Exemple d’un algorithme ................................................................................ 15
1.2. Programme informatique ....................................................................................... 16
1.3. Pourquoi utiliser un algorithme ? .......................................................................... 16
1.4. Algorithmique .......................................................................................................... 17
1.4.1. Validité d’un algorithme .................................................................................. 18
1.4.2. Robustesse d’un algorithme ............................................................................ 18
1.4.3. Réutilisabilité d’un algorithme ....................................................................... 19
1.4.4. Complexité d’un algorithme ............................................................................ 19
1.4.5. Efficacité d’un algorithme ............................................................................... 19
1.5. Formalisme de représentation d’un algorithme ................................................... 19
1.6. Langages évolués...................................................................................................... 20
1.7. Que faut-il pour être bon en Algorithmique ? ...................................................... 22
1.8. AlgoBox..................................................................................................................... 23
1.8.1. Présentation de l’interface d’AlgoBox ............................................................ 23
1.8.2. Fonctionnement général .................................................................................. 24
1.9. Exercices ................................................................................................................... 25
Chapitre 2 : Variables et instructions ....................................................................................... 26
2.1. Objets ............................................................................................................................ 26
2.2. Variables........................................................................................................................ 27
2.2.1. Définition ............................................................................................................... 27
2.2.2. Règles de nommage ............................................................................................... 28
2.2.3. Variables en AlgoBox ............................................................................................ 28
2.3. Structure d’un algorithme.............................................................................................. 29
2.4. Affectation ..................................................................................................................... 30
2.4.1. Utilisateur et concepteur......................................................................................... 30
2.4.2. Syntaxe ................................................................................................................... 30
2.4.3. Expressions et opérateurs ....................................................................................... 31
6

2.4.4. Erreurs à éviter ....................................................................................................... 34


2.5. Saisie et affichage .......................................................................................................... 34
2.5.1. Affichage ................................................................................................................ 34
2.5.2. Saisie ...................................................................................................................... 36
2.6. Exemple avec AlgoBox ................................................................................................. 37
2.7. Exercices ....................................................................................................................... 38
Chapitre 3 : Branchements conditionnels................................................................................. 43
3.1. Introduction ................................................................................................................... 43
3.2. Opérateurs de comparaison ........................................................................................... 43
3.3. Structure alternative ...................................................................................................... 44
3.4. Structure conditionnelle ................................................................................................ 46
3.5. Tests imbriqués ............................................................................................................. 47
3.6. Choix multiple ............................................................................................................... 50
3.7. Variables booléennes..................................................................................................... 52
3.8. Exercices ....................................................................................................................... 52
Chapitre 4 : Boucles ................................................................................................................. 58
4.1. Introduction ................................................................................................................... 58
4.2. Boucle tant_que ............................................................................................................. 58
4.3. Boucle faire … tant_que................................................................................................ 62
4.4. Boucle pour … faire ...................................................................................................... 63
4.5. Applications .................................................................................................................. 66
4.5.1. Recherche de la valeur maximale........................................................................... 66
4.5.2. Rendre la monnaie .................................................................................................. 67
4.6. Boucles imbriquées ....................................................................................................... 68
4.7. Exercices ....................................................................................................................... 70
Chapitre 5 : Tableaux ............................................................................................................... 74
5.1. Utilité des tableaux ........................................................................................................ 74
5.2. Déclaration des tableaux ............................................................................................... 75
5.2.1. Tableau à une dimension ........................................................................................ 75
5.2.2. Tableaux à deux dimensions .................................................................................. 76
5.2.3. Exemple d’utilisation ............................................................................................. 77
5.2.4. Tableaux dynamiques ............................................................................................. 78
5.3. Algorithmes de tri .......................................................................................................... 80
5.3.1. Tri par sélection ...................................................................................................... 80
5.3.2. Tri par insertion ...................................................................................................... 83
5.3.3. Tri à bulles .............................................................................................................. 86
5.4. Recherche par dichotomie ............................................................................................. 88
7

5.4.1. Traitement par dichotomie ..................................................................................... 88


5.4.2. Recherche dichotomique ........................................................................................ 88
5.5. Exercices ....................................................................................................................... 90
Chapitre 6 : Procédures et fonctions ........................................................................................ 96
6.1. Présentation ................................................................................................................... 96
6.2. Structures d’une fonction .............................................................................................. 96
6.2.1. Définition ............................................................................................................... 96
6.2.2. Syntaxe d’une fonction ......................................................................................... 97
6.2.3. Procédures ............................................................................................................. 98
6.3. Spécificités des fonctions ............................................................................................. 99
6.3.1. Exemple .................................................................................................................. 99
6.3.2. Environnements des données ................................................................................. 99
6.4. Fonctions prédéfinies .................................................................................................. 104
6.4.1. Fonctions mathématiques .................................................................................. 104
6.4.2. Fonctions sur chaînes ........................................................................................... 108
6.4.3. Fonctions de conversion ..................................................................................... 109
6.5. Récursivité.................................................................................................................. 110
6.5.1. Définition ............................................................................................................. 110
6.5.2. Structure d’une fonction récursive ................................................................... 110
6.5.3. Recherche dans un tableau ................................................................................ 112
6.6. Exercices ..................................................................................................................... 113
Chapitre 7 : Fichiers ............................................................................................................... 117
7.1. Introduction ................................................................................................................. 117
7.2. Organisation des fichiers .......................................................................................... 117
7.3. Structure des enregistrements .................................................................................. 118
7.3. Types d’accès ............................................................................................................. 119
7.4. Instructions d’un fichier texte en accès séquentiel ................................................. 119
7.4.1. Ouverture et fermeture ...................................................................................... 119
7.4.2. Ecriture des enregistrements ............................................................................. 121
7.4.3. Lecture des enregistrements .............................................................................. 122
7.5. Stratégies de traitement ............................................................................................... 124
7.6. Exercices ..................................................................................................................... 125
Chapitre 8 : Classes et objets.................................................................................................. 132
8.1. Introduction ................................................................................................................. 132
8.2. Classes ......................................................................................................................... 133
8.2.1. Définition ............................................................................................................. 133
8.2.2. Constituants d’une classe ..................................................................................... 133
8

8.2.3. Exemple d’une classe ........................................................................................... 134


8.2.4. Attribut statique .................................................................................................... 135
8.3. Objets .......................................................................................................................... 136
8.3.1. Définition ............................................................................................................. 136
8.3.2. Constructeurs ........................................................................................................ 136
8.3.3. Variables et instances ........................................................................................... 137
8.3.4. Appel d’une méthode ........................................................................................... 138
8.3.5. Opérateur this ....................................................................................................... 138
8.3.6. Accesseurs ............................................................................................................ 139
8.3.7. Ecriture d’une classe ............................................................................................ 142
8.3.8. Tableaux ............................................................................................................... 144
8.4. Exemple d’application................................................................................................. 144
8.4.1. Saisir les notes ...................................................................................................... 144
8.4.2. Visualiser les noms............................................................................................... 145
8.4.3. Menu..................................................................................................................... 145
8.5. Exercices ..................................................................................................................... 146
Chapitre 9 : Relations multi-classes ....................................................................................... 150
9.1. Héritage ....................................................................................................................... 150
9.1.1. Définition et exemple ........................................................................................... 150
9.1.3. Opérateur super .................................................................................................... 152
9.1.4. Polymorphisme .................................................................................................. 152
9.1.5. Ajout d’un comportement à une méthode de la superclasse .......................... 153
9.2. Classes et méthodes abstraites ..................................................................................... 154
9.3. Interfaces ..................................................................................................................... 156
9.4. Gestion d’une pharmacie ............................................................................................. 158
9.4.1. Classe Medicament .............................................................................................. 158
9.4.2. Classe Client ......................................................................................................... 159
9.4.3. Classe Pharmacie .................................................................................................. 160
9.5. Gestion des employés d’une entreprise ....................................................................... 165
9.5.1. Classe Employe .................................................................................................... 165
9.5.2. Calcul de salaire ................................................................................................... 166
9.5.3. Employés à risques ............................................................................................... 168
9.5.4. Collection d'employés .......................................................................................... 169
9.5.5. Classe Salaires ...................................................................................................... 171
9.6. Exercices ..................................................................................................................... 171
Chapitre 10 : Complexité algorithmique ................................................................................ 174
10.1. Définitions ................................................................................................................. 174
9

10.1.1. Opérations élémentaires ..................................................................................... 174


10.1.2. Instance............................................................................................................... 174
10.1.3. Ordre de grandeur............................................................................................... 175
10.2. Généralités ................................................................................................................. 175
10.2.1. But d'un calcul de complexité ............................................................................ 175
10.2.2. Types de complexité........................................................................................... 176
10.2.3. De quoi est fonction la complexité ? .................................................................. 177
10.3. Sommes usuelles ...................................................................................................... 178
10.4. Calculs de la complexité .......................................................................................... 179
10.4.1. Application des règles ........................................................................................ 179
10.4.2. Classification des algorithmes ......................................................................... 180
10.4.3. Quelques exemples ........................................................................................... 181
10.5. Exercices ................................................................................................................... 186
Annexe : Corrigés des exercices ............................................................................................ 187
Chapitre 1 ........................................................................................................................... 187
Chapitre 2 ........................................................................................................................... 187
Chapitre 3 ........................................................................................................................... 193
Chapitre 4 ........................................................................................................................... 207
Chapitre 5 ........................................................................................................................... 216
Chapitre 6 ........................................................................................................................... 227
Chapitre 7 ........................................................................................................................... 235
Chapitre 8 ........................................................................................................................... 251
Chapitre 9 ........................................................................................................................... 257
Chapitre 10 ......................................................................................................................... 265
Bibliographie .......................................................................................................................... 267
10
11

Avant-propos
Aujourd’hui, l’informatique est devenue une industrie, l’un des secteurs de base de
l’économie mondiale. Sa contribution à n’importe quelle entreprise est double :
 de par ses performances techniques, c’est un outil incomparable pour le traitement et
l’exploitation de données à des fins pratiques.
 C’est aussi grâce aux réseaux de transmission, l’informatique apparaît comme un
puissant vecteur de modernité venant largement influencer la conduite des entreprises.

Au niveau mondial, il est reconnu que le coût du matériel informatique ne fait que
diminuer alors que la performance ne fait qu’augmenter. Le marché du matériel s’est donc
standardisé. Dès lors, les problèmes liés à l’informatique sont essentiellement des problèmes
de logiciel.

La sûreté de fonctionnement des logiciels est un défi, car contrairement aux autres
domaines de l’ingénierie, les erreurs et les défaillances ne proviennent ni de défauts dans les
matériaux ni de phénomènes d’usure, mais toujours d’erreurs humaines inhérentes à l’activité
de programmation.

Programmer, c’est donner à l’ordinateur une série d’instructions pour lui permettre de
réaliser un travail à notre place. Mais comme l’ordinateur est stupide, un enfant de 3 ans est
plus intelligent qu’un ordinateur, il faut lui expliquer la manière s'y prendre. Comment le lui
dire ? Comment le lui apprendre ? Comment s'assurer qu'il fait ce travail aussi bien que nous ?
Et mieux que nous? D’où le bien-fondé de l’algorithmique, passage obligé pour apprendre à
mieux programmer dans un langage informatique.

L’algorithme permet de décrire sur papier, dans son patois et avec un crayon, le
raisonnement que l’on veut imposer à l’ordinateur. Mieux, c’est un langage pour réfléchir sur
papier. Dans l’art d’écrire des programmes, il est impérieux de savoir formaliser et expliciter
son raisonnement à l’intention de l’ordinateur.

Au-delà de l’algorithmique procédurale, l’algorithmique dite orientée objet (AOO)


repose essentiellement sur des concepts de classe, objet, héritage, encapsulation et
12

polymorphisme. Les avantages de l’AOO sont : une meilleure maîtrise de la complexité


(diviser un problème complexe en une suite de petits problèmes), un réemploi plus facile, une
meilleure facilité de correction et d’évolution.

Cet ouvrage de dix chapitres donne, d’une façon très méthodique, tous outils
nécessaires pour concevoir un algorithme efficace et aussi la possibilité d’apprendre
facilement n’importe quel langage de programmation. Chaque chapitre du livre se termine par
une série d’exercices et les résolutions sont placées en annexe. Pour tester la véracité de
certains algorithmes sur ordinateur, nous nous sommes servis d’AlgoBox.

Dépouillé de tout fondement mathématique et rattachement à un langage de


programmation particulier, cet ouvrage a été conçu sous forme d’un cours, avec une démarche
assez claire et très progressive. Les énoncés des exercices et certaines solutions ont été glané
par-ci, par-là sur internet et livres [1-18].

Le premier chapitre présente les différents concepts de base de l’algorithmique. Il se


termine par la présentation et le fonctionnement d’AlgoBox, un logiciel libre, multiplateforme
et gratuit d’aide à l’élaboration et à l’exécution d’algorithmes.

Dans le second chapitre, nous introduisons la notion de variable et son utilisation. Les
instructions aussi sont présentées avec illustrations sous AlgoBox. Il est aussi consacré aux
deux autres instructions de base que sont la lecture et l’écriture.

Toutes les possibilités relatives aux instructions de branchements conditionnels et


leurs imbrications font l’objet du troisième chapitre.

Le quatrième chapitre introduit les différentes sortes de boucles (structures


répétitives, structures de répétition ou encore structures itératives). La possibilité d’imbriquer
les boucles est aussi indiquée.

Les tableaux uni ou multidimensionnels statiques et dynamiques ainsi que les


différents algorithmes de tri font l’objet du cinquième chapitre. La recherche par dichotomie
est aussi réalisée.
13

Dans le sixième chapitre, nous jetons un regard intéressé sur les notions de fonctions
et procédures. Nous donnons, d’une façon non exhaustive, les fonctions mathématiques, sur
chaînes, de conversion. Il se termine par la notion de récursivité.

Pour assurer la gestion de grandes masses données, nous avons pensé à l’introduction
de la notion de fichier au septième chapitre.

Le huitième chapitre introduit les principales notions liées à l’orienté objet, le cœur de
notre ouvrage. Chaque notion est bien illustrée avec beaucoup d’exemples. Les différentes
notions sont regroupées dans une application de gestion des notes d’étudiants.

Dans le neuvième chapitre, nous nous attelons sur la suite des notions de l’orienté
objet. Il est aussi exploré la possibilité de faire les liens entre différentes classes d’une
application consustituves d’une appliction.

La notion de complexité algorithmique clos le contenu de ce livre. Au-delà de la


définition, elle est ullistrée et évaluée.
14
15

Chapitre 1 : Notions de base


Le mot algorithme vient du nom latinisé du mathématicien perse Al-Khawarizmi
(783-850), écrivant en langue arabe et surnommé « le père de l’algèbre ». On peut trouver des
algorithmes là où on ne les soupçonne pas : recette de cuisine, mode d’emploi, itinéraire
routier, etc.

1.1. Qu’est-ce qu’un algorithme ?


1.1.1. Définition

Dans la littérature, il existe plusieurs définitions du concept algorithme. Toutefois, un


algorithme peut être défini comme une séquence d’actions permettant d’arriver à un résultat
déterminé à partir d’une situation donnée.

D’un point de vue purement informatique, nous pouvons définir un algorithme comme
une suite finie et non ambiguë d’opérations ou instructions, qui une fois exécutée
correctement, conduit à un résultat donné.

Pour fonctionner, un algorithme doit donc pouvoir contenir uniquement des instructions
compréhensibles par celui qui devra l’exécuter. Ainsi, il doit respecter les règles suivantes :
 être défini sans ambiguïté
 se terminer après un nombre fini d’opérations
 toutes les opérations en doivent pouvoir être effectuées par un homme utilisant des
moyens manuels
 manipuler des objets qui doivent être définis de façon très précise.

1.1.2. Exemple d’un algorithme

Cet algorithme est extrait d’un dialogue entre un touriste égaré et un autochtone
 Pourriez-vous m’indiquer le chemin de la cathédrale, s’il vous plait ?
 Oui bien sûr : vous allez tout droit jusqu’au prochain carrefour, vous prenez à gauche
au carrefour et ensuite la troisième à droite, et vous verrez la cathédrale juste en face
de vous
 Merci
16

Dans ce dialogue, la réponse de l’autochtone est la description d’une suite ordonnée


d’instructions (allez tout droit, prenez à gauche, prenez la troisième à droite) qui manipulent
des données (carrefour, rues) pour réaliser la tâche désirée (aller à la cathédrale).

Nous pouvons aussi dire qu’un algorithme est un ensemble de règles opératoires
rigoureuses, ordonnant à un processeur d'exécuter dans un ordre déterminé une succession
d'opérations élémentaires, pour résoudre un problème donné.

C'est un outil méthodologique général qui ne doit pas être confondu avec le
programme proprement dit.

1.2. Programme informatique

Un algorithme, traduit dans un langage compréhensible par l’ordinateur (ou langage de


programmation), donne un programme. Ce dernier peut ensuite être exécuté, pour effectuer le
traitement souhaité.

Dès lors, un algorithme exprime la structure logique d’un programme informatique et


de ce fait est indépendant du langage de programmation utilisé. Par contre, la traduction de
l’algorithme dans un langage particulier dépend du langage choisi et sa mise en œuvre dépend
également de la plateforme d’exécution.

Un programme est alors constitué d’un ensemble de directives, nommées instructions,


qui spécifient :
 les opérations élémentaires à exécuter,
 la manière dont elles s’enchaînent.

1.3. Pourquoi utiliser un algorithme ?

Un ordinateur est un ensemble de circuits électroniques permettant de manipuler des


informations qu’on appelle des données et capable de faire "tourner" des programmes, c’est-à-
dire une suite ou séquence d’instructions programmées à l’avance et qu’il va dérouler du
début à la fin dans le but d’obtenir des résultats.
17

L’algorithme, ou pseudo-code, décrit formellement ce que doit faire l’ordinateur pour


arriver à un but bien précis. Ce sont les instructions qu’on doit lui donner. Ces instructions
sont souvent décrites dans un langage clair et compréhensible par l’être humain : faire ceci,
faire cela si le résultat a telle valeur, et ainsi de suite.

Un algorithme bien établi et qui fonctionne (tout au moins en théorie) pourra être
directement réécrit dans un langage de programmation évolué comme le C, Java ou PHP.
Malheureusement, en programmation c’est souvent à l’homme de se mettre au niveau de la
machine.

Figure 1.1 : De la réflexion à la programmation [17, 18]


1.4. Algorithmique

L’algorithmique est la science des algorithmes. 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, on doit en plus se soucier des problèmes de syntaxe, ou de types d’instructions,
propres à ce langage. Apprendre l’algorithmique de manière séparée, c’est donc cerner les
difficultés pour mieux les vaincre.

L’algorithmique permet ainsi de passer d’un problème à résoudre à un algorithme qui


décrit la démarche de résolution du problème. Tandis que la programmation a alors pour rôle
de traduire cet algorithme dans un langage «compréhensible» par l’ordinateur afin qu’il puisse
exécuter l’algorithme automatiquement.

Elle s’intéresse donc à l’art de construire des algorithmes ainsi qu’à caractériser leur
validité, leur robustesse, leur réutilisabilité, leur complexité ou leur efficacité.
18

Figure 1.2 : Du problème au code source

1.4.1. Validité d’un algorithme

La validité d’un algorithme est son aptitude à réaliser exactement la tâche pour
laquelle il a été conçu.

Si l’on reprend l’exemple de l’algorithme de recherche du chemin de la cathédrale,


l’étude de sa validité consiste à s’assurer qu’on arrive effectivement à la cathédrale en
exécutant scrupuleusement les instructions dans l’ordre annoncé.

1.4.2. Robustesse d’un algorithme

C’est son aptitude à se protéger de conditions anormales d’utilisation.

Dans l’exemple de recherche du chemin de la cathédrale, la question de la robustesse


de l’algorithme se pose par exemple si le chemin proposé a été pensé pour un piéton, alors
que le «touriste égaré » est en voiture et que la «troisième à droite » est en sens interdit.
19

1.4.3. Réutilisabilité d’un algorithme

C’est son aptitude à être réutilisé pour résoudre des tâches équivalentes à celle pour
laquelle il a été conçu.

L’algorithme de recherche du chemin de la cathédrale est-il réutilisable tel quel pour


se rendre à la mairie? A priori non, sauf si la mairie est juste à côté de la cathédrale.

1.4.4. Complexité d’un algorithme

C’est le nombre d’instructions élémentaires à exécuter pour réaliser la tâche pour


laquelle il a été conçu.

Si le « touriste égaré » est un piéton, la complexité de l’algorithme de recherche de


chemin peut se compter en nombre de pas pour arriver à la cathédrale.

1.4.5. Efficacité d’un algorithme

C’est son aptitude à utiliser de manière optimale les ressources du matériel qui
l’exécute.
N’existerait-il pas un raccourci piétonnier pour arriver plus vite à la cathédrale?

1.5. Formalisme de représentation d’un algorithme

Le but d’un algorithme étant de décrire un traitement informatique dans quelque chose
de compréhensible par l’humain (et facilement transposable vers la machine), pour qu’un
algorithme soit compréhensible, il faut qu’il soit clair et lisible. Dans ce cas, il existe deux
moyens efficaces:
 soit d’écrire l’algorithme sous forme de texte simple et évident (faire ceci, faire cela),
 soit de faire un schéma explicatif avec des symboles.

Dans la pratique, les deux formes sont possibles. Mais un dessin ne vaut-il pas un long
discours ? Il est d’ailleurs courant de commencer par un schéma, puis quand celui-ci devient
trop complexe, de passer à un texte explicatif.
20

Dans les deux cas, la syntaxe pour le texte ou les symboles pour les schémas doivent
répondre à des règles strictes, voire normalisées. Il faut que chacun connaisse leur
signification et sache donc les interpréter. C’est pour ça que toutes les représentations
algorithmiques suivent à peu de choses près le même formalisme. Si les schémas sont
possibles, ils sont cependant de moins à moins utilisés que les algorithmes sous forme
textuelle. C’est que si vous construisez un algorithme (ou « pseudocode »), il est plus facile de
le corriger quand il est saisi au clavier sous forme de texte que lorsqu’il est dessiné sous forme
d’organigramme dans un logiciel de dessin vectoriel ou de présentation.

1.6. Langages évolués

Malgré leur multitude, la plupart des langages de programmation se basent sur un bon
nombre de principes fondamentaux communs.

Certains découlent immédiatement de la nature même de l’ordinateur et de l’existence


d’un programme de traduction. C’est, par exemple, le cas de la notion de variable: elle
consiste à donner un nom à un emplacement de la mémoire destiné à contenir une
information. Elle est donc liée à la fois à la notion technologique d’adresse et à l’existence
d’un compilateur. De même, tout langage possède :
 des instructions dites d’affectation : elles permettent de calculer la valeur d’une
expression et de la ranger dans une variable ;
 des instructions permettant d’échanger des informations entre la mémoire et des
périphériques (qu’ils soient de communication ou d’archivage). On parle
d’instructions :
 de lecture, lorsque l’échange a lieu du périphérique vers la mémoire,
 d’écriture, lorsque l’échange a lieu de la mémoire vers le périphérique.

D’autres concepts, plus théoriques, ont été inventés par l’homme pour faciliter
l’activité de programmation. C’est notamment le cas de ce que l’on nomme les structures de
contrôle, les structures de données, les fonctions et, plus récemment, les objets.

Les structures de contrôle servent à préciser comment doivent s’enchaîner les


instructions d’un programme. En particulier, elles permettent d’exprimer les répétitions et les
21

choix: on parle alors de structure de choix (ou branchements) ou de structure de répétition


(ou boucles). Bien entendu, au bout du compte, après traduction du programme, ces structures
se ramènent à des instructions machine et elles font finalement intervenir des instructions de
branchement.

Les structures de données servent à mieux représenter les informations qui doivent
être manipulées par un programme. C’est le cas de la notion de tableau dans laquelle un seul
nom permet de désigner une liste ordonnée de valeurs, chaque valeur étant repérée par un
numéro nommé indice.

La fonction (ou procédure) permet de donner un nom à un ensemble d’instructions


qu’il devient possible d’utiliser à volonté, sans avoir à les écrire plusieurs fois. Comme dans
le cas d’une fonction mathématique, ces instructions peuvent être paramétrées, de façon à
pouvoir être utilisées à différentes reprises avec des variables différentes, nommées
paramètres. Le bon usage des fonctions permet de structurer un programme en le
décomposant en différentes unités relativement indépendantes.

Les notions d’objet et de classe sont les piliers de la programmation orientée objet. Un
même objet regroupe, à la fois des données et des fonctions (nommées alors méthodes) ;
seules ces méthodes sont habilitées à accéder aux données de l’objet concerné. La classe
généralise aux objets la notion de type des variables. Elle définit les caractéristiques d’objets
disposant de la même structure de donnée et des mêmes méthodes. Cette notion de classe
offre une nouvelle possibilité de décomposition et de structuration des programmes. Elle sera
complétée par les notions :
 d’héritage : possibilité d’exploiter une classe existante en lui ajoutant de nouvelles
fonctionnalités
 de polymorphisme : possibilité de s’adresser à un objet sans en connaître exactement la
nature, en le laissant adapter son comportement à sa nature véritable.

On parle généralement de langage procédural pour qualifier un langage disposant de


la notion de procédure (ou fonction), ce qui est le cas de tous les langages actuels. On parle
souvent de langage objet pour qualifier un langage qui, en plus de l’aspect procédural, dispose
de possibilités orientées objets. En toute rigueur, certains langages objet ne disposent pas de la
fonction « usuelle », les seules fonctions existantes étant les méthodes des objets. De tels
22

langages sont souvent qualifiés de totalement orientés objets. Ils sont cependant assez rares et,
de toute façon, en dehors de cette différence, ils utilisent les mêmes concepts fondamentaux
que les autres langages. Les autres langages objet permettent de faire cohabiter la
décomposition procédurale avec la décomposition objet.

Dans la suite de l’ouvrage, nous étudierons d’abord les notions communes aux
langages procéduraux, avant d’aborder les concepts objet. Cette démarche nous semble
justifiée par le fait que la programmation orientée objet s’appuie sur les concepts procéduraux
(même la notion de méthode reste très proche de celle de fonction).

Un algorithme informatique se ramène donc toujours au bout du compte à la combinaison de


des quatre petites briques de base que sont :
 l’affectation de variables
 la lecture / écriture
 les tests
 les boucles

1.7. Que faut-il pour être bon en Algorithmique ?

Rien de sorcier, la maîtrise de l’algorithmique requiert ipso facto deux qualités, très
complémentaires d’ailleurs :

 il faut avoir une certaine intuition, car aucune recette ne permet de savoir a priori
quelles instructions permettront d’obtenir le résultat voulu. C’est là, si l’on y tient,
qu’intervient la forme « d’intelligence » requise pour l’algorithmique. Alors, c’est
certain, il y a des gens qui possèdent au départ davantage cette intuition que les autres.
Cependant, les réflexes, cela s’acquiert. Et ce qu’on appelle l’intuition n’est
finalement que de l’expérience tellement répétée que le raisonnement, au départ
laborieux, finit par devenir « spontané ».

 il faut être méthodique et rigoureux. En effet, chaque fois qu’on écrit une série
d’instructions qu’on croit justes, il faut systématiquement se mettre mentalement à la
place de la machine qui va les exécuter, armé d'un papier et d'un crayon, afin de
vérifier si le résultat obtenu est bien celui que l’on voulait. Cette opération ne requiert
23

pas la moindre once d’intelligence. Mais elle reste néanmoins indispensable, si l’on ne
veut pas écrire à l’aveuglette.

Et petit à petit, à force de pratiquer, vous verrez que vous pourrez faire de plus en plus
souvent l’économie de cette dernière étape : l’expérience fera que vous « verrez » le résultat
produit par vos instructions, au fur et à mesure que vous les écrirez. Naturellement, cet
apprentissage est long, et demande des heures de travail patient. Aussi, dans un premier
temps, évitez de sauter les étapes : la vérification méthodique, pas à pas, de chacun de vos
algorithmes représente plus de la moitié du travail à accomplir... et le gage de vos progrès.

1.8. AlgoBox

Au-delà de la feuille et du crayon et indépendamment de tout langage de


programmation, AlgoBox est un logiciel libre, multiplateforme et gratuit d’aide à l’élaboration
et à l’exécution d’algorithmes.

AlgoBox permet à travers un « mini-langage » et des commandes prêtes à l'emploi de


créer des algorithmes qui détailleront de façon précise à l'ordinateur la liste d’instructions à
suivre. Une fois l'algorithme mis au point, il devra être testé afin de vérifier que l'on obtient
bien le résultat désiré.

1.8.1. Présentation de l’interface d’AlgoBox

Le logiciel AlgoBox propose deux modes d’édition d’algorithme :


 Mode normal (pour les débutants, le logiciel vous guidera pas par pas dans la création
du code du programme)
 Mode éditeur du texte (pour ceux qui connaissent le logiciel, le mode permet de taper
le code directement sur un cadre prévu à cet effet).

Contrairement au mode « éditeur de texte » où l’on peut taper directement le code


source sur l’écran, le mode normal s’utilise avec les boutons à droite et en bas de la fenêtre.
24

Figure 1.3 : Interface d’AlgoBox

1.8.2. Fonctionnement général

Le fonctionnement d'AlgoBox est basé sur les deux principes suivants :


 Pour pouvoir utiliser une variable dans son algorithme, il faut d'abord la déclarer en
utilisant le bouton qui est activable à tout moment.

 Pour ajouter un nouvel élément à l'algorithme (autre que la déclaration d'une variable),
il faut d'abord insérer une nouvelle ligne en utilisant le bouton.

 Une fois que l'on est positionné sur une nouvelle ligne, il suffit de cliquer sur l'un des
boutons disponibles dans le panneau "Ajouter code" pour insérer l'instruction (ou le
bloc d'instructions) désiré.
 Pour tester le fonctionnement de l'algorithme, il suffit de cliquer sur le bouton
25

 Une fenêtre apparaît alors dans laquelle il suffit de cliquer sur le bouton pour

procéder à l'exécution de l'algorithme.

Au-delà de Nouveau, Ouvrir et Sauver liés au menu Fichier, via le menu Édition, il
est possible de copier/coller/couper une ligne de code, mais cette option n'est valable que pour
les lignes du type ...PREND_LA_VALEUR..., AFFICHER.... et TRACER.....

Nota : Pour coller une ligne de code, il faut d'abord créer une nouvelle ligne conformément
aux règles d'édition en vigueur sur AlgoBox.

1.9. Exercices
Exercice 1.1
Qu’est-ce qui différencie fondamentalement un algorithme d’un programme
informatique ?
Exercice 1.2
Qui a besoin de l’algorithmique ?
Exercice 1.3
Faut-il être forcément mathématicien pour être bon en algorithmique ?
Exercice 1.4
Peut-on exécuter sur ordinateur un algorithme non traduit dans un langage de
programmation ?
Exercice 1.5
Peut-on faire la programmation orientée objet avec le logiciel AlgoBox ?
26

Chapitre 2 : Variables et instructions

2.1. Objets

Un algorithme est sensé manipuler plusieurs sortes d’objets. Ces derniers peuvent être
catégorisés comme suit :
2. Les objets d’entrée : données fournies à l’algorithme
3. Les objets de sortie: résultats produits par l’algorithme
4. Les objets internes : ce sont des objets servant aux manipulations internes de
l’algorithme

Le traitement d’un objet concerne la valeur de cet objet. Un objet dont la valeur ne
peut pas être modifiée dans un algorithme est une constante, sinon c’est une variable. Un
objet est parfaitement défini si nous connaissons ces trois caractéristiques :
 Son identifiant ou nom: il est représenté par une vie quelconque de caractères
alphanumériques commençant obligatoirement par une lettre
 Sa valeur ou son contenu (une constante ou une variable)
 Son type ou sa nature: le type d’un objet est défini par un ensemble de valeurs
constantes et par l’ensemble des opérations que nous pouvons appliquer à ces
constantes.

Les objets peuvent être de type (appelé aussi domaine de définition): numérique (entier
ou réel), alphanumérique (caractère ou chaîne), booléen (sensé prendre la valeur vrai ou faux),
monétaire ou date. En algorithmique, on ne se tracassera pas trop avec les sous-types de
variables numériques.

Tous les objets utilisés dans un algorithme doivent être déclarés. Ainsi, nous
déterminons quels sont les objets de valeurs constantes et variables. La syntaxe de déclaration
d’objet constante ou variable est la suivante :
Constantes
nomObjet = valeur
Variables
nomObjet : type
27

Nota :
 Si plusieurs variables sont de même type, nous pouvons les regrouper sur une même
ligne.
 Les constantes sont déclarées en premier
 Les termes réservés Constantes et Variables (VARIABLES pour AlgoBox) ne figurent
qu’une seule fois dans l’algorithme.

Exemples :
Constantes
pi = 3.14
Variables
montant : réel
somme, moyenne : réel
quantite : entier
nom : chaîne
car : caractère

Pour les variables contenant des nombres réels, ces derniers s’écrivent avec une vraie
virgule comme en français "3,14" ou avec le point décimal. Cependant dans les langages de
programmation, ce sera bien souvent le point qui sera utilisé "3.14".

En pseudocode algorithmique, les chaînes de caractères sont placées entre guillemets


pour deux raisons :
 Éviter une ambiguïté entre les nombres sous forme de chaîne de caractères et les
nombres au format numérique.
 Ne pas confondre le nom de la variable avec son contenu, notamment lors d’une
affectation.

Notons qu’AlgoBox ne supporte pas les constantes et les variables booléennes.

2.2. Variables
2.2.1. Définition

Du point de vue de l’ordinateur, une variable est une zone de mémoire au contenu de
laquelle on accède via un identificateur. Par contre, du point de vue algorithmique, une
variable est caractérisée par son nom, sa structure (variable simple, liste, tableau, fichier), son
type et sa valeur qui peut changer en cours d’exécution de l’algorithme.
28

Les noms de variables doivent de préférence assez courts mais aussi explicites que
possible, de manière à exprimer clairement ce que la variable est censée référencer.

2.2.2. Règles de nommage

Chacun est libre de donner les noms à ses variables, mais le mieux est de choisir des
noms significatifs (montant sera un meilleur choix que x pour désigner le montant d’une
facture).

Pour faciliter la lecture des algorithmes, il convient de respecter des règles suivantes
pour nommer les variables :
• Le nom d’une variable commence par une lettre minuscule
• Le nom d’une variable ne comporte pas d’espace
• Si le nom de la variable est composé de plusieurs mots, il faut faire commencer
chacun d’eux par une majuscule (par exemple: prixVente, valeurMaxOuMin) et ne
pas faire figurer de traits d’union
• Il faut également faire attention à bien donner aux variables un nom explicite
(éviter i2, zz2 …)

2.2.3. Variables en AlgoBox

Avant de pouvoir utiliser des variables sur le logiciel AlgoBox, il faudra les déclarer
dans le préambule du programme (c’est le code entre la rubrique VARIABLES et
DEBUT_ALGORITHME).

AlgoBox permet l'utilisation de trois types de variables : les nombres (type


NOMBRE), les listes de nombres (type LISTE) et les chaînes de caractères (type CHAINE).

Exemple : Si nous voulons déclarer une variable montant qui est de type NOMBRE, nous

pouvons utiliser le bouton suivant dans le mode guidé :


Nous utilisons la fenêtre :
29

Nous obtenons finalement le code suivant :


VARIABLES
montant EST_DU_TYPE NOMBRE

2.3. Structure d’un algorithme

Un algorithme sera défini par :


 Un nom ;
 Déclarations des variables et des constantes ;
 Les actions constituant le traitement a exécuté seront délimitées par les termes Debut
et Fin.

Afin de permettre une grande lisibilité, il faudra utiliser des commentaires en les
faisant précédés par deux fois slashs (// commentaires) ou délimités par les sigles (/*
commentaires */).

La structure globale d’un algorithme se présente comme suit:

Algorithme nomAlgorithme // partie en-tête


[Constantes // partie déclaration
nomConstante = valeur]
[Variables
nomVariable : type]
Debut // partie traitement
Bloc d’instructions
Fin

Un bloc d’instructions est une partie de traitement d’un algorithme, constituée


d’opérations élémentaires situées entre Debut et Fin ou entre accolades.
30

2.4. Affectation
2.4.1. Utilisateur et concepteur

En programmation, il y a deux types de personnes :


 le programmeur qui conçoit le code de l’algorithme ;
 l’utilisateur qui utilise et exécute le programme.
Remarque
L’utilisateur peut très bien être le concepteur du programme (ou programmeur). Ainsi,
il y a deux types de variables :
 des variables dont l’affectation (attribution d’une valeur ou d’un contenu) est faite par
le programmeur ;
 des variables dont l’affectation est faite par l’utilisateur.

Une variable est affectée par le programmeur si l’attribution de sa valeur se fait dans le
code.

2.4.2. Syntaxe

Pour donner une valeur à une variable, il faut passer par un processus d’affectation à
l’aide d’un opérateur. En pseudocode, on utilise le symbole d’affectation « ← ». À gauche de
ce symbole, vous placez le nom de la variable, à droite la valeur.
nomVariable ← valeur
La valeur peut être :
 Une variable du même type que nomVariable
 Une constante du dit nomVariable
 Une expression dont l’évaluation produit un résultat du même type que nomVariable

Vous trouverez aussi dans certaines représentations algorithmiques le « := » issu du


Pascal. Les deux sont équivalents et utilisables (mais évitez de les mélanger, pour s’y
retrouver). Dans cet ouvrage, nous option exclusivement pour la première représentation.

Exemple :
montant ← 25
Attribue la valeur 25 à la variable montant.
31

Dans AlgoBox, l’instruction PREND_LA_VALEUR permet d’affecter une variable


déclarée d’une certaine valeur.
Affectation par le programmeur
Si on veut affecter une variable numérique montant (déclarée dans le préambule du de
l’algorithme) de la valeur 25, on écrit ceci :
VARIABLES
montant EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
montant PREND_LA_VALEUR 25
FIN_ALGORITHME

* Bouton guide :

Vous avez aussi le droit de donner une valeur initiale ou par défaut à une variable lors
de sa déclaration. Dans ce cas vous devez utiliser l’opérateur d’affectation lors de la
déclaration.

Exemple :
Variables
montant ← 25: entier
M.

2.4.3. Expressions et opérateurs


a. Expressions

Une expression est un ensemble de valeurs, reliées par des opérateurs, et équivalent à
une seule valeur. Dès lors, dans une expression, on peut trouver des variables, des constantes
et des opérateurs.

b. Opérateurs

Un opérateur est un signe qui relie deux valeurs, pour produire un résultat. Les
opérateurs possibles dépendent du type des valeurs qui sont en jeu.

b.1. Opérateurs numériques

Ce sont les quatre opérations arithmétiques, tout ce qu’il y a de classique.

+ : addition
32

- : soustraction

* : multiplication

/ : division

Mentionnons également le ^ qui signifie « puissance ». 45 au carré s’écrira donc 45 ^2.


Il y a aussi DIV pour la « division entière » (45 DIV 2 = 22) et MOD (ou %) pour le « reste
de la division entière » (45 MOD 2 = 1).

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 ?

En revanche, 12 * (3 + 5) vaut 12 * 8 soit 96. Rien de difficile là-dedans, que du normal.

Quelques langages admettent des opérateurs arithmétiques unaires, c’est-à-dire qui ne


prennent qu’une valeur :

++ x incrémente de 1 la variable x

x ++ idem mais après l’utilisation en cours

-- x décrémente de 1 la variable x

x -- idem mais après l’utilisation en cours

Les opérateurs + et - peuvent aussi être utilisés comme opérateurs unaires : placés
avant une constante ou une variable, le signe "-" donnera l’opposé de cette valeur (--1est égal
à 1).

b.2. Opérateur alphanumérique : &

Cet opérateur permet de concaténer, autrement dit d’agglomérer, deux chaînes de


caractères.

Exemple :

Variables
33

a, b, c : chaîne

Debut
a ← "Bon"
b ← "jour"
c←a&b
Fin

La valeur de c à la fin de l’algorithme est "Bonjour".


34

b.3. Opérateurs logiques (ou booléens)

Il s’agit du et (ou ET), du ou (ou OU), du non (ou NON), et du mystérieux (mais
rarissime xor (ou XOR)).

2.4.4. Erreurs à éviter

Les erreurs les plus courantes concernant l’utilisation des variables sont:
• Une variable n’est déclarée qu’une seule fois dans un algorithme ;
• Une variable est déclarée au début de l’algorithme et non dans la partie réservée
aux instructions de traitement
• Avant de pouvoir utiliser une variable, il faut l’avoir déclarée dans le bloc des
variables
• Avant de pouvoir utiliser la valeur d’une variable, une valeur doit lui être
attribuée.

Exemple :
Algorithme variablesErreurs
Variables
nombre, resultat : réel
Debut
resultat ← nombre * 2 //erreur : nombre n’a pas de valeur
valeur ←1 //erreur : valeur n’a pas été définie
Fin

2.5. Saisie et affichage


2.5.1. Affichage

Pour simuler l’affichage d’un texte ou d’une valeur sur l’écran, il faut utiliser la
pseudo instruction "afficher" ou "ecrire" qui prend à sa suite une chaîne de texte ou une
variable. Si vous mélangez du texte et des variables, séparez ceux-ci par des virgules. À
l’affichage, les virgules seront remplacées par des espaces.

Exemple :
Algorithme affiche
Variables
a: entier
texte: chaîne
35

Debut
a←10
texte ← "Hello World"
afficher a
afficher texte
afficher "Bonjour les amis"
Fin

Dans AlgoBox, on utilise l’instruction AFFICHER pour pouvoir permettre d’afficher


la valeur d’une variable ou un message, mais pas les deux à la fois.
 Boutons guide :

et
Le clic sur le premier bouton affiche:

Et le deuxième bouton, on obtient :

L’exemple précédent se présente comme suit :

VARIABLES
a EST_DU_TYPE NOMBRE
texte EST_DU_TYPE CHAINE
DEBUT_ALGORITHME
a PREND_LA_VALEUR 10
AFFICHER a
AFFICHER "Hello World"
AFFICHER texte
AFFICHER "Bonjour les amis"
FIN_ALGORITHME
36

***Algorithme lancé***
10
Hello World
Bonjour les amis
***Algorithme terminé***

2.5.2. Saisie

Une variable est affectée par l’utilisateur si l’attribution de sa valeur se fait pendant
l’exécution du programme.

Pour inviter un utilisateur à rentrer au clavier une valeur utilisez la pseudo instruction
"saisir" ou "lire". L’algorithme attendra alors une entrée au clavier qui sera validée avec la
touche d’entrée. La valeur que vous saisissez sera placée dans la variable indiquée à la suite
de "saisir".

Algorithme saisie
Variables
reponse : chaîne
Debut
afficher "Quel est votre nom ?"
saisir reponse
afficher "Vous vous appelez ", reponse
Fin

Dans AlgoBox, l’instruction LIRE permet de demander à l’utilisateur d’affecter une


valeur à une variable déclarée.

* Bouton guide :

L’exemple précédent se présente comme suit :


VARIABLES
reponse EST_DU_TYPE CHAINE
DEBUT_ALGORITHME
AFFICHER "Quel est votre nom?"
LIRE reponse
AFFICHER "Vous vous appelez "
AFFICHER reponse
FIN_ALGORITHME
37

***Algorithme lancé***
Quel est votre nom?
Entrer reponse : Amel Djungu
Vous vous appelez Amel Djungu
***Algorithme terminé***

Si vous devez saisir plusieurs valeurs à placer chacune dans une variable, vous pouvez
utiliser plusieurs "saisir", mais plus simplement placez les diverses variables à la suite d’un
unique saisir, séparées par des virgules. L’utilisateur devra alors saisir plusieurs valeurs
(selon le langage final : les unes à la suite des autres séparées par des espaces, ou en appuyant
sur la touche [Entrée] après chaque saisie).

Algorithme saisieMultiple
Variables
nom, prenom : chaînes
Debut
afficher "Quels sont vos noms et prénoms ?"
saisir nom, prenom
Fin

2.6. Exemple avec AlgoBox

Connaissant le rayon, l’algorithme ci-dessous permet de calculer respectivement la


surface et le périmètre d’un cercle. Son équivalent AlgoBox et le résultat sont aussi affichés.

Algorithme cercle
Variables
r, pi1, surface, perimetre : réel
Debut
pi1←3,1415927
lire r
surface ← pi1 * r * r
perimetre ← 2 * pi1 * r
afficher surface
afficher perimetre
Fin

Version AlgoBox
VARIABLES
r EST_DU_TYPE NOMBRE
pi1 EST_DU_TYPE NOMBRE
surface EST_DU_TYPE NOMBRE
perimetre EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
38

pi1 PREND_LA_VALEUR 3.1415929


LIRE r
surface PREND_LA_VALEUR pi1*r*r
perimetre PREND_LA_VALEUR 2*pi1*r
AFFICHER surface
AFFICHER perimetre
FIN_ALGORITHME

Résultats
***Algorithme lancé***
Entrer r : 2.5
19.634956
15.707964
***Algorithme terminé***

2.7. Exercices
Exercice 2.1
Quelles seront les valeurs des variables a et b après exécution des instructions
suivantes ?

Algorithme exercice21
Variables
a, b : entier
Debut
a←5
b←a+3
a←7
Fin

Exercice 2.2
Quelles seront les valeurs des variables a, b et c après exécution des instructions
suivantes ?

Algorithme exercice22
Variables
a, b, c : entier
Debut
a←3
b←5
c←a+b
39

a←1
c←b–a
Fin

Exercice 2.3
Quelles seront les valeurs des variables a et b après exécution des instructions
suivantes ?

Algorithme exercice23
Variables
a, b : entier
Debut
a←7
b←1
a←b
b←a
Fin

Les deux dernières instructions permettent-elles d’échanger les deux valeurs de a et b ?


Si l’on inverse les deux dernières instructions, cela change-t-il quelque chose ?

Exercice 2.4
Ecrire un algorithme permettant d’échanger les valeurs de deux variables a et b, et ce
quel que soit leur contenu préalable.

Exercice 2.5
Soient trois variables a, b et c (supposées du même type). Écrire les instructions
permutant leurs valeurs, de sorte que la valeur de b passe dans a, celle de c dans b et celle de a
dans c.

Exercice 2.6
En supposant que les variables a, b et c sont de type entier et qu’elles contiennent
respectivement les valeurs 5, 8 et 19, déterminer les valeurs des expressions suivantes :
a+b/c
a+c/b
(a + c) / b
a+b/a+b
(a + b) / (a + b)
40

Exercice 2.7
Que produit l’algorithme suivant ?

Algorithme exercice27
Variables
a, b, c : chaine
Debut
a ← "123"
b ← "45"
c←a+b
Fin

Exercice 2.8
Que produit l’algorithme suivant ?

Algorithme exercice28
Variables
a, b, c : chaine
Debut
a ← "123"
b ← "45"
c←a&b
Fin

Exercice 2.9
Quel résultat produit le programme suivant ?

Algorithme exercice29
Variables
val, prod : réel
Debut
val ← 15
prod ← val * 5
afficher val
afficher prod
Fin

Exercice 2.10

Ecrire un programme qui demande un nombre à l’utilisateur, puis qui calcule et affiche
le carré de ce nombre.
41

Exercice 2.11

Écrire un programme qui demande deux nombres entiers et qui fournit leur somme et
leur produit.

Exercice 2.12

Ecrire un algorithme qui demande à l'utilisateur de taper 5 entiers et qui affiche leur
moyenne.

Exercice 2.13
Ecrire un algorithme qui permet d’introduire à l’ordinateur son prénom et nom son à
partir du clavier. Demander ensuite à l’ordinateur de les afficher à l’écran.

Exercice 2.14

Ecrire un algorithme qui permet d’introduire à l’ordinateur les cotes sur 10 obtenues
respectivement à l’examen et aux travaux pratiques dans un cours. Demander ensuite à
l’ordinateur de calculer la cote globale obtenue sur 20 points dans ce cours et de l’afficher à
l’écran.

Exercice 2.15

Ecrire un algorithme qui permet de convertir de francs en dollars.


Exercice 2.16

Ecrire un algorithme qui prend une somme en dollars et la décompose en billets de 10,
5 et 1 dollar.

Exercice 2.17

Ecrire un algorithme qui demande à l'utilisateur de taper le prix prixHT d'un kilo de
tomates, le nombre de kilos de tomates achetés, le taux de tva (Exemple 10%, 16%, ...).
L’algorithme affiche alors le prix total prixTTC des marchandises. Faire en sorte que des
libellés apparaissent clairement.
42

Exercice 2.18

Ecrire un algorithme qui demande à l'utilisateur de saisir la largeur et la longueur d'un


champ et qui en affiche le périmètre et la surface.

Exercice 2.19

Ecrire un algorithme qui permet de demander à l’ordinateur de calculer le périmètre et


la surface d’un cercle et de l’afficher à l’écran, sur base de la valeur du rayon de ce cercle
introduite à partir du clavier.

Exercice 2.20

Ecrire un algorithme qui calcule la surface et le volume d’une sphère.


43

Chapitre 3 : Branchements conditionnels


3.1. Introduction

L’ordinateur est une machine de traitement automatique de l’information. Son intérêt


essentiel et sa puissance proviennent de deux choses :
 la possibilité d’effectuer des choix dans le traitement réalisé. Dans un programme de
facturation, par exemple, on déterminera une remise dont le pourcentage dépendra du
montant de la facture ;
 la possibilité de répéter plusieurs fois les mêmes instructions. Un programme de
facturation, par exemple, répètera pour chaque client les instructions d’établissement
d’une facture.

Comme on peut s’y attendre, ces choix et ces répétitions sont réalisables dans tous les
langages de programmation. En définitive, nous pouvons dire qu’un algorithme comporte
deux sortes d’instructions [8]:
 les instructions de base : elles réalisent une certaine action: affectation, lecture,
écriture (cfr le chapitre 2);
 les instructions de structuration du programme : elles servent à préciser comment
doivent s’enchaîner chronologiquement ces instructions de base. On les nomme
également instructions structurées ou instructions de contrôle ou encore structures de
contrôle.

Dans ce chapitre, nous allons exclusivement nous atteler sur la structure de choix
(instruction conditionnelle, structure conditionnelle, branchement conditionnel ou encore
test). Les structures de répétition ou boucles seront étudiées dans le chapitre suivant.

3.2. Opérateurs de comparaison

Suivant les langages de programmation, les symboles de comparaison prendront des


aspects différents. Ils servent essentiellement à effectuer des comparaisons. Dans cet ouvrage,
nous utiliserons les symboles suivants pour faire les tests:
44

Symbole Signification pour les types Signification pour les types caractères
numériques (entier ou réel)
= ou == égal à égal à
< inférieur à placé avant dans l’ordre alphabétique
> supérieur à placé après dans l’ordre alphabétique
<= inférieur ou égal à placé avant dans l’ordre alphabétique ou égal
= supérieur ou égal à placé après dans l’ordre alphabétique ou égal
<> ou != différent de différent de

Tableau 3.1 : Opérateurs de comparaison

Pour faire la comparaison, en AlgoBox, utilisez exclusivement == pour l’égalité et !=


pour différent de.

3.3. Structure alternative

Elle détermine si le bloc d’instructions suivant est exécuté ou non. La condition est
une expression booléenne dont la valeur détermine le bloc d’instructions à exécuter.

La syntaxe de cette instruction est :


si (condition) alors
{
action 1 // exécutée si condition égale vrai
}
sinon
{
action 2 // exécutée si condition égale faux
}

où action 1 et action 2 peuvent être une instruction, un ensemble d’instructions ou un


algorithme.

Sur AlgoBox :

SI (< condition >) ALORS


DEBUT_SI
// bloc d’instructions
FIN_SI
SINON
DEBUT_SINON
// bloc d’instructions
FIN_SINON
45

* Bouton Guide :

Exemple : Ecrire un algorithme permettant de lire deux entiers et d’afficher le plus grand des
deux.
Algorithme maxDeDeuxEntiers
Variables
x, y, max : entiers
Debut
lire x
lire y
si (x > y) alors
{
max ← x
}
sinon
{
max ← y
}
afficher ("Le maximum est : ", max)
Fin

On peut simplifier l’écriture de l’instruction en omettant les accolades de délimitation


de bloc, lorsqu’il n’y a pas d’ambiguïté (si le bloc ne se compose que d’une seule instruction).

Algorithme maxDeDeuxEntiers
Variables
x, y, max : entiers
Debut
lire x
lire y
si (x > y) alors
max ← x
sinon
max ← y
afficher ("Le maximum est : ", max)
Fin

Sur AlgoBox:
VARIABLES
x EST_DU_TYPE NOMBRE
y EST_DU_TYPE NOMBRE
max EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE x
LIRE y
SI (x > y) ALORS
DEBUT_SI
46

max PREND_LA_VALEUR x
FIN_SI
SINON
DEBUT_SINON
max PREND_LA_VALEUR y
FIN_SINON
AFFICHER "Le maximum est : "
AFFICHER max
FIN_ALGORITHME

***Algorithme lancé***
Entrer x : 12
Entrer y : 5
Le maximum est : 12
***Algorithme terminé***

Notez que la plupart des langages autorisent des conditions formées de plusieurs
conditions simples reliées entre elles par des opérations logiques : et, ou et non.

3.4. Structure conditionnelle

Une version plus simple est utilisée si l’alternative n’a pas lieu. La syntaxe de cette
instruction est alors :
si (condition) alors
{
action
}

Exemple : Ecrire un algorithme qui permet d’afficher la valeur positive d’un nombre s’il est
négatif.

Algorithme valeurPostive
Variables
valeur, positif: entier
Debut
lire valeur
si (valeur < 0) alors
{
positif ← -1*valeur
}
afficher "La valeur positive est : ", positif
Fin
47

Présentation d’un algorithme

Les décalages dans l’écriture d’un algorithme sont nécessaires à sa bonne lisibilité.
Savoir présenter un algorithme, c’est montrer qu’on a compris son exécution.

La règle est très simple: dès qu’un nouveau bloc d’instructions commence par un
Debut ou une accolade ouverte, toutes les instructions suivantes sont décalées d’une
tabulation. Dès qu’une instruction se termine par une Fin ou une accolade fermante, toutes les
instructions suivantes sont décalées d’une tabulation vers la gauche.

3.5. Tests imbriqués

Il peut arriver que l’une des parties d’une structure alternative contienne à son tour une
structure alternative. Dans ce cas, on dit que l’on a des structures imbriquées les unes dans les
autres. Par la suite, nous verrons que cette imbrication peut concerner d’autres structures
comme les boucles. La syntaxe générale des tests imbriqués se présente comme suit :

si (condition 1) alors
{
action 1
}
sinon
{
si (condition 2) alors
{
action 2
}
sinon
{

}
}

Exemple : Ecrire un algorithme permettant d’octroyer une remise :


 de 1% lorsque le montant d’achat est compris entre 200 dollars (inclus) et 500 dollars
(exclus) ;
 de 2% lorsque le montant est supérieur ou égal à 500 dollars.
48

Voici une façon de procéder, en deux étapes. Dans un premier temps, on détermine le
taux de remise, dans la variable réelle taux. Dans un deuxième temps, on applique ce taux
(éventuellement nul), pour calculer la remise dans la variable réelle remise :

si montant < 200 alors taux ← 0


sinon si montant < 500 alors taux ← 1
sinon taux ← 2
remise ← montant * taux/100
montant ← montant - remise

Voici un algorithme complet accompagné de deux exemples d’exécution avec le


logiciel AlgoBox.

Algorithme facturationRemise
Variables
montant, taux, remise : réel
Debut
afficher "Donnez le montant brut : "
lire montant
si (montant < 200) alors
taux ← 0
sinon si (montant < 500) alors
taux ← 1
sinon
taux ← 2
remise ← montant * taux/100
montant ← montant - remise
afficher "Montant après remise : ", montant
Fin

Il est fréquent chez les débutants d’oublier les instructions sinon intermédiaires.

Sur AlgoBox :
VARIABLES
montant EST_DU_TYPE NOMBRE
taux EST_DU_TYPE NOMBRE
remise EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
AFFICHER "Donnez le montant brut: "
LIRE montant
SI (montant< 200) ALORS
DEBUT_SI
taux PREND_LA_VALEUR 0
49

FIN_SI
SINON
DEBUT_SINON
SI (montant< 500) ALORS
DEBUT_SI
taux PREND_LA_VALEUR 1
FIN_SI
SINON
DEBUT_SINON
taux PREND_LA_VALEUR 2
FIN_SINON
FIN_SINON
remise PREND_LA_VALEUR montant * taux/100
montant PREND_LA_VALEUR montant – remise
AFFICHER "Montant après remise: "
AFFICHER montant
FIN_ALGORITHME

***Algorithme lancé***
Donnez le montant brut:
Entrer montant : 300
Montant après remise: 297
***Algorithme terminé***

***Algorithme lancé***
Donnez le montant brut:
Entrer montant : 750
Montant après remise: 735
***Algorithme terminé***

Notez que, dans la formulation utilisant une suite d’exécutions conditionnelles, il est
possible d’éviter le risque de variable non définie, en affectant d’office une valeur à taux
avant d’examiner s’il y a lieu de lui en donner une autre (on utilise une technique
d’initialisation explicite par défaut).

taux ← 0
si ((montant >= 200) et (montant < 500)) alors taux ← 1
sinon si (montant >= 500) alors taux ← 2

Notons qu’il n’y a jamais une seule manière juste de traiter les structures alternatives.
Et plus généralement, il n’y a jamais une seule manière juste de traiter un problème. Entre les
50

différentes possibilités, qui ne sont parfois pas meilleures les unes que les autres, le choix est
une affaire de style.

3.6. Choix multiple

Si les tests imbriqués facilitent parfois la vie, ils deviennent parfois trop lourds lorsque
le nombre de tests devient trop important. Certains langages ont trouvé une intéressante
parade à ce problème en proposant des structures de tests selon_que ou suivant_que telle
expression est vraie, ou telle autre, et ainsi de suite. Au lieu de faire des si imbriqués ou des
sinon si, il suffit alors d’indiquer quoi faire quand telle ou telle valeur est rencontrée.

Une instruction de choix multiple permettant un « aiguillage » (switch, en anglais)


basé sur la valeur d’une expression entière, se présente ainsi :
suivant_que variable faire
{
valeur 1 : action 1
valeur 2 : action 2

valeur n : action n
sinon action]
}
où action 1, action 2, … peuvent être une instruction, un ensemble d’instructions ou un
algorithme.

Nota : Plusieurs valeurs entrainer un même traitement.

Exemple 1: Ecrire un algorithme permettant de demander le numéro du mois en cours et


d’afficher le nom du mois correspondant.

Algorithme afficheMois
Variables
numero : entier
mois : chaine
Debut
afficher "Entrer le numéro du mois : "
lire numero
suivant_que numero faire
51

{
1 : mois ← "Janvier"
2 : mois ← "Février"
3 : mois ← "Mars"
4 : mois ← "Avril"
5 : mois ← "Mai"
6 : mois ← "Juin"
7 : mois ← "Juillet"
8 : mois ← "Août"
9 : mois ← "Septembre"
10 : mois ← "Octobre"
11 : mois ← "Novembre"
12 : mois ← "Décembre"
sinon afficher "Erreur"
}
afficher mois
Fin

Exemple 2: Ecrire un algorithme permettant à un robot de conduire une voiture. En tenant


compte de la couleur du feu qui sera saisi, il peut exécuter trois actions : s’arrêter, ralentir ou
passer.

Algorithme robot
Variables
couleur : chaine
Debut
afficher "Saisir la couleur"
lire couleur
suivant_que couleur faire
{
verte : afficher "passer"
orange : afficher "ralentir"
rouge : afficher "s’arrêter"
sinon afficher "Veuillez saisir une couleur correcte"
}
Fin

Notons qu’AlgoBox ne supporte pas le choix multiple.


52

3.7. Variables booléennes

Jusqu’ici, pour écrire nos tests, nous avons utilisé uniquement des conditions. Mais
vous vous rappelez qu’il existe un type de variables (les booléennes) susceptibles de stocker
les valeurs vrai ou faux. En fait, on peut donc entrer des conditions dans ces variables, et
tester ensuite la valeur de ces variables.

Exemple :

Algorithme robot
Variables
temp : entier
a, b : booléen
Debut
afficher "Entrez la température de l’eau :"
lire temp
a ← temp =< 0
b ← temp < 100
si a alors
afficher "C’est de la glace"
sinon si b alors
afficher "C’est du liquide"
sinon
afficher "C’est de la vapeur"
Fin

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 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 des et et des ou partout) cette technique peut faciliter le travail du
développeur, en améliorant nettement la lisibilité de l’algorithme.

3.8. Exercices
Exercice 3.1
Ecrire un algorithme qui demande un nombre à l’utilisateur, et l’informe ensuite si ce
nombre est positif ou négatif (on laisse de côté le cas où le nombre vaut zéro).

Exercice 3.2
Ecrire un algorithme qui demande un nombre entier à l’utilisateur et qui précise s’il est
ou non compris entre 10 (exclus) et 20 (inclus).
53

Exercice 3.3
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 3.4
Ecrire un algorithme qui demande trois noms à l’utilisateur et l’informe ensuite s’ils
sont rangés ou non dans l’ordre croissant strict.

Exercice 3.5
Coel va dans un magasin d’électro-ménager. Il regarde dans sa poche et constate qu’il
a x dollars dans sa poche (x étant un entier naturel). Il voudrait s’acheter une clé USB à 5 $.
Combien restera-t-il dans sa poche après passage à la caisse ?

Exercice 3.6
Donel va à la fête foraine et joue à un jeu de fléchettes. La cible circulaire a 10 cases
numérotées de 1 à 10. Si elle fait plus de 8 (8 inclus), elle gagne 10 $ sinon elle perd sa mise
de départ de 2 $.

Exercice 3.7
Pour organiser des rencontres sportives, un moniteur doit connaître l'âge des enfants,
puis constituer des équipes homogènes. Parmi les moins de 16 ans et les plus de 6 ans, les
catégories sont : "Poussin" de 6 à 7 ans, "Pupille" de 8 à 9, "Minime" de 10 à 11 et "Cadet"
après 12 ans. Ecrire un algorithme qui classe l'enfant dans la catégorie de son âge. Peut-on
concevoir plusieurs algorithmes équivalents menant à ce résultat ?

Exercice 3.8
Au baccalauréat, la mention associée à une note sur 20 est « très bien » pour les notes
supérieures ou égales à 16, « bien » pour les notes comprises entre 14 inclus et 16 exclu,
« assez bien » pour les notes comprises entre 12 inclus et 14 exclu, « passable » pour les notes
comprises entre 10 inclus et 12 exclu et « insuffisant » pour les notes strictement inférieures à
10.
54

Exercice 3.9
Ecrire un algorithme qui demande 5 notes, calcule la moyenne et attribue la mention
correspondante :
 Si moyenne >= 16, mention "Très bien"
 Si moyenne >= 14, mention "Bien"
 Si moyenne >= 12, mention "Assez bien"
 Si moyenne >= 10, mention "Passable"
 Si moyenne >= 8, "Admis oral du deuxième groupe"
 Sinon "Recalé"

Exercice 3.10
Écrire un algorithme qui lit un prix hors taxe et qui calcule et affiche le prix TTC
(Toutes Taxes Comprises) correspondant (avec un taux de TVA de 16%). Il établit ensuite
une remise dont le taux est le suivant :
 0% pour un montant TTC inférieur à 100 dollars,
 1% pour un montant TTC supérieur ou égal à 100 euros et inférieur à 200 dollars,
 2% pour un montant TTC supérieur ou égal à 2000 euros et inférieur à 500 dollars,
 5% pour un montant TTC supérieur ou égal à 500 dollars.
On affichera la remise obtenue et le nouveau montant TTC.

Exercice 3.11
Ecrire un algorithme qui permet de calculer une équation du second degré.

Exercice 3.12
Ecrire un algorithme destiné à prédire l'avenir, et il doit être infaillible. Il lira au
clavier l’heure et les minutes, et il affichera l’heure qu’il sera une minute plus tard. Par
exemple, si l'utilisateur tape 7 puis 14, l'algorithme doit répondre : "Dans une minute, il sera 7
heure(s) 15". On suppose que l'utilisateur entre une heure valide et donc pas besoin donc de la
vérifier.

Exercice 3.13
Un magasin de reprographie facture 0,10 $ les dix premières photocopies, 0,09 $ les
vingt suivantes et 0,08 $ au-delà. Ecrire un algorithme qui demande à l’utilisateur le nombre
de photocopies effectuées et qui affiche la facture correspondante.
55

Exercice 3.14
Les habitants du Sankuru paient l’impôt selon les règles suivantes :

 les hommes de plus de 20 ans paient l’impôt


 les femmes paient l’impôt si elles ont entre 18 et 35 ans
 les autres ne paient pas d’impôt

L’algorithme demandera donc l’âge et le sexe du Sankurois, et se prononcera donc


ensuite sur le fait que l’habitant est imposable.

Exercice 3.15
Une assurance propose trois tarifs (Vert, Orange et Rouge) selon l’âge et le nombre
d’accidents des automobilistes.
Moins de 25 ans 25 ans et plus
0 accident Orange Vert
1 ou 2 accidents Rouge Orange
3 à 6 accidents Pas assuré Rouge
7 accidents ou plus Pas assuré Pas assuré

Ecrire un algorithme qui affiche le tarif après avoir saisi l’âge et le nombre d’accidents
d’un automobiliste.

Exercice 3.16
Une compagnie d’assurance automobile propose 4 familles de tarifs du moins cher au
plus onéreux : A, B, C et D. Le tarif dépend de la situation du conducteur.
 Un conducteur de moins de 25 ans et titulaire du permis depuis moins de deux ans, se
voit attribuer le tarif D s’il n’a jamais été responsable d’accident. Sinon, la compagnie
refuse de l’assurer.
 Un conducteur de moins de 25 ans et titulaire du permis depuis plus de deux ans, ou
de plus de 25 ans mais titulaire du permis depuis moins de deux ans a le droit au tarif
C s’il n’a jamais provoqué d’accident, au tarif D pour un accident, sinon il est refusé.
 Un conducteur de plus de 25 ans titulaire du permis depuis plus de deux ans bénéficie
du tarif B s’il n’est à l’origine d’aucun accident et du tarif C pour un accident, du tarif
D pour deux accidents, et refusé sinon.
56

Par ailleurs, pour encourager la fidélité de ses clients, la compagnie propose un contrat
au tarif immédiatement inférieur s’il est assuré depuis plus d’un an.

Ecrire un algorithme qui propose un tarif d’assurance selon les caractéristiques d’un
client potentiel.

Exercice 3.17
Vous désirez comparer deux offres d’abonnement téléphonique. La facture est calculée
avec un fixe (somme à payer obligatoirement tous les mois) et une partie proportionnelle au
temps passé à téléphoner (indiqué en minutes).

Offre Fixe Prix à la minute


Telecom 1 10 $ 0.50 $
Telecom 2 15 $ 0.42 $

Ecrire un algorithme qui indique l’opérateur le plus intéressant après avoir saisi la
consommation moyenne mensuelle (en minutes).

Exercice 3.18
Dans un hôtel, sur les prix affichés pour deux chambres ayant les mêmes
caractéristiques, on peut lire :
Chambre A : prix fixe de la chambre 150 dollars + 10 dollars de connexion internet par jour ;
Chambre B : prix fixe de la chambre 170 dollars + 5 dollars de connexion internet par jour ;
On souhaite concevoir un algorithme permettant de trouver le prix le plus avantageux entre
les deux chambres en fonction du nombre de jours de location.

Exercice 3.19
Les élections législatives d’un pays X obéissent à la règle suivante :

 lorsque l'un des candidats obtient plus de 50% des suffrages, il est élu dès le premier
tour.
 en cas de deuxième tour, peuvent participer uniquement les candidats ayant obtenu au
moins 12,5% des voix au premier tour.
57

Ecrire un algorithme qui permet de saisir les scores de quatre candidats au premier
tour. Cet algorithme traitera ensuite le candidat numéro 1 (et uniquement lui) : il dira s'il est
élu, battu, s'il se trouve en ballottage favorable (il participe au second tour en étant arrivé en
tête à l'issue du premier tour) ou défavorable (il participe au second tour sans avoir été en tête
au premier tour).

Exercice 3.20
Ecrire un algorithme qui permet de calculer le lendemain d’une date selon les critères
suivants :
 La date est décomposée dans trois variables année, mois et jour.

 Il faut gérer : les changements de mois

o le nombre de jours dans le mois

o le changement d’année

o les années bissextiles pour le mois de février

 Pour information, une année est bissextile si elle vérifie intégralement deux règles :

o les années divisibles par 4, et,

o les années divisibles par 400 mais pas par 100


58

Chapitre 4 : Boucles
4.1. Introduction

Nous allons maintenant étudier les structures les plus puissantes de l’algorithmique, à
savoir les boucles (structures répétitives, structures de répétition ou encore structures
itératives): elles permettent d’exécuter à plusieurs reprises une suite d’instructions. Dans la
plupart des langages, ces répétitions se classent en deux catégories :
 Les répétitions conditionnelles (ou « indéfinies ») : la poursuite de la répétition des
instructions concernées dépend d’une certaine condition qui peut être examinée :
o soit après les instructions à répéter : on parle généralement de répétition
jusqu’à ;
o soit avant les instructions à répéter : on parle généralement de répétition tant
que.
 Les répétitions inconditionnelles (ou « avec compteur » ou « définies ») : les
instructions concernées sont répétées un nombre donné de fois.

Notons que les boucles, c'est généralement le point douloureux de l'apprenti


programmeur. C'est là que ça coince, car autant il est assez facile de comprendre comment
fonctionnent les boucles, autant il est souvent long d'acquérir les réflexes qui permettent de
les élaborer judicieusement pour traiter un problème donné.

4.2. Boucle tant_que

La boucle de type "tant_que" permet la répétition d’un bloc d’instructions tant que la
condition testée est vérifiée, donc vraie. Sa syntaxe est la suivante :

tant_que (condition_de_poursuite) faire


{
bloc d’instructions
}

Elle sera utilisée lorsqu’il n’est pas possible de connaître par avance le nombre
d’itérations à réaliser. Une boucle tant_que peut ne pas être exécutée lors du déroulement de
59

l’algorithme. Il est donc indispensable qu’il y ait dans la boucle des instructions qui modifient
la condition.

Sur AlgoBox :
TANT_QUE (< condition_de_poursuite>) FAIRE
DEBUT_TANT_QUE
// bloc d’instructions
FIN_TANT_QUE

* Bouton Guide :

Exemple 1: Ecrire un algorithme permettant d’afficher la table des carrés de 1 à 5. Résultats à


afficher : 1^2=1, 2^2=4, 3^2=9, 4^2=16, 5^2=25.

Algorithme carres
Variables
nb, nbcarre : entier
Debut
nb← 1
tant_que (nb <= 5) faire
{
nbcarre ← nb*nb
afficher nb, "^=", nbcarre
nb← nb + 1
}
Fin

Sur AlgoBox :
VARIABLES
nb EST_DU_TYPE NOMBRE
nbcarre EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
nb PREND_LA_VALEUR 1
TANT_QUE (nb<= 5) FAIRE
DEBUT_TANT_QUE
nbcarre PREND_LA_VALEUR nb*nb
AFFICHER nb
AFFICHER "^2="
AFFICHER nbcarre
nb PREND_LA_VALEUR nb+1
FIN_TANT_QUE
FIN_ALGORITHME
60

***Algorithme lancé***
1^2=1
2^2=4
3^2=9
4^2=16
5^2=25
***Algorithme terminé***

Exemple 2: Ecrire un algorithme permettant d’afficher la longueur de chaque mot saisi. Nous
comptons également compter le nombre de mots saisis. L’utilisateur entre autant de mots qu’il
souhaite.

Algorithme mots
Variables
nbmot, lgmot : entier
mot, choix : chaine
Debut
nbmot ← 0
choix ← "O"
tant_que (choix <> "N") faire
{
afficher "Veuillez saisir un mot"
lire mot
lgmot ← longueur(mot)
nbmot ← nbmot + 1
afficher "Le mot ", mot, " se compose de ", lgmot, " caractères."
afficher "Voulez-vous continuer (O/ ?)"
lire choix
}
afficher "Vous avez saisi ", nbmot, ", mots"
Fin

Exemple 3: Ecrire un algorithme permettant de calculer la factorielle d’un nombre entier


positif.

Algorithme factorielle
Variables
cpt, resultat : entier
Debut
afficher "Quelle factorielle ?"
lire cpt
resultat←cpt
61

tant_que (cpt>2) faire


{
cpt←cpt-1
resultat←cpt*resultat
}
afficher resultat
Fin

Condition d’arrêt

Il est plus naturel de se demander « quand la boucle s’arrête-t-elle? » que de


déterminer la condition de continuité « tant que quoi la boucle continue-t-elle». Pour écrire
une boucle, prenez l’habitude de:
• chercher la condition d’arrêt
• écrire sa négation à l’aide du tableau de correspondance des conditions d’arrêt
qui suit (à connaître)

Logique d’arrêt == <> >= > <= < et ou


Logique de continuité <> == < <= > >= ou et

En ce qui concerne les combinaisons des et / ou, on peut se servir des lois de De
Morgan.

Pour écrire une boucle, trois étapes sont obligatoires:


 L’initialisation des variables du compteur, et en général du bloc, avant d’entrer dans la
boucle
 La condition de poursuite. Il existe toujours différentes conditions de poursuite, qui sont
toutes justes (équivalentes)
 La modification d’au moins une valeur dans la boucle (celle que l’on a initialisée
précédemment) pour que la répétition exprime une évolution des calculs.

La boucle naturelle est la boucle tant_que. Elle sera utilisée systématiquement dans
tous les algorithmes. Mais les langages informatiques disposent de nombreuses syntaxes pour
alléger l’écriture des programmes. Ci-dessous, nous donnons deux nouveaux types de
boucles.
62

4.3. Boucle faire … tant_que

La boucle faire … tant_que (ou "répéter … jusqu’à") effectue l’évaluation de la


boucle booléenne après avoir effectué le premier tour de boucle. Dans certains cas, des
algorithmes s’écrivent avec moins de lignes en utilisant ce type de boucle. Faites attention
avec la condition de continuité. La syntaxe est la suivante :
faire
{
bloc d’instructions
} tant_que (condition_de_poursuite)

AlgoBox ne supporte pas cette boucle.

Exemple 1: Ecrire un algorithme permettant d’afficher la table des carrés de 1 à 5. Résultats à


afficher : 1^2=1, 2^2=4, 3^2=9, 4^2=16, 5^2=25.

Algorithme carres
Variables
nb, nbcarre : entier
Debut
nb← 1
faire
{
nbcarre ← nb*nb
afficher (nb, "^=", nbcarre)
nb← nb + 1
} tant_que (nb <= 5)
Fin

Exemple 2: Ecrire un algorithme permettant d’afficher la longueur de chaque mot saisi. Nous
comptons également compter le nombre de mots saisis. L’utilisateur entre autant de mots qu’il
souhaite.

Algorithme mots
Variables
nbmot, lgmot : entier
mot, choix : chaine
Debut
nbmot ← 0
choix ← "O"
faire
63

{
afficher "Veuillez saisir un mot"
lire mot
lgmot ← longueur(mot)
nbmot ← nbmot + 1
afficher "Le mot ", mot, " se compose de ", lgmot, " caractères."
afficher "Voulez-vous continuer (O/ ?)"
lire choix
} tant_que (choix <> "N")
afficher "Vous avez saisi ", nbmot, ", mots"
Fin

Exemple 3: Ecrire un algorithme permettant de calculer la factorielle d’un nombre entier


positif.

Algorithme factorielle
Variables
cpt, resultat : entier
Debut
afficher "Quelle factorielle ?"
lire cpt
resultat←cpt
faire
{
cpt←cpt-1
resultat←cpt*resultat
} tant_que (cpt>2)
afficher cpt, "!= ", resultat
Fin

4.4. Boucle pour … faire

La boucle pour … faire est utilisée très fréquemment en programmation pour réitérer
une exécution un nombre de fois connu à l’avance.

Cette écriture est pratique puisqu’elle désigne l’ensemble de la boucle en une seule
ligne: l’incrémentation (de 1) de la variable est sous-entendue à la fin de la boucle.

pour variable_de_début à fin [Pas pas] faire


{
64

bloc d’instructions
}
À chaque passage dans la boucle, la variable prendra successivement chacune des
valeurs dans l’intervalle [début, fin] (début et fin inclus). Le pas est optionnel et est de 1 par
défaut.

Sur AlgoBox :

POUR <variable > ALLANT_DE <min > A <max >


DEBUT_POUR
// bloc d’instructions
FIN_POUR

* Bouton Guide :

Exemple 1: Ecrire un algorithme permettant d’afficher la table des carrés de 1 à 5. Résultats à


afficher : 1^2=1, 2^2=4, 3^2=9, 4^2=16, 5^2=25.

Algorithme carres
Variables
nb, nbcarre : entier
Debut

pour nb de 1 à 5 faire
{
nbcarre ← nb*nb
afficher nb, "^=", nbcarre
}
Fin

Il est possible de trouver des syntaxes légèrement différentes, elles sont cependant
toutes équivalentes :
pour variable allant de début à fin [Pas pas] faire
{
bloc d’instructions
}
ou encore
pour variable ← début jusqu’à fin [Pas pas] faire
{
bloc d’instructions
65

Dans cette dernière forme, il est intéressant de constater qu’il est plus simple, dans le
cas de boucles contenant un gros bloc d’instructions, de s’y retrouver, la variable étant répétée
dans la syntaxe de fin de boucle. Enfin il est possible de trouver des syntaxes alternatives
dérivant de ces trois dernières.

Exemple 2: Ecrire un algorithme permettant de calculer la factorielle d’un nombre entier


positif.

Algorithme factorielle
Variables
i, cpt, resultat : entier
Debut
afficher "Quelle factorielle ?"
lire cpt
resultat ←1
pour i allant de 1 à cpt faire
{
resultat←i*resultat
}
afficher cpt"!= ", resultat
Fin

Sur AlgoBox
VARIABLES
i EST_DU_TYPE NOMBRE
cpt EST_DU_TYPE NOMBRE
resultat EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
AFFICHER "Quelle factorielle ?"
LIRE cpt
resultat PREND_LA_VALEUR 1
POUR i ALLANT_DE 1 A cpt
DEBUT_POUR
resultat PREND_LA_VALEUR i*resultat
FIN_POUR
AFFICHER cpt
AFFICHER "!="
AFFICHER resultat
FIN_ALGORITHME
66

***Algorithme lancé***
Quelle factorielle ?
Entrer cpt : 5
5!=120
***Algorithme terminé***

Piège à éviter
Tout comme il faut éviter les boucles infinies (sauf si c’est parfaitement volontaire), il
faut aussi éviter quelques erreurs qui peuvent se révéler très surprenantes selon le cas. Voici
un exemple de ce qu’il ne faut pas faire :
Variable
x: entier
Début
pour x ← 1 jusqu’à 31 faire
{
afficher x
x ← x*2
}
Fin

4.5. Applications
4.5.1. Recherche de la valeur maximale

Ecrire un algorithme qui permet de calculer le plus grand des 5 entiers saisis au clavier
de l’ordinateur.

Algorithme lePlusGrandDe5Entiers
Variables
cpt, valeur, max : entier
Debut
lire valeur
max ← valeur
cpt ← 1
tant_que (cpt < 5) faire
{
lire valeur
si (max < valeur) alors
{
max ← valeur
}
}
afficher "La valeur maximale est ", max
Fin
67

4.5.2. Rendre la monnaie

Ecrire un algorithme qui permet de calculer un rendu de monnaie en fonction de la


valeur des billets, en déterminant combien de billets de telle valeur il faut rendre. Il s’agit
donc de transformer une somme en coupures correspondantes. Par exemple 387 dollars
peuvent se décomposer en :
 3 billets de 100 dollars
 1 billet de 50 dollars
 1 billets de 20 dollars
 1 billet de 10 dollars
 1 billet de 5 dollars
 2 billets de 1 dollar

Algorithme renduMonnaie
Variables
montant, nb100, nb50, nb20, nb10, nb5, nb1 : entier
nb100, nb50, nb20, nb10, nb5, nb1 : entier
Debut
nb100 ← 0
nb50 ← 0
nb20 ← 0
nb10 ← 0
nb5 ← 0
nb1 ← 0
afficher "Entrez un montant"
lire montant
tant_que (montant >100) faire
{
nb100 ← nb100+1
montant ← montant - 100
}
tant_que (montant >50) faire
{
nb50 ← nb50+1
montant ← montant - 50
}
tant_que (montant >20) faire
{
nb20 ← nb20 + 1
montant ← montant - 20
}
tant_que (montant >10) faire
{
nb10 ← nb10 + 1
montant ← montant - 10
}
tant_que (montant >5) faire
68

{
nb5 ← nb5 + 1
montant ← montant - 5
}
tant_que (montant >1) faire
{
nb1 ← nb1 + 1
montant ← montant - 1
}
si (nb100 > 0) alors
{
afficher nb100, " billets de 100 dollars"
}
si (nb50 > 0) alors
{
afficher nb50, " billets de 50 dollars"
}
si (nb20 > 0) alors
{
afficher nb20 ," billets de 20 dollars"
}
si (nb10 > 0) alors
{
afficher nb10, " billets de 10 dollars"
}
si (nb5 > 0) alors
{
afficher nb5 ," billets de 5 dollars"
}
si (nb1 > 0) alors
{
afficher nb1 ," billets de 1 dollar"
}
Fin

4.6. Boucles imbriquées

Il n’y a qu’un seul bloc d’instructions à répéter lors d’une boucle. Mais le bloc peut
être lui-même composé d’une ou plusieurs boucles. On parle alors de boucles imbriquées.

Exemple : Ecrire un algorithme qui invite l’utilisateur à saisir des notes d’étudiants entre 0 et
20, de déterminer la note la plus basse, la note la plus haute et de calculer une moyenne. Tant
que l’utilisateur n’a pas saisi de note négative de 1, la saisie ne s’arrête pas. Les résultats sont
ensuite affichés.

Cet algorithme présente un intérêt certain : il faut contrôler la saisie des notes ; si
l’utilisateur saisit autre chose qu’une note allant de 1 à 20, la question lui est reposée, sachant
que -1 correspond à une fin de saisie.
69

Algorithme note
Variables
note, cpt, min, max, sum : entiers
moy : réel
Debut
min ←20
max←0
cpt←0
sum←0
afficher "Entrez une note"
lire note
tant_que (note > -1) faire
{
si (note >20) alors
{
tant_que ((note <-1) ou (note > 20)) faire
{
afficher "Erreur , essayez encore :"
lire note
}
}
si (note <> -1) alors
{
cpt ← cpt + 1
sum ← sum + note
si (note < min) alors
{
min ← note
}
sinon si (note > max) alors
{
max ← note
}
}
afficher "Entrez une note"
lire note
}
si (cpt>0) alors
{
moy ← sum/cpt
afficher "Nombre de notes :", cpt
afficher "Note la plus basse :", min
afficher "Note la plus haute : ", max
afficher "Moyenne :", moy
}
sinon
{
afficher "Aucune note n’a été saisie"
}
Fin
70

4.7. Exercices
Exercice 4.1
Écrire un programme qui demande à l’utilisateur de lui fournir un nombre entier
positif et inférieur à 10 et ceci jusqu’à ce que la réponse soit satisfaisante.

Exercice 4.2
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 4.3
Réécrire l’algorithme précédent en utilisant une autre forme de boucle.

Exercice 4.4
Ecrire un algorithme qui demande un nombre de départ, et qui ensuite affiche les vingt
nombres suivants.

Exercice 4.5
Écrire un algorithme qui demande un nombre et qui calcule la somme des entiers
consécutifs de 1 jusqu'à ce nombre.

Exercice 4.6
Lire deux nombres entiers dans les variables nd et nf et écrire les doubles des nombres
compris entre ces deux limites (incluses).

Exercice 4.7
Écrire un algorithme qui demande un nombre et qui calcule la somme des entiers
inversés consécutifs de 1 jusqu'à ce nombre.

Exercice 4.8
Ecrire un algorithme qui reçoit en entrée un nombre entier de 1 à 10 et affiche en sortie
la table de multiplication de ce nombre.
71

Exercice 4.9
A la naissance de Donel, son grand-père Yan, lui ouvre un compte bancaire. Ensuite, à
chaque anniversaire, le grand père de Donel verse sur son compte 100 dollars, auxquels il
ajoute le double de l’âge de Donel. Par exemple, lorsqu’elle a deux ans, il lui verse 104
dollars. Ecrire un algorithme qui permette de déterminer quelle somme aura Donel lors de son
nième anniversaire.

Exercice 4.10
La population de Beni est de 10 000 000 d’habitants et elle augmente de 500, 000
habitants par an. Celle du Sankuru est de 5 000 000 habitants et elle augmente de 3% par an.
Ecrire un algorithme permettant de déterminer dans combien d’années la population du
Sankuru dépassera celle de Beni.

Exercice 4.11
Ecrire un algorithme qui demande successivement n nombres à l’utilisateur, et qui lui
dise ensuite quel était le plus grand parmi ces n nombres.

Exercice 4.12
Réécrire l’algorithme précédent, mais cette fois-ci on ne connaît pas d’avance combien
l’utilisateur souhaite saisir de nombres. La saisie des nombres s’arrête lorsque l’utilisateur
entre un zéro.

Exercice 4.13
Pour une promotion donnée, écrire un algorithme qui permet d’introduire le nom de
chaque étudiant et les notes obtenues dans les cinq cours inscrits au programme, calcule la
moyenne et affiche ensuite quel était le meilleur parmi ces étudiants.

Exercice 4.14
Lire la suite des prix (en dollars entiers et terminée par zéro) des achats d’un client.
Calculer la somme qu’il doit, lire la somme qu’il paye, et simuler la remise de la monnaie en
affichant les textes "10 dollars", "5 dollars" et "1 dollar" autant de fois qu’il y a de coupures
de chaque sorte à rendre.
72

Exercice 4.15
Votre tante fortunée vous envoie désormais un montant chaque mois. A la fin de
l'année vous souhaitez faire un bilan de vos richesses. Ecrire un algorithme qui affiche la
somme mensuelle moyenne reçue, le montant minimal reçu sur l'année et le montant maximal
reçu sur l'année.

Exercice 4.16
Ecrire un algorithme qui demande à l’utilisateur de lui fournir la valeur d’un capital
qu’il souhaite placer, ainsi que le taux (annuel) auquel sera effectué le placement. Il affiche
l’évolution annuelle de ce capital jusqu’à ce qu’il ait atteint ou dépassé le double du capital
initial.

Exercice 4.17
Modifier le programme de doublement de capital, de manière qu’il affiche, outre le
capital obtenu chaque année, un numéro d’année, comme suit :
donnez le capital à placer et le taux : 10000 0.12
capital, à l’année 1 : 11200.00
capital, à l’année 2 : 12544.00
.....
capital, à l’année 6 : 19738.23
capital, à l’année 7 : 22106.82

Exercice 4.18
Un institut de sondage veut faire une enquête sur les intentions de vote à un
référendum. Il y a trois intentions possibles :

 voter oui
 voter non
 voter blanc ou s’abstenir

L’institut veut distinguer les intentions de vote des hommes et des femmes.

Exercice 4.19
Yan est un fermier qui dispose d’un couple de shadoks capables de se reproduire à
vitesse phénoménale. Un couple de shadocks met deux mois pour grandir ; à partir du
troisième mois, le couple de shadocks engendre une paire de nouveaux shadocks (qui mettront
73

deux mois pour grandir et donc trois mois pour engendrer une nouvelle paire, etc.). Et surtout,
les shadoks ne meurent jamais !
D’après cet exercice le nombre de couples de shadoks fn à chaque mois n obéit à la loi:
 f0= 1
 f1= 1
 fn= fn-1+ fn-2 pour tout n > 1

Développer un algorithme permettant de construire la suite des couples depuis le


premier jusqu’au 20ème mois.

Exercice 4.20
Ecrire un algorithme permettant d’évaluer vos chances de gagner dans l’ordre ou dans
le désordre au tiercé, quarté ou quinté. De manière formelle, le problème est le suivant :
 Données : un nombre n de chevaux partants et un nombre p ∈ {3, 4,5} de chevaux
joués
 Résultat : la probabilité x de gagner au jeu dans l’ordre, et la probabilité y de gagner
au jeu dans le désordre

x et y nous sont donnés par la formule suivante, si n est le nombre de chevaux partants
et p le nombre de chevaux joués:
x = n ! / (n - p) ! y = n ! / (p ! * (n – p) !)
74

Chapitre 5 : Tableaux
5.1. Utilité des tableaux

La notion de variable introduite au chapitre 2 permet de créer un emplacement


mémoire pour stocker, à un instant donné, une seule valeur. Ce type des variables sont
appelées des variables simples (ou scalaires).

Imaginons que dans un programme, nous ayons besoin simultanément de 15 valeurs


(par exemple, des notes des 15 étudiants pour calculer une note moyenne dans un cours).
Evidemment, la seule solution dont nous disposons à l’heure actuelle consiste à déclarer
douze variables, appelées par exemple noteA, noteB, noteC, etc. Bien sûr, on peut opter pour
une notation 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 quinze
instructions lire distinctes, cela donnera obligatoirement une atrocité du genre :

moy ← (n1+ n2+ n3+ n4+ n5+ n6+ n7+ n8+ n9+ n10+ n11+ n12+ n13+ n14+ n15)/15

Mais cette façon de procéder présente des inconvénients :


 Il faut trouver un nom de variable par valeur. Ça passe encore avec 15 valeurs, mais
cela risque de devenir plutôt fastidieux avec cent ou mille valeurs !
 Il n’existe aucun lien entre ces différentes variables. Or dans certains cas, on aura à
appliquer un même « traitement » à l’ensemble (ou à une partie) de ces valeurs.

Pour pallier à ce problème, l’algorithmique nous permet de rassembler toutes ces


variables en une seule, au sein de laquelle chaque valeur sera désignée par un numéro. Cela
donnerait donc quelque chose du genre « la note numéro 1 », « la note numéro 2 », « la note
numéro 3 », etc. Dès lors, c’est largement plus pratique.

Définition 5.1 : Un ensemble de valeurs représenté par le même nom de variable et où chaque
valeur est identifiée par un numéro, s’appelle un tableau, ou encore une variable indicée. Le
numéro qui sert à identifier un élément ou une valeur du tableau s’appelle un indice. En
représentation algorithmique, un élément du tableau est représenté par le nom de la variable
auquel on accole l’indice entre crochets.
75

En d’autres termes, on appelle tableau une variable composée de données de même


type, stockée de manière contiguë en mémoire (les unes à la suite des autres).

Notez qu’un tableau n’est pas un type de données, mais une liste d’éléments d’un type
donné. On parlera d’un tableau de n éléments de type numérique, ou alphanumérique, etc.

5.2. Déclaration des tableaux

5.2.1. Tableau à une dimension


Un tableau doit être déclaré comme tel, en précisant le nombre et le type de valeurs
qu’il contiendra.

En algorithmique, les tableaux se déclarent au même endroit que les variables, juste
avant le début du traitement lui-même, sous cette forme :

Variables
nomTableau1 : tableau[1..nbElements] de type // tableau à une dimension
ou
nomTableau1 : tableau[nbElements] de type // tableau à une dimension
Entre les crochets, placez le nombre d’éléments du tableau.

Il est possible d’initialiser le contenu du tableau à sa création comme ceci :

Variables
mois: tableau[1..12] ←{"Janvier",...,"Décembre"} de chaînes

Ce même tableau pourrait être placé dans la section Constantes, ce qui en ferait une
constante.

Les indices des tableaux peuvent démarrer à 0 ou 1, selon les usages. Dès lors, si un
tableau représente cinq valeurs alors :

 Si la numérotation commence à 1, les indices vont de valeur[1] à valeur[5]


 Si la numérotation commence à 0, les indices vont de valeur[0] à valeur[4]
76

Avec AlgoBox, un tableau est déclaré comme une variable de type LISTE.

5.2.2. Tableaux à deux dimensions

Un tableau à une dimension correspond à une liste ordonnée de valeurs qu’on peut
schématiser par une ligne ou une colonne de valeurs. Quoi qu’il en soit, il s’agit d’un schéma
qu’on pourrait effectivement qualifier comme étant « à une dimension » et qui fait songer à la
notion de vecteur en mathématiques.

Dans la vie courante, on a plutôt tendance à utiliser le mot tableau pour un ensemble
de valeurs susceptibles d’être présentées sous forme d’un schéma à deux dimensions
comportant à la fois des lignes et des colonnes. Ainsi, on peut faire un tableau donnant les
notes de chaque étudiant d’une promotion, dans chacune des différentes matières. Il pourrait
se présenter ainsi (ici, par souci de simplicité, nous nous sommes limités à 4 étudiants et à 5
matières) :
Informatique Algorithmique Architecture des Langage C Programmation
générale ordinateurs Web
Enyungu 17 11 9 14 8
Kalonji 9 13 11 10 5
Makambo 15 10 7 15 9
Nonge 11 8 19 14 10

Dans la plupart des langages, il est possible de placer ces différentes valeurs dans un
tableau à deux dimensions. Cela consiste, comme dans le cas des tableaux à une dimension, à
donner un nom, par exemple notes à l’ensemble de ces valeurs. Chaque note est alors repérée
par les valeurs de deux indices qui en précisent la position. D’une façon générale, on a la
syntaxe suivante:

nomTableau2 : tableau[1..dim1][1..dim2] de type // tableau à deux dimensions


77

5.2.3. Exemple d’utilisation

Un élément de tableau reçoit une valeur comme une variable, se lit comme une
variable et s’écrit comme une variable. Ce sont dans les boucles que les tableaux prennent
toutes leurs significations. En effet, les indices des dimensions peuvent être représentés à
l’aide de variables.

Exemple : Ecrire un algorithme qui permet de lire au clavier les notes de 5 étudiants et qui
affiche la note moyenne.

Algorithme noteMoyenne
Variables
note : tableau[1..5] d’entiers
i, som : entier
moy : réel
Début
som← 0
pour i ← 0 à 4
{
afficher"Entrez la note n° ", i
lire note[i]
som ← som + note[i]
}
moy ← som / 5
afficher ("La note moyenne = ", moy)
Fin

Sur AlgoBox
VARIABLES
note EST_DU_TYPE LISTE
som EST_DU_TYPE NOMBRE
moy EST_DU_TYPE NOMBRE
i EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
POUR i ALLANT_DE 0 A 4
DEBUT_POUR
LIRE note[i]
som PREND_LA_VALEUR som+note[i]
FIN_POUR
moy PREND_LA_VALEUR som/5
AFFICHER "La note moyenne = "
AFFICHER moy
FIN_ALGORITHME

***Algorithme lancé***
78

Entrer le terme de rang i de la liste note : 10


Entrer le terme de rang i de la liste note : 15
Entrer le terme de rang i de la liste note : 8
Entrer le terme de rang i de la liste note : 16
Entrer le terme de rang i de la liste note : 9
La note moyenne = 11.6
***Algorithme terminé***

5.2.4. Tableaux dynamiques

Il arrive fréquemment que l’on ne connaisse pas à l’avance le nombre d’éléments que
devra comporter un tableau. C’est le cas avec AlgoBox. Dans ces conditions, vous avez deux
possibilités :
 Fixer un nombre d’éléments suffisamment grand à l’avance pour être sûr d’en avoir
assez.
 Ou alors, meilleure solution, redimensionner votre tableau à la bonne taille dès que le
nombre d’éléments vous est connu.

Si vous devez utiliser des tableaux dynamiques, alors vous ne devez pas indiquer de
nombres d’éléments dans la déclaration.

Exemple : Ecrire un algorithme qui détermine la position d’une valeur dans un tableau
d’entiers. Le tableau est initialisé des valeurs lues au clavier, l’utilisateur cherche ensuite une
valeur: l’algorithme détermine la position du premier élément du tableau (même s’il y en a
plusieurs) ou il renvoi -1 si le tableau ne possède pas cette valeur.

Algorithme chercherValeurDansTableau
Variables
tab : tableau[] d’entiers
taille, indice, valeurRech : entier
positionCherchee : entier
Début
lire taille
indice ← 0
tant_que (indice < taille) faire
{
lire tab[indice]
indice ← indice + 1
}
// La recherche
lire valeurRech
79

positionCherchee ← -1
indice ← 0
tant_que ((positionCherchee = -1) et (indice < taille)) faire
{
si (tab[indice] = valeurRech) alors
{
positionCherchee ← indice
}

indice ← indice + 1 // Elément suivant


}
afficher positionCherchee
Fin

Sur AlgoBox

VARIABLES
tab EST_DU_TYPE LISTE
taille EST_DU_TYPE NOMBRE
indice EST_DU_TYPE NOMBRE
valeurRech EST_DU_TYPE NOMBRE
positionCherchee EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE taille
indice PREND_LA_VALEUR 0
TANT_QUE (indice < taille) FAIRE
DEBUT_TANT_QUE
LIRE tab[indice]
indice PREND_LA_VALEUR indice+1
FIN_TANT_QUE
LIRE valeurRech
positionCherchee PREND_LA_VALEUR -1
indice PREND_LA_VALEUR 0
TANT_QUE ((positionCherchee == -1) ET (indice < taille)) FAIRE
DEBUT_TANT_QUE
SI (tab[indice] == valeurRech) ALORS
DEBUT_SI
positionCherchee PREND_LA_VALEUR indice
FIN_SI
indice PREND_LA_VALEUR indice+1
FIN_TANT_QUE
AFFICHER positionCherchee
FIN_ALGORITHME

***Algorithme lancé***
Entrer taille : 5
Entrer le terme de rang indice de la liste tab : 15
Entrer le terme de rang indice de la liste tab : 10
Entrer le terme de rang indice de la liste tab : 4
Entrer le terme de rang indice de la liste tab : 3
Entrer le terme de rang indice de la liste tab : 12
Entrer valeurRech : 3
80

3
***Algorithme terminé***

C’est une erreur algorithmique de parcourir tout le tableau si vous avez trouvé la
valeur recherchée: il faut absolument sortir de la boucle dès que la valeur est déterminée.

5.3. Algorithmes de tri

L’utilisation d’un tableau permet de résoudre un problème assez fréquent, à savoir


ordonner, par exemple de manière croissante, une suite de valeurs.

Dans tous les cas, on commence par placer les valeurs en question dans un tableau.
Puis, on effectue ce que l’on nomme un « tri » des valeurs de ce tableau. Plusieurs techniques
existent à cet effet. Nous allons étudier les quatre plus classiques.

5.3.1. Tri par sélection

Le tri par sélection, appelé aussi tri par le min, permet de trier un tableau à une
dimension. L’algorithme parcourt le tableau pour identifier le plus petit élément, positionne ce
dernier au début du tableau, et recommence l’opération.

Chaque étape se fait en deux temps :


1. Déterminer le minimum de la partie non triée du tableau ;
2. Echanger le minimum avec la première case non triée.

Le même algorithme, le tri par le max, parcourt le tableau à la recherche de l’élément


le plus grand pour le placer à la fin.

Exemple : Trier par ordre croissant les éléments du tableau suivant :


7 16 5 10 2

Étape 1 : La plus petite valeur est 2, on permute 2 et 7.


2 16 5 10 7
Étape 2 : La plus petite valeur suivante est 5, on permute 5 et 16.
2 5 16 10 7
81

Étape 3 : La plus petite valeur suivante est 7, on permute 7 et 16.


2 5 7 10 16

Étape 4 : La plus petite valeur suivante est 10, déjà à la bonne place. Le tableau est trié.
2 5 7 10 16

Ce tri parcourt tous les éléments de l’indice 0 au dernier. Il s’agit là de la boucle


principale qui permet d’ajouter à chaque tour l’élément le plus petit restant dans la partie non
triée du tableau.

Voici l’algorithme :
Algorithme triParSelection
Variables
tab : tableau[] d’entiers
i, j: entier // Des indices
minV, taille, temp : entier
Début
lire taille
pour i ← 0 à taille-1 faire
{
lire tab[i]
}
// Tri
pour i ← 0 à taille-2 faire
{
// on considère provisoirement que tab[i]est le plus petit élément
minV ← i
// Boucle de recherche du minimum pour la partie non triée
pour j ← i+1 à taille-1 faire
{
si (tab[j] < tab[minV]) alors
{
minV ← j
}
}
si (minV != i) alors
{
// Echanger les valeurs
temp ← tab[minV]
tab[minV] ← tab[i]
tab[i] ← temp
}
}
82

// Affichage du tableau trié


pour i ← 0 à taille-1
{
afficher tab[i], " "
}
Fin

Sur AlgoBox

VARIABLES
tab EST_DU_TYPE LISTE
i EST_DU_TYPE NOMBRE
j EST_DU_TYPE NOMBRE
minV EST_DU_TYPE NOMBRE
taille EST_DU_TYPE NOMBRE
temp EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE taille
POUR i ALLANT_DE 0 A (taille-1)
DEBUT_POUR
LIRE tab[i]
FIN_POUR
POUR i ALLANT_DE 0 A (taille-2)
DEBUT_POUR
minV PREND_LA_VALEUR i
POUR j ALLANT_DE (i+1) A (taille-1)
DEBUT_POUR
SI (tab[j] < tab[minV]) ALORS
DEBUT_SI
minV PREND_LA_VALEUR j
FIN_SI
FIN_POUR
SI (minV != i) ALORS
DEBUT_SI
temp PREND_LA_VALEUR tab[minV]
tab[minV] PREND_LA_VALEUR tab[i]
tab[i] PREND_LA_VALEUR temp
FIN_SI
FIN_POUR
AFFICHER "Le tableau trié est : "
POUR i ALLANT_DE 0 A taille-1
DEBUT_POUR
AFFICHER tab[i]
AFFICHER " "
FIN_POUR
FIN_ALGORITHME

***Algorithme lancé***
Entrer taille : 5
Entrer le terme de rang i de la liste tab : 7
Entrer le terme de rang i de la liste tab : 16
83

Entrer le terme de rang i de la liste tab : 5


Entrer le terme de rang i de la liste tab : 10
Entrer le terme de rang i de la liste tab : 2
Le tableau trié est : 2 5 7 10 16
***Algorithme terminé***

5.3.2. Tri par insertion

Le tri par insertion permet de trier un tableau à une dimension. L’algorithme parcourt
le tableau pour insérer chaque élément à la bonne place dans la partie triée du tableau. On
procède en trois étapes :
 On place l’élément à trier dans une variable temporaire.
 Tant que les éléments du tableau qui précèdent l’élément à trier lui sont supérieurs, on
décale ces éléments d’une position en récupérant l’espace vide laissé par l’élément à
trier.
 On insère ensuite la variable temporaire à la nouvelle position laissée vacante par le
décalage.

Voici les différentes étapes pour le tableau :


Étape 1 : Le deuxième élément 16 est placé dans une variable temporaire qui est comparée
aux éléments qui le précèdent. Comme elle supérieure à 7, pas de décalage.
7 16 5 10 2

7 16 5 10 2

Étape 2 : 5 est comparé aux éléments qui le précèdent et chacun est décalé jusqu’à ce que
l’élément ne soit plus supérieure au troisième.
7 16 5 10 2

5 7 16 10 2

Étape 3 : 10 est comparé aux éléments qui le précèdent. Chacun est décalé jusqu’à ce que
l’élément ne soit plus supérieur au quatrième.
5 7 16 10 2
84

5 7 10 16 2

Étape 4 : 2 est comparé aux éléments qui le précèdent. Chacun est décalé jusqu’à ce que
l’élément ne soit plus supérieur au cinquième.
5 7 10 16 2

2 5 7 10 16

Voici l’algorithme :
Algorithme triParInsertion
Variables
tab : tableau[] d’entiers
i, ins: entiers // Des indices
temp, taille : entier
Début
lire taille
pour i ← 0 à taille-1
{
lire tab[i]
}
// Tri
i←1
tant_que (i < taille) faire
{
// décalage vers la gauche de tab[i] : à sa place
temp ← tab[i]
ins ← i-1
// boucle de recherche du minimum
tant_que ((ins >= 0) et (temp <= tab[ins])) faire
{
tab[ins+1] ← tab[ins]
ins ← ins-1
}
tab[ins+1] ← temp
i ← i+1
}
// Affichage du tableau trié
pour i ← 0 à taille-1
{
Afficher tab[i], " "
}
Fin
85

Sur AlgoBox

VARIABLES
tab EST_DU_TYPE LISTE
i EST_DU_TYPE NOMBRE
ins EST_DU_TYPE NOMBRE
emp EST_DU_TYPE NOMBRE
taille EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE taille
POUR i ALLANT_DE 0 A taille-1
DEBUT_POUR
LIRE tab[i]
FIN_POUR
i PREND_LA_VALEUR 1
TANT_QUE (i < taille) FAIRE
DEBUT_TANT_QUE
temp PREND_LA_VALEUR tab[i]
ins PREND_LA_VALEUR i-1
TANT_QUE ((ins >= 0) ET (temp <= tab[ins])) FAIRE
DEBUT_TANT_QUE
tab[ins+1] PREND_LA_VALEUR tab[ins]
ins PREND_LA_VALEUR ins-1
FIN_TANT_QUE
tab[ins+1] PREND_LA_VALEUR temp
i PREND_LA_VALEUR i+1
FIN_TANT_QUE
AFFICHER "Le tableau trié est : "
POUR i ALLANT_DE 0 A taille-1
DEBUT_POUR
AFFICHER tab[i]
AFFICHER " "
FIN_POUR
FIN_ALGORITHME

***Algorithme lancé***
Entrer taille : 5
Entrer le terme de rang i de la liste tab : 5
Entrer le terme de rang i de la liste tab : 10
Entrer le terme de rang i de la liste tab : 16
Entrer le terme de rang i de la liste tab : 7
Entrer le terme de rang i de la liste tab : 2
Le tableau trié est : 2 5 7 10 16
***Algorithme terminé***

Nota :
Le tri Shell est une variante du tri précédent qui a été proposé par Donald L. Shell en
1959. Dans ce type de tri, les éléments ne sont plus décalés de un à un mais par pas plus
important. La permutation s’effectue en fonction de ce pas. Une fois les permutations de ce
86

pas effectuées, le pas est réduit. Quand le pas atteint 1, le tri Shell devient un "bête" tri par
insertion. Au final, le tri Shell consiste à dégrossir un maximum le tableau à trier en plaçant
dès les premiers passages le plus d’éléments possibles dans les bonnes parties du tableau.

5.3.3. Tri à bulles

Le tri à bulles, appelé aussi tri bulles, permet de trier un tableau. L’algorithme
parcourt le tableau pour comparer les éléments deux à deux afin de faire descendre les valeurs
les plus lourdes en bas du tableau.

Les éléments les plus légers (un peu comme les bulles d’air dans l’eau) vont remonter
au début du tableau (à la surface). Voici une simulation pas à pas du premier passage :

Etape 1 : 7 est inférieur à 16, on ne permute pas:


7 16 5 10 2

Etape 2 : 16 est supérieur à 5, on permute:


7 5 16 10 2

Etape 3 : 16 est supérieur à 10, on permute:


7 5 10 16 2

Etape 4 : 16 est supérieur à 2, on permute:


7 5 10 2 16

À l’issue de ce premier passage, vous remarquez que la valeur la plus élevée est déjà
en dernière place du tableau mais que le tableau n’est pas entièrement trié. Aussi, il faut
effectuer plusieurs passages en vérifiant à chaque passage si des permutations ont eu lieu.
Quand au moins une permutation a eu lieu lors d’un passage, il faut en relancer un autre.
Ainsi, il faut mettre en place un drapeau (flag) indiquant si une permutation a eu lieu ou non.
Voici les résultats après les passages successifs :

Passe 1 :
7 5 10 2 16
87

Passe 2 :
5 7 2 10 16

Passe 3 :
5 2 7 10 16

Passe 4 :
2 5 7 10 16

La structure globale de l’algorithme est donc :


Algorithme triBulles
Variables
tab : tableau[] d’entiers
i, ins: entiers // Des indices
temp, taille : entier
permut : booléen
Début
lire taille
pour i ← 0 à taille-1
{
lire tab[i]
}
// Tri
permut ← vrai
tant_que permut faire
{
permut ← faux

pour i ← 0 à taille-2
{
si (tab[i] > tab[i+1]) alors
{
// Echanger les valeurs
temp ← tab[i]
tab[i] ← tab[i+1]
tab[i+1] ← temp
permut ← vrai
}
}

}
// Affichage du tableau trié
pour i ← 0 à taille-1
{
afficher(tab[i], " ")
}
Fin
88

5.4. Recherche par dichotomie

Avant les exercices, nous allons terminer ce chapitre par une technique célèbre de
recherche, qui révèle toute son utilité lorsque le nombre d'éléments est très élevé. Par
exemple, imaginons que nous ayons un programme qui doit vérifier si un mot existe dans le
dictionnaire. Nous pouvons supposer que le dictionnaire a été préalablement entré dans un
tableau (à raison d'un mot par emplacement). Ceci peut nous mener à 100 000 mots.

Une première approche de vérifier si un mot se trouve dans le dictionnaire consiste à


examiner successivement tous les mots du dictionnaire, du premier au dernier, et à les
comparer avec le mot à vérifier. Ça marche, mais cela risque d'être long : si le mot ne se
trouve pas dans le dictionnaire, le programme ne le saura qu'après 100 000 tours de boucle !
Et même si le mot figure dans le dictionnaire, la réponse exigera tout de même en moyenne
50 000 tours de boucle. C'est beaucoup, même pour un ordinateur.

Or, il y a une autre manière de chercher, bien plus intelligente pourrait-on dire, et qui
met à profit le fait que dans un dictionnaire, les mots sont triés par ordre alphabétique.
D'ailleurs, un être humain qui cherche un mot dans le dictionnaire ne lit jamais tous les mots,
du premier au dernier : il utilise lui aussi le fait que les mots sont triés.

5.4.1. Traitement par dichotomie

La dichotomie consiste à subdiviser des données ou un problème en deux. Le


traitement sur deux parties plus petites de moitié est en effet souvent plus simple.

La dichotomie est associée au concept de « diviser pour régner », permet de répartir le


traitement d’une grande quantité de données en deux traitements de deux quantités moins
importantes.

5.4.2. Recherche dichotomique

L’algorithme par dichotomie ne s’applique que sur les tableaux déjà triés. La méthode
de recherche retourne la position de l’élément ayant la valeur recherchée. Si l’élément n’est
pas dans le tableau, l’algorithme affiche -1. Si la valeur recherchée apparaît plusieurs fois
dans le tableau, l’algorithme affiche l’une des positions.
89

La dichotomie consiste à diviser par deux l’intervalle de recherche tant que l’élément
recherché n’est pas trouvé. Sur un tableau tab de 10 éléments triés :
Indice 0 1 2 3 4 5 6 7 8 9
Valeur 2 6 9 10 12 14 16 18 20 28

Vous voulez savoir si la valeur 20 est présente dans le tableau.

Etape 1 : Calculer l’indice situé au milieu du tableau. L’indice de début est 0, l’indice de fin
est 9, le milieu vaut (début+fin)/2. Comme cette valeur n’est pas forcément entière on
récupère la division entière : (début+fin) DIV 2. Ici 4.

Indice 0 1 2 3 4 5 6 7 8 9
Valeur 2 6 9 10 12 14 16 18 20 28

Etape 2 : Comparer la valeur tab[4] avec 20. Étant inférieure, cela veut dire que la valeur 20
est forcément au-delà de l’indice 4. On positionne Début à 5 et on recalcule (début+fin) DIV
2. Ici 7.
Indice 0 1 2 3 4 5 6 7 8 9
Valeur 2 6 9 10 12 14 16 18 20 28

Etape 3 : Comparer la valeur tab[7] avec 20. Étant inférieure, cela veut dire que la valeur 20
est au-delà de l’indice 7. On positionne Début à 8 et on recalcule. On obtient 8.
Indice 0 1 2 3 4 5 6 7 8 9
Valeur 2 6 9 10 12 14 16 18 20 28

Etape 4 : Comparer tab[8] avec 20. Les valeurs sont identiques, la recherche est terminée.

La recherche doit continuer tant que Début est inférieur ou égal à Fin et que l’élément
recherché n’a pas été trouvé.

Algorithme dichotomie
Variables
tab : tableau[] d’entiers
indice, taille, gauche, droite, milieu, valeurRech : entier
trouve : booléen
Debut
90

lire taille
gauche ← 0
droite ← taille-1
trouve ← faux
tant_que (indice < taille) faire
{
lire tab[indice]
indice ← indice + 1
}
// La recherche
lire valeurRech
tant_que ((gauche < = droite) et (non trouve)) faire
{
milieu ← (gauche + droite) DIV 2
trouve ← (tab[milieu]=valeurRech)
si (valeurRech > tab[milieu]) alors
gauche ← milieu + 1
sinon
gauche ← milieu - 1
}
si (valeurRech = tab[milieu]) alors
afficher "Trouvé"
sinon
afficher "Absent"
Fin

5.5. Exercices
Exercice 5.1
Que produit l’algorithme suivant ?

Algorithme exercice51
Variables
tab : tableau[10] d’entiers
i : entier
Debut
pour i ← 0 à 9 faire
{
tab[i]← i * i
}
pour i ← 0 à 9 faire
{
afficher tab[i]
}
Fin

Peut-on simplifier cet algorithme avec le même résultat ?

Exercice 5.2
Que produit l’algorithme suivant ?
91

Algorithme exercice52
Variables
tab : tableau[10] d’entiers
i, k : entier
Debut
tab[0]← 1
pour i ← 1 à 9 faire
{
tab[i]← tab[i-1]+2
}
pour k ← 0 à 9 faire
{
afficher tab[k]
}
Fin

Peut-on simplifier cet algorithme avec le même résultat ?

Exercice 5.3
Que produit l’algorithme suivant ?

Algorithme exercice53
Variables
tab : tableau[10] d’entiers
i: entier
Debut
tab[0]← 1
tab[1]← 1
pour i ← 2 à 9 faire
{
tab[i]← tab[i-2]+tab[i-1]
}
pour i ← 0 à 9 faire
{
afficher tab[i]
}
Fin

Peut-on simplifier cet algorithme avec le même résultat ?

Exercice 5.4
Quel résultat produira cet algorithme ?

Algorithme exercice54
Variables
tab : tableau[2][3] d’entiers

i, j, val : entier
92

Ddbut
val ← 1
pour i ← 0 à 1 faire
{
pour j ← 0 à 2 faire
{
tab[i][j] ← val
val ← val + 1
}
}
pour i ← 0 à 1 faire
{
pour j ← 0 à 2 faire
{
afficher tab[i][j]
}
}
Fin

Exercice 5.5
Ecrire un algorithme qui détermine le nombre d’occurrences de x dans un tableau de
dix entiers.

Exercice 5.6
Ecrire un algorithme qui permet de faire la somme de deux vecteurs de taille n.

Exercice 5.7
Ecrire un algorithme qui permet le produit scalaire de deux vecteurs de taille n.
Exercice 5.8
Votre tante fortunée vous envoie désormais un montant chaque mois. A la fin de
l'année vous souhaitez faire un bilan de vos richesses. Ecrire un algorithme qui affiche la
somme mensuelle moyenne reçue, le montant minimal reçu sur l'année et le montant maximal
reçu sur l'année.

Exercice 5.9
Pour sa naissance, la grand-mère de Gabriela place une somme de 1000 dollars sur son
compte épargne rémunéré au taux de 2.25% (chaque année le compte est augmenté de
2.25%). Développer un algorithme permettant d’afficher un tableau sur 20 ans associant à
chaque anniversaire de Gabriela la somme acquise sur son compte.
93

Exercice 5.10
Ecrire 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 5.11
Ecrire un algorithme calculant la somme des valeurs d’un tableau (on suppose que le tableau a
été préalablement saisi).

Exercice 5.12
Ecrire un algorithme permettant, à l’utilisateur de saisir les notes des étudiants d’une
promotion. Le programme, une fois la saisie terminée, renvoie le nombre de ces notes
supérieures à la moyenne de la promotion.

Exercice 5.13
Ecrire un algorithme qui calcule le plus grand écart dans un tableau d’entiers. Rappel :
L’écart entre deux entiers x et y est la valeur absolue de leur différence |x - y|.

Exercice 5.14
Ecrire un algorithme qui inverse l’ordre des éléments d’un tableau dont on suppose
qu'il a été préalablement saisi (« les premiers seront les derniers… »).
Exercice 5.15
Ecrire un algorithme qui permette à l’utilisateur de supprimer une valeur d’un tableau
préalablement saisi. L’utilisateur donnera l’indice de la valeur qu’il souhaite supprimer.
Attention, il ne s’agit pas de remettre une valeur à zéro, mais bel et bien de la supprimer du
tableau lui-même.

Exercice 5.16
Ecrire un algorithme qui permet de calculer la trace (somme des éléments de la
diagonale principale) d’une matrice carrée.
94

Exercice 5.17
Soit un tableau Tab à deux dimensions (10,6) préalablement rempli de valeurs
numériques. Écrire un algorithme qui recherche la plus grande valeur au sein de ce tableau.

Exercice 5.18
Ecrire un algorithme qui permet de calculer le produit d’une matrice par un vecteur.

Exercice 5.19
Ecrire un algorithme qui permet de calculer le produit de deux matrices.

Exercice 5.20
On se propose d’établir les résultats d’examen d’un ensemble d’étudiants d’une
promotion. Chaque étudiant sera représenté par un objet comportant obligatoirement les
champs suivants :
 le nom de l’étudiant,
 son admissibilité à l’examen, sous forme d’une valeur d’un type énuméré comportant
les valeurs suivantes : N (non admis), P (passable), AB (Assez bien), B (Bien), TB
(Très bien).

Idéalement, les noms des étudiants pourraient être contenus dans un fichier. Ici, par
souci de simplicité, nous les supposerons fournis par un tableau de chaînes.

On demande d’écrire un algorithme qui :


 pour chaque étudiant, lit au clavier, par exemple 3 notes d’examen, en calcule la
moyenne et renseigne convenablement le champ d’admissibilité, suivant les règles
usuelles :
o moyenne < 10 : Non admis
o 10 <= moyenne <12 : Passable
o 12 <= moyenne <14 : Assez bien
o 14 <= moyenne <16 : Bien
o 16 <= moyenne : Très bien
 affiche l’ensemble des résultats en fournissant en clair la mention obtenue.
Voici un exemple d’exécution d’un tel programme :
Donnez les trois notes de l’étudiant Donel
11.5 14.5 10
95

Donnez les trois notes de l’étudiant Amel


9.5 10.5 9
Donnez les trois notes de l’étudiant Grael
14.5 12 16.5
Donnez les trois notes de l’étudiant Coel
6 14 11
Donnez les trois notes de l’étudiant Anael
17.5 14 18.5
Résultats :
Donel - Assez bien
Amel - Non admis
Grael - Bien
Coel - Passable
Anael - Très bien
96

Chapitre 6 : Procédures et fonctions

6.1. Présentation

Nous avons déjà utilisé depuis le deuxième chapitre les fonctions lire et afficher, sous
forme d’instructions, pour saisir et afficher des valeurs. Une fonction fournit un service dans
un algorithme isolé. Lorsque votre algorithme doit effectuer plusieurs fois la même chose, il
est judicieux d’isoler cette tâche dans une fonction et de l’appeler au moment opportun : votre
algorithme n’en sera que plus facile à écrire et à modifier.

L’intérêt de la l’utilisation des fonctions est double. Il existe dans tous les langages
informatiques des bibliothèques de fonctions associées à des domaines de traitements
particuliers (traitement des fichiers, des images, des animations, …). Pour maîtriser un
langage, un programmeur doit connaître et utiliser les bibliothèques de fonctions.

La maîtrise des fonctions est une étape nécessaire à la compréhension ultérieure de la


notion d’objet et de méthode.

Dès lors, un algorithme est structuré en modules de traitement autonomes et


complémentaires ; ce sont les sous-algorithmes. Il en existe de deux sortes :
 Les procédures ;
 Les fonctions.

6.2. Structures d’une fonction


6.2.1. Définition

Une fonction est un algorithme indépendant. Elle est constituée de trois parties :

 le nom proprement dit de la fonction.

 deux parenthèses, une ouvrante, une fermante. Ces parenthèses sont toujours
obligatoires, même lorsqu'on n'écrit rien à l'intérieur.

 une liste de valeurs, indispensables à la bonne exécution de la fonction. Ces valeurs


s’appellent des arguments, ou des paramètres. Certaines fonctions exigent un seul
argument, d’autres deux, etc. et d’autres encore aucun. A noter que même dans le cas
97

de ces fonctions n’exigent aucun argument, les parenthèses restent obligatoires. Notez
également que les arguments doivent être d’un certain type, et qu’il faut respecter ces
types.

La définition d’une fonction se termine en retournant ou non une valeur. Lorsqu’elle


ne retourne rien, on parle de procédure.

Notons qu’une fonction en informatique se distingue principalement de la fonction


mathématique par le fait qu’en plus de calculer un résultat à partir de paramètres, la fonction
informatique peut avoir des « effets de bord » : par exemple afficher un message à l’écran,
jouer un son, ou bien piloter une imprimante.

Une fonction qui n’a pas d’effet de bord joue le rôle d’une expression évaluable. Celle
qui n’a que des effets de bord est appelée une procédure et joue le rôle d’une instruction

6.2.2. Syntaxe d’une fonction

La structure d’une fonction est la suivante :

fonction nomDeLaFonction(liste des paramètres) : typeRetourne


Variables
nomVariable : type] // variable locale
Debut
[Bloc d’instructions]
retourne valeur
Fin

Trois étapes sont toujours nécessaires à l’exécution d’une fonction:

1. L’algorithme appelant interrompt son exécution

2. La fonction appelée effectue son bloc d’instructions. Dès qu’une instruction retourne
est exécutée, la fonction s’arrête

3. L’algorithme appelant reprend alors son exécution

Nota : Le développeur doit penser à concevoir et écrire des fonctions pour améliorer son
algorithme. Il y gagnera sur plusieurs points:
98

 Le code des algorithmes est plus simple, plus clair et plus court. Dans un algorithme,
appeler une fonction se fait en une seule ligne et la fonction peut être appelée à
plusieurs reprises.

 Une seule modification dans la fonction sera automatiquement répercutée sur tous les
algorithmes qui utilisent cette fonction.

 L’utilisation des fonctions génériques dans des algorithmes différents permet de


réutiliser son travail et de gagner du temps.

6.2.3. Procédures

Les procédures sont des sous-algorithmes constitués d’une suite d’instructions


indépendantes. Une procédure ne retourne pas de résultat ou de valeur à l’algorithme qui l’a
appelé, tout comme les valeurs passées en paramètre ne sont pas forcément modifiées de
manière globale. Une procédure pourrait faire l’objet d’un algorithme à part. Son contenu peut
cependant parfois influer sur le déroulement global de l’algorithme, s’il modifie un fichier,
une base de données, etc.

La procédure afficheBonjour() est un exemple typique. C’est une fonction qui ne


retourne pas de valeur : ceci est signalé en précisant qu’elle retourne vide.

fonction afficheBonjour() : vide


Debut
afficher("Bonjour Anael")
retourne
Fin

Ecrivons maintenant un algorithme qui appelle la procédure afficheBonjour().

algorithme utiliseFonction
Variables
i: entier
Debut
afficher ("Voici afficher 10 fois le message "Bonjour Anael "")
pour i ← 0 à 9 faire
{
afficheBonjour()
}
afficher ("Le programme est terminé")
Fin
99

6.3. Spécificités des fonctions


6.3.1. Exemple

Prenons l’exemple d’une fonction, vu au chapitre 4 (cfr. 4.6), qui permet de lire une
note entre 0 et 20.
fonction lireNote() : entier
Variables
note : entier
Début
afficher ("Entrez une note")
lire(note)
tant_que ((note<-1) ou (note>20)) faire
{
afficher ("Erreur (0->20, -1 sortie) :")
lire(note)
}
retourne note
Fin

La fonction lireNote() retourne la valeur entière à la fin de son exécution. L’instruction


retourne indique la fin immédiate de la fonction et retour dans le programme appelant.

6.3.2. Environnements des données


a. Paramètres

Par définition, un paramètre est une variable locale à une fonction. Il possède dès le
début de la fonction la valeur passée par l’algorithme appelant.

b. Passage des paramètres

Prenons l’exemple de la fonction maxDe2Valeurs() qui retourne le maximum de deux


valeurs passées en paramètre. Cette fonction doit retourner une valeur entière : celle-ci est
calculée en tenant compte des deux valeurs passées en paramètres.

fonction maxDe2Valeurs(p1 : entier, p2 : entier) : entier


Variables
resultat : entier
Debut
si (p1 < p2) alors
{
resultat ← p2
}
100

sinon
{
resultat ← p2
}
retourne resultat
Fin

Cette fonction effectuera les opérations situées entre Debut et Fin. Soit un algorithme
qui appelle la fonction maxDe2Valeurs().
algorithme utiliseFonctionMax
Variables
v1, v2, maxV : entiers
Debut
lire( v1)
lire (v2)
maxV ← maxDe2Valeurs(v1, v2)
afficher ("La valeur maximale est ", maxV)
Fin

Nota : Il faut éviter autant que possible d’écrire l’instruction retourne au milieu d’une
fonction. La lisibilité est alors moins facile.

c. Données d’une fonction

Dans l’utilisation et l’écriture d’une fonction, la plus grande difficulté est de


comprendre l’ensemble de données auxquelles la fonction à accès.

Un environnement de données, appelé aussi espace d’adressage, correspond à


l’ensemble des variables associées exclusivement à un algorithme ou une fonction.

Une variable définie dans un algorithme (respectivement une fonction), existe le temps
limité de l’exécution de l’algorithme (respectivement de la fonction). Peu importe le nom des
variables définies dans la fonction pour pouvoir l’utiliser. Ainsi, un développeur ne donne
jamais le nom des variables internes à une fonction dont il est l’auteur.

Pour revenir à l’exemple précédent, on peut écrire la définition de la même fonction de


différentes manières :
 fonction maxDe2Valeurs(p1 : entier, p2 : entier) : entier
ou
101

 fonction maxDe2Valeurs(v1 : entier, v2 : entier) : entier


ou
 fonction maxDe2Valeurs(p1, p2) : entier

Dans les trois cas, l’utilisation de la fonction est identique :


maxV ← maxDe2Valeurs(55, 18).

Il est tout à fait possible que 2 variables, l’une déclarée dans le programme appelant et
l’autre déclarée dans la fonction, portent le même nom. Elles peuvent être du même type ou
non, peu importe, puisqu’elles sont utilisées de manière différente dans des environnements
de données différents.

d. Paramètres et variables

La plupart du temps, l’exécution d’une fonction est paramétrable grâce à des valeurs
qui lui sont passées. Les paramètres sont les variables de la fonction: il est donc faux de
vouloir les redéfinir dans la zone de déclaration des variables.

Une fonction peut accéder à deux types de données:


 Les paramètres, dont les valeurs sont connues dès le début de la fonction, les valeurs
sont passées en paramètres. Il est donc inutile de nommer les paramètres avec le
même nom que les variables utilisées lors de l’appel de la fonction.
 Les variables (appelées variables locales) définies dans le bloc de déclaration des
variables.

e. Techniques

La signature d’une fonction décrit les éléments permettant de l’appeler correctement:


 Le nom de la fonction;
 Le type (et l’ordre) des paramètres;
 Le type de la valeur retournée.

Un développeur qui souhaite utiliser une fonction n’a pas besoin de connaître le corps
de la fonction (situé entre Debut et Fin), ni même le nom ou les types des variables internes à
102

la fonction, seulement les caractéristiques nécessaires à son utilisation: sa signature. Il s’agit


de la carte d’identité de la fonction.

Deux fonctions ayant des signatures différentes sont différentes. Bien sûr, le
développeur doit connaître l’action de la fonction qu’il utilise en plus de savoir l’appeler.

Deux fonctions peuvent avoir le même nom et des paramètres différents en nombre ou
en type. Le polymorphisme paramétrique garantit automatiquement l’exécution de la bonne
fonction associée au bon nombre de paramètres et à leurs types. En effet, les algorithmes
identifient une fonction par sa signature (et pas uniquement par son nom).

Erreurs à éviter

Les erreurs à éviter dans l’utilisation d’une fonction:


 Oublier les parenthèses
 Ne pas respecter le type de retour
 Ne pas respecter le type des paramètres
 Ne pas réécrire à chaque fois une fonction qui existe déjà
 Croire que la fonction peut modifier une fonction qui existe déjà.

algorithme utiliseFonctionErreurs
Variables
v1, maxV : entiers
Debut
afficheBonjour // mettre les parenthèses : afficheBonjour()
hasard(5) // et la valeur retournée ? v1 ← hasard(5)
hasard(2.5) // le type du paramètre ?
Fin

Erreurs à éviter dans l’écriture d’une fonction:


 Donner le même nom à un paramètre et à une variable
 Placer plusieurs retourne consécutifs dans la fonction
 Vouloir retourner plusieurs valeurs
 Oublier de retourner la valeur ou retourner une valeur du mauvais type
 Vouloir continuer le traitement après l’instruction retourne
103

 Penser qu’en modifiant la valeur d’un paramètre, celui-ci sera modifié dans le
programme appelant.

fonction fonctionErreurs(p1 : entier) : entier


Variables
p1 : entier // erreur : p1 est déjà paramètre !
resultat : réel
Debut
retourne (resultat +p1) // erreur : mauvais type de retour
p1 ← 2 // la variable passée à la fonction n’aura pas été modifiée
retourne (2, resultat) // erreur : on ne peut pas retourner plusieurs valeurs
resultat ← p1 // erreur : cette opération ne sera jamais exécutée
Fin

f. Tableaux

Une fonction peut retourner un tableau seulement si la variable qui la reçoit est elle-
même un tableau de même dimension et de même nombre d’indices.

De même, il est possible de passer un tableau en paramètre d’une fonction. Dans ce


cas, vous ne connaissez pas forcément par avance le nombre d’éléments du tableau, aussi
vous pouvez ne rien préciser entre les crochets. Cependant, si le langage d’implémentation ne
propose pas d’instructions ou de fonctions prédéfinies pour trouver la taille d’un tableau, vous
devriez passer celle-ci en paramètre. Quand vous passez un tableau en paramètre d’un sous-
algorithme, mettez uniquement son nom sans utiliser les crochets.

De nombreux exemples sont possibles. Parmi eux, pourquoi ne pas trier un tableau ?
Reprenez l’un des algorithmes de tri du chapitre précédent, comme le tri par insertion et
adaptez-le pour le transformer en fonction :

fonction triTableau(tab : tableau[] d’entiers, taille : entier ): tableau[] d’entiers


Variables
i, ins: entiers
temp: entier
Début
i←1
tant_que (i < taille) faire
{
// décalage vers la gauche de tab[i] : à sa place
temp ← tab[i]
104

ins ← i-1
// boucle de recherche du minimum
tant_que ((ins >= 0) et (temp <= tab[ins])) faire
{
tab[ins+1] ← tab[ins]
ins ← ins-1
}
tab[ins+1] ← temp
i ← i+1
}
retourne tab
Fin

Voici un petit programme pour l’exploiter :

Algorithme triTableau
Constantes
indice = 5
Variables
t : tableau[1..indice] ← {7,16,5,10,2} d’entiers
i : entier
Début
t ← triTableau(t, indice)
pour i ← 0 à indice-1 faire
{
afficher(t[i])
}
Fin

6.4. Fonctions prédéfinies

Tout langage de programmation propose un certain nombre de fonctions. Certaines


sont indispensables, car elles permettent d’effectuer des traitements qui seraient sans elles
impossibles. D’autres servent à soulager le programmeur, en lui épargnant de longs – et
pénibles - algorithmes.

6.4.1. Fonctions mathématiques

a. Fonctions de base

Les langages de programmation proposent plus fonctions mathématiques. Les plus


courantes sont :
105

 racine(x) : donne la racine carrée de x


 puissance(x, y) : donne x à la puissance y
 sin(x) : sinus de x
 cos(x) : cosinus de x
 tan(x) : tangente de x

Certaines conventions algorithmiques ne reconnaissant pas les % ou MOD comme


opérateurs modulos (alors que les langages, eux, si), vous pouvez trouver parfois la fonction
mod(x, y), qui équivaut à x MOD y et la fonction entier(x, y) qui équivaut à x DIV y.

Une fonction très sympathique est la fonction aléatoire(). Elle détermine un nombre
aléatoire. Utilisée sans paramètre, elle trouve un réel entre 0 et 1. Utilisée avec un paramètre
entier, elle trouve une valeur entre 0 et n. Idéal pour un lancer de dé.

Exemple : Ecrire un algorithme qui permet de manipuler le dé.

Algorithme JeuDe
Variables
de, saisie :entiers
Debut
de ← aléatoire(5)+1 // entre 1 et 6
faire
{
afficher "Quelle est la valeur du dé ?"
lire( saisie)
si (de <> saisie ) alors
{
afficher ("Raté, essayez encore")
}
} tant_que (de = saisie)
afficher( "Bravo !")
Fin

b. Fonctions offertes par AlgoBox

En plus des 4 opérations de base (+,-,*,/), les calculs possibles sont (x étant une
variable du type NOMBRE) :
 Racine carrée d'une variable x : sqrt(x)
 Mettre une variable x à la puissance n : pow(x, n)
 Obtenir un nombre pseudo-aléatoire compris en 0 et 1 : random()
106

 Nombre 𝜋 : Math.PI
 Partie entière d'une variable x : floor(x)
 Cosinus d'une variable x (en radians): cos(x)
 Sinus d'une variable x (en radians): sin(x)
 Tangente d'une variable x (en radians): tan(x)
 Valeur absolue d'une variable x : abs(x)
 Arrondi d'une variable x à l'entier le plus proche : round(x)
 Reste de la division de la variable x par la variable y : x%y

Exemple1 : Ecrire un algorithme qui permet de calculer la racine carrée d’un nombre introduit
au clavier.

VARIABLES
x EST_DU_TYPE NOMBRE
y EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
LIRE x
y PREND_LA_VALEUR sqrt(x)
AFFICHER "La racine carrée de "
AFFICHER x
AFFICHER " est "
AFFICHER y
FIN_ALGORITHME

***Algorithme lancé***
Entrer x : 25
La racine carrée de 25 est 5
***Algorithme terminé***

Exemple2 : Ecrire un algorithme qui permet de calculer les racines carrées d’une équation du
second degré.

VARIABLES
a EST_DU_TYPE NOMBRE
b EST_DU_TYPE NOMBRE
c EST_DU_TYPE NOMBRE
x1 EST_DU_TYPE NOMBRE
x2 EST_DU_TYPE NOMBRE
delta EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
AFFICHER "Introduisez les valeurs de a, b et c:"
107

LIRE a
LIRE b
LIRE c
delta PREND_LA_VALEUR pow(b,2)-4*a*c
SI (delta>0) ALORS
DEBUT_SI
x1 PREND_LA_VALEUR (-b+sqrt(delta))/(2*a)
x2 PREND_LA_VALEUR (-b-sqrt(delta))/(2*a)
AFFICHER "Les racines sont: "
AFFICHER x1
AFFICHER " et "
AFFICHER x2
FIN_SI
SINON
DEBUT_SINON
SI (delta == 0) ALORS
DEBUT_SI
x1 PREND_LA_VALEUR -b/(2*a)
x2 PREND_LA_VALEUR x1
AFFICHER "Les racines sont:"
AFFICHER x1
AFFICHER " et "
AFFICHER x2
FIN_SI
SINON
DEBUT_SINON
AFFICHER "Pas de racines réelles"
FIN_SINON
FIN_SINON
FIN_ALGORITHME

***Algorithme lancé***
Introduisez les valeurs de a, b et c:
Entrer a : 1
Entrer b : 5
Entrer c : 6
Les racines sont: -2 et -3
***Algorithme terminé***

***Algorithme lancé***
Introduisez les valeurs de a, b et c:
Entrer a : 1
Entrer b : 4
Entrer c : 4
Les racines sont: -2 et -2
***Algorithme terminé***
108

***Algorithme lancé***
Introduisez les valeurs de a, b et c:
Entrer a : 5
Entrer b : 3
Entrer c : 1
Pas de racines réelles
***Algorithme terminé***

6.4.2. Fonctions sur chaînes

Une catégorie privilégiée de fonctions est celle qui nous permet de manipuler des
chaînes de caractères. Nous avons déjà vu au chapitre 2 (cfr. 2.4.2) qu’on pouvait facilement
coller deux chaînes l’une à l’autre avec l’opérateur de concaténation &. Mais ce que nous ne
pouvions pas faire, et qui va être maintenant possible, c’est pratiquer des extractions de
chaînes.

Tous les langages de programmation proposent les fonctions suivantes, même si le


nom et la syntaxe peuvent varier d’un langage à l’autre :

 longueur(chaîne) : renvoie le nombre de caractères d’une chaîne. Elle est parfois


nommée len().

 milieu(chaîne, n1, n2) : renvoie un extrait de la chaîne, commençant au caractère n1 et


faisant n2 caractères de long. Elle est parfois nommée sschaine (sous-chaîne).

Ce sont les deux seules fonctions de chaînes réellement indispensables. Cependant,


pour nous épargner des algorithmes fastidieux, les langages proposent également :

 gauche(chaîne, n) : renvoie les n caractères les plus à gauche dans la chaîne.

 droite(chaîne, n) : renvoie les n caractères les plus à droite dans la chaîne

 trouve(chaîne1, chaîne2) : renvoie un nombre correspondant à la position de chaîne2


dans la chaîne1. Si chaîne2 n’est pas comprise dans la chaîne1, la fonction renvoie
zéro. Elle est parfois nommée pos().

 suppr(chaîne, n1, n2) : permet de supprimer une sous-chaîne d’une chaîne de


caractères en fonction de sa position initiale et de sa longueur.

 modifierIeme(n, chaine) : remplace le caractère situé à la position donnée en


paramètre.
109

Exemple : Ecrire un algorithme qui permet de déterminer la longueur d’une chaine de


caractères saisie au clavier. Il va ensuite afficher tous les caractères d’une chaîne, les uns
après les autres, puis la première sous chaîne, puis la dernière de taille 5.

Algorithme decoupeChaine
Variables
txt, resultat: chaîne
i, t : entier
Debut
afficher ("Entrez une phrase :")
lire(txt)
t ← longueur(txt)
pour i ←0 à t-1 faire
{
resul t← milieu(txt, i, 1)
afficher(result) // les lettres une à une
}
affiche(gauche(txt, 5))
affiche(droite(txt, 5))
Fin

6.4.3. Fonctions de conversion

Vous pouvez convertir une chaîne de caractères en valeur numérique à l’aide de la


fonction chnum(), qui prend comme paramètre la chaîne de caractères et qui retourne la valeur
en entier ou réel (selon le cas). La chaîne doit être une représentation d’une valeur numérique
et rien d’autre.

La fonction numch() fait exactement le contraire : elle convertit un nombre en chaîne


de caractères, l’idéal pour sauver tout ceci dans un fichier texte. Voici un exemple simple :

Algorithme conversion
Variables
rPi : réel
cPi : chaîne
Debut
rPi ← 3.1415927
cPi ← numch(rPi)
afficher(cPi)
cPi ← "3.14"
rPi ← chnum(cPi)
afficher (rPi)
Fin
110

6.5. Récursivité

6.5.1. Définition

Une fonction est récursive si elle s’appelle elle-même. Autrement dit, si dans une
fonction ou une procédure vous faites appel à cette propre fonction ou procédure, celle-ci est
dite récursive. L’exemple le plus simple est la factorielle : n!=n*(n-1)!

La récursivité est une technique de programmation puissante: elle permet quelquefois


de trouver rapidement des solutions élégantes à des problèmes compliqués.

Lorsque des fonctions s’appellent mutuellement, on parle de la récursivité croisée ou


indirecte.

6.5.2. Structure d’une fonction récursive

Deux conditions sont nécessaires pour être en mesure d’utiliser la récursivité:

 Il faut pouvoir exprimer un algorithme sous forme d’une fonction de telle manière que
sa valeur à un certain rang ne dépende que de sa valeur aux rangs inférieurs.

 On doit aussi connaître la solution pour les rangs initiaux.

Un algorithme récursif se compose de deux parties:

 Au moins une condition d’arrêt des appels récursifs, où les valeurs à déterminer sont
immédiatement connues.

 Un appel récursif. La fonction s’appelle elle-même, dans un autre environnement.

Ainsi, pour des raisons évidentes, la syntaxe d’une fonction récursive qui retourne un
vide se présente comme :

fonction fonctionRecursive(liste des paramètres) : typeRetourne


Debut
si (condition d’arrêt) alors // condition d’arrêt et de retour
{
retourne … // à mettre au début du corps de la fonction
}
sinon // appel récursif
{
retourne fonctionRecursive(liste des nouveaux paramètres)
}
Fin
111

Exemple : Proposer la version récursive d’un algorithme permettant de calculer la factorielle


d’un nombre.

La fonction factorielle est définie par:


factorielle(n)=n!=1*2*…*(n-1)*n
On peut réécrire la fonctionnelle factorielle(n) d’une manière récurrente strictement
équitante à la précédente:
• factorielle(1)=1
• factorielle(n)=n*factorielle(n-1), pou n >1

fonction factorielle(nb : entier) : entier


Variables
f : entier
Debut
si (nb = 1) alors
{
f←1
retourne f
}
sinon // appel récursif
{
f ← nb* factorielle(nb - 1)
retourne f
}
Fin

Nota : La manière la plus concise à écrire est la suivante :

si (nb = 1) alors
{
retourne 1
} sinon
retourne nb* factorielle(nb - 1) // La fonction s’appelle elle-même

Algorithme d’utilisation :

Algorithme manipulationFactorielle
Variables
n, f : entier
Debut
lire(n)
afficher(factorielle(n))
Fin
112

6.5.3. Recherche dans un tableau

Ce problème a été abordé de manière itérative au chapitre précédent (cfr.5.2.4).


Introduisons la fonction recherche: elle devra contenir comme paramètres le tableau étudié, sa
taille et la valeur recherchée.

fonction chercher(tab : tableau[] d’entiers, taille : entier, valeur : entier ): entier

Pour chercher une valeur dans un tableau de manière récursive, il faut supposer que
cette valeur a été trouvée (ou pas) au rang inférieur, donc dans tout le tableau sauf la 1e case.

Il reste donc à tester le 1er élément: s’il est égal à la valeur cherchée, on retourne sa
place, sinon on retourne la solution au rang inférieur.

La condition d’arrêt a lieu simplement quand il ne reste pas de case à tester: la valeur
n’a alors pas été trouvée. Il faut donc introduire aussi le rang debut de l’élément à tester.

fonction chercher(tab :tableau[] d’entiers, taille : entier, valeur : entier, debut : entier): entier
Début
si (debut >= taille) alors // condition d’arrêt
{
retourne -1
}
si (tab[debut] = valeur) alors // on a trouvé
{
retourne debut
}
retourne (chercher(tab, taille, valeur, debut + 1)) //appel récursif entre debut+1 et taille
Fin

Erreurs à ne pas commettre

L’utilisation de la récursivité semblera évidente pour certains, et demandera beaucoup


plus de temps à d’autres. Il existe néanmoins certaines règles et certaines techniques qu’il faut
garder à l’esprit:

 Ne pas mettre la boucle tant_que dans une fonction récursive (c’est faux dans 99% des
cas)

 Ne pas oublier la condition d’arrêt.


113

6.6. Exercices

Exercice 6.1

Ecrire une fonction qui retourne la somme de deux entiers et un algorithme qui
l’utilise.

Exercice 6.2

Écrire une fonction qui convertit les kilomètres en miles (1 mile = 1,609 km).

Exercice 6.3

Écrire une fonction qui convertit les degrés Fahrenheit en degrés centigrades. Formule
5
: 𝑡𝑐 = 9 (𝑡𝐹 − 32)

Exercice 6.4

Écrire une fonction qui calcule le volume d’une sphère.

Exercice 6.5

Écrire une fonction ayant en paramètres le nombre d’heures effectuées par un salarié
dans la semaine et son salaire horaire, qui retourne sa paye hebdomadaire. On prendra en
compte les heures supplémentaires (au-delà de 35 heures) payées à 150%.
Exercice 6.6

Ecrire une procédure qui demande une phrase à l’utilisateur et qui affiche à l’écran le
nombre de voyelles contenues dans cette phrase.

Exercice 6.7

Ecrire une procédure qui indique le nombre d’apparition d’une voyelle dans une
phrase.

Exercice 6.8

Ecrire un algorithme qui demande une phrase à l’utilisateur et qui affiche à l’écran le
nombre de mots de cette phrase. On suppose que les mots ne sont séparés que par des espaces.
114

Exercice 6.9

Ecrire un algorithme qui demande une phrase à l’utilisateur. Celui-ci entrera ensuite le
rang d’un caractère à supprimer, et la nouvelle phrase doit être affichée.

Exercice 6.10

Un professeur note les résultats d’un test portant sur 50 questions en utilisant la table
suivante:
Bonnes réponses 0 - 10 11 - 20 21 - 30 31 - 40 41 - 50
Note E D C B A

Écrire une fonction qui retourne la note, étant donné un nombre de bonnes réponses.
Exercice 6.11

Écrire une fonction ayant en paramètre un entier représentant une année et retournant 1
(vrai) si l’année est bissextile et 0 (faux) sinon.

Exercice 6.12

Écrire une fonction ayant en paramètre deux entiers représentant un mois et une année
et retournant le nombre de jours du mois de cette année.

Exercice 6.13

Un des plus anciens systèmes de cryptographie (aisément déchiffrable) consiste à


décaler les lettres d’un message pour le rendre illisible. Ainsi, les A deviennent des B, les B
des C, etc. Ecrire une procédure qui demande une phrase à l’utilisateur et qui la code selon ce
principe.

Exercice 6.14

Une amélioration (relative) du principe précédent consiste à opérer avec un décalage


non de 1, mais d’un nombre quelconque de lettres. Ainsi, par exemple, si l’on choisit un
décalage de 12, les A deviennent des M, les B des N, etc.

Réaliser une procédure sur le même principe que le précédent, mais qui demande en
plus quel est le décalage à utiliser.
115

Exercice 6.15

Une technique ultérieure de cryptographie consista à opérer non avec un décalage


systématique, mais par une substitution aléatoire. Pour cela, on utilise un alphabet-clé, dans
lequel les lettres se succèdent de manière désordonnée, par exemple :

HYLUJPVREAKBNDOFSQZCWMGITX

C’est cette clé qui va servir ensuite à coder le message. Selon notre exemple, les A
deviendront des H, les B des Y, les C des L, etc.

Ecrire une procédure qui effectue ce cryptage (l’alphabet-clé sera saisi par l’utilisateur,
et on suppose qu'il effectue une saisie correcte).

Exercice 6.16

Écrire une procédure qui lit au clavier un verbe du premier groupe (il s’assurera qu’il
est bien terminé par er) et qui en affiche la conjugaison au présent de l’indicatif. On supposera
qu’il s’agit d’un verbe régulier. Autrement dit, on admettra que l’utilisateur ne fournit pas un
verbe tel que manger (dans ce cas, le programme affichera nous mangons !). Les résultats se
présenteront ainsi :
donnez un verbe régulier du premier groupe : dire
*** il ne se termine pas par er - donnez-en un autre : chanter
je chante
tu chantes
il/elle chante
nous chantons
vous chantez
ils/elles chantent
Exercice 6.17

Écrire une fonction qui retourne le plus grand commun diviseur (pgcd) de deux
nombres entiers positifs.
L’algorithme d’Euclide est basé sur le principe suivant :

a si b = 0
pgcd(a, b) = {
pgcd(b, a mod b) sinon

Exercice 6.18
116

Écrire une fonction qui retourne le plus petit diviseur premier d’un nombre.

Exercice 6.19

Écrire une fonction qui calcule le ne terme de la suite suivante :


1
𝑢0 =
3
4
𝑢𝑛+1 = 𝑢𝑛 − 1
3
Exercice 6.20

Écrire une fonction qui retourne le ne terme d’une suite de Fibonacci initialisée par a et
b.
𝑢0 = 𝑎
𝑢1 = 𝑏
𝑢𝑛 = 𝑢𝑛−1 + 𝑢𝑛−2 𝑝𝑜𝑢𝑟 𝑛 ≥ 2
117

Chapitre 7 : Fichiers
7.1. Introduction

Jusqu’à présent, les informations utilisées dans nos algorithmes ne pouvaient provenir
que de deux sources : soit elles étaient inclues dans l’algorithme lui-même, par le
développeur, soit elles étaient entrées en cours de route par l’utilisateur. Mais évidemment,
cela ne suffit pas à combler les besoins réels des informaticiens.

Imaginons que l’on veuille écrire un programme gérant un carnet d’adresses. D’une
exécution de l’algorithme à l’autre, l’utilisateur doit pouvoir retrouver son carnet à jour, avec
les modifications qu’il y a apportées la dernière fois qu’il a exécuté l’algorithme. Les données
du carnet d’adresse ne peuvent donc être inclues dans l’algorithme, et encore moins être
entrées au clavier à chaque nouvelle exécution.

Les fichiers sont là pour combler ce manque. Ils servent à stocker des informations de
manière permanente, entre deux exécutions d’un algorithme. Car si les variables, qui sont des
adresses de mémoire vive, disparaissent à chaque fin d’exécution, les fichiers, eux sont
stockés sur des périphériques à mémoire de masse (clé USB, disque dur, CD Rom, …).

7.2. Organisation des fichiers

Un premier grand critère, qui différencie les deux grandes catégories de fichiers, est le
suivant : le fichier est-il ou non organisé sous forme de lignes successives ? Si oui, cela
signifie vraisemblablement que ce fichier contient le même genre d'information à chaque
ligne. Ces lignes sont alors appelées des enregistrements.

Afin d’éclairer ces propos, prenons le cas classique, celui d'un carnet d'adresses. Le
fichier est destiné à mémoriser les coordonnées d'un certain nombre de personnes. Pour
chacune, il faudra noter le nom, le prénom, le numéro de téléphone et l'email. Dans ce cas, il
peut paraître plus simple de stocker une personne par ligne du fichier (par enregistrement).
Autrement, quand on prendra une ligne, on sera sûr qu'elle contient les informations
concernant une personne, et uniquement cela. Un fichier ainsi codé sous forme
d'enregistrements est appelé un fichier texte.

Le second type de fichier se définit a contrario : il rassemble les fichiers qui ne


possèdent pas de structure de lignes (d'enregistrement). Les octets, quels qu’ils soient, sont
118

écrits à la queue leu leu. Ces fichiers sont appelés des fichiers binaires. C’est le cas avec les
fichiers sons, images, programmes exécutables, etc.

Autre différence majeure entre fichiers texte et fichiers binaires : dans un fichier texte,
toutes les données sont écrites sous forme de texte. Cela veut dire que les nombres y sont
représentés sous forme de suite de chiffres (des chaînes de caractères). Ces nombres doivent
donc être convertis en chaînes lors de l'écriture dans le fichier. Inversement, lors de la lecture
du fichier, on devra convertir ces chaînes en nombre si l'on veut pouvoir les utiliser dans des
calculs. En revanche, dans les fichiers binaires, les données sont écrites à l'image exacte de
leur codage en mémoire vive, ce qui épargne toutes ces opérations de conversion.

7.3. Structure des enregistrements

Les deux grandes variantes pour structurer les données au sein d’un fichier texte sont
la délimitation et les champs de largeur fixe.

Reprenons le cas du carnet d’adresses, avec dedans le nom, le prénom, le téléphone et


l'email. Les données, sur le fichier texte, peuvent être organisées ainsi :

Structure n°1
"Djungu";"Donel";0818899608;donel.djungu@cria.cd
"Enyungu";"Sarah";0856912347;sarah@unikin.cd
"Kawe";"Yan";0999765194;yan.kawe@cria.cd
ou ainsi :

Structure n°2
Djungu Donel 0818899608 donel.djungu@cria.cd
Enyungu Sarah 0856912347 sarah@unikin.cd
Kawe Yan 0999765194 yan.kawe@cria.cd

La structure n°1 est dite délimitée. Elle utilise un caractère spécial, appelé caractère de
délimitation, qui permet de repérer quand finit un champ et quand commence le suivant. Il va
de soi que ce caractère de délimitation doit être strictement interdit à l’intérieur de chaque
champ, faute de quoi la structure devient proprement illisible.
119

La structure n°2, elle, est dite à champs de largeur fixe. Il n’y a pas de caractère de
délimitation, mais on sait que les x premiers caractères de chaque ligne stockent le nom, les y
suivants le prénom, etc. Cela impose bien entendu de ne pas saisir un renseignement plus long
que le champ prévu pour l’accueillir.

A l’époque où la place mémoire coûtait cher, la structure délimitée était souvent


privilégiée. Mais depuis bien des années, la quasi-totalité des logiciels – et des programmeurs
– optent pour la structure en champs de largeur fixe. Aussi, sauf mention contraire, nous ne
travaillerons qu’avec des fichiers bâtis sur cette structure.

7.3. Types d’accès

Il existe une autre ligne de partage des fichiers : le type d’accès, autrement dit la
manière dont la machine va pouvoir aller rechercher les informations contenues dans le
fichier.

On distingue :

 L’accès séquentiel : on ne peut accéder qu’à la donnée suivant celle qu’on vient de
lire. On ne peut donc accéder à une information qu'en ayant au préalable examiné celle
qui la précède. Dans le cas d'un fichier texte, cela signifie qu'on lit le fichier ligne par
ligne (enregistrement par enregistrement).

 L’accès direct (ou aléatoire) : on peut accéder directement à l’enregistrement de son


choix, en précisant le numéro de cet enregistrement. Mais cela veut souvent dire une
gestion fastidieuse des déplacements dans le fichier.

 L’accès indexé : pour simplifier, il combine la rapidité de l'accès direct et la simplicité


de l'accès séquentiel (en restant toutefois plus compliqué). Il est particulièrement
adapté au traitement des gros fichiers.

Notons que c’est dans l’algorithme, et seulement dans l’algorithme, que l’on choisit le
type d’accès souhaité.

7.4. Instructions d’un fichier texte en accès séquentiel

7.4.1. Ouverture et fermeture


Pour travailler avec des fichiers, vous devrez respecter un certain ordre. Il vous faudra:
120

 Ouvrir le fichier, c’est-à-dire indiquer à quel fichier vous voulez accéder et comment.
 Traiter le contenu du fichier : le lire, y écrire, bref toutes les opérations souhaitées
pour accéder et manipuler son contenu.
 Fermer le fichier, quand tous les traitements sont terminés.

L’étape la plus importante est la première. Comment ouvrir un fichier ? On stipule ce


qu’on va en faire : lire, écrire ou ajouter. Si vous aviez le droit d’ouvrir seulement un seul
fichier, ce serait assez simple, mais qu’est-ce qui vous empêcherait d’en ouvrir trois ou quatre
en même temps ?
L’important est que lorsqu’on ouvre un fichier,

 Si on ouvre un fichier pour lecture, on pourra uniquement récupérer les informations


qu’il contient, sans les modifier en aucune manière.

 Si on ouvre un fichier pour écriture, on pourra mettre dedans toutes les informations
que l’on veut. Mais les informations précédentes, si elles existent, seront
intégralement écrasées. Et on ne pourra pas accéder aux informations qui existaient
précédemment.

 Si on ouvre un fichier pour ajout, on ne peut ni lire, ni modifier les informations


existantes. Mais on pourra, ajouter de nouvelles lignes.

Notons qu’il n'y a pas d'instructions qui permettent de supprimer un enregistrement


d'un fichier. Toutefois, avec un peu d’habitude, on se rend compte que malgré tout, même si
ce n’est pas toujours marrant, on peut quand même faire tout ce qu’on veut avec ces fichiers
séquentiels.

Pour ouvrir un fichier texte, on écrira par exemple :

ouvrir "adresse.txt" dans fic pour lecture

Ici, "adresse.txt" est le nom du fichier sur le disque dur et ce fichier a donc été ouvert dans le
fichier logique fic en lecture.

Vous trouverez aussi parfois cette syntaxe sous forme de fonction, plus proche de
certains langages :
fic ← ouvrir("adresse.txt","lecture")
121

La première syntaxe est souvent préférable en algorithmique. Pour fermer un fichier,


utilisez l’instruction fermer suivie du nom logique du fichier.

fermer fic
Il existe aussi une syntaxe fonctionnelle, mais les mêmes remarques s’appliquent :
utilisez la première en cas de doute.
fermer(fic)

Un éventuel algorithme ressemblerait à ceci :

Algorithme ouvreFichier
Variables
fic : fichier séquentiel
nomF : chaîne
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour lecture
/* traitements */
fermer fic
Fin

7.4.2. Ecriture des enregistrements

L’écriture utilise l’instruction ecrireFichier, une fonction qui prend comme paramètre
le nom logique du fichier et l’enregistrement (la ligne) à écrire. Sa syntaxe est la suivante:

ecrireFichier(nom_logique, enregistrement)

Comme vous devez écrire des enregistrements à largeur fixe, c’est à vous de vérifier
que les enregistrements sont à la bonne longueur. S’ils sont trop longs, vous avez mal
dimensionné vos enregistrements à l’origine (un cas régulier est une adresse à rallonge ou un
nom de ville composé). S’ils sont trop courts, vous devrez leur ajouter des espaces en fin de
chaîne.

Quelques formalismes algorithmiques autorisent parfois de préciser à l’avance une


longueur de chaîne à la déclaration de la variable.
nom : chaîne de 20 caractères
Algorithme ecrireFichier
Variables
fic : fichier séquentiel
nom: chaîne de 20 caractères
122

prenom: chaîne de 15 caractères


tel: chaîne de 10 caractères
email: chaîne de 20 caractères
nomF, ligne : chaîne
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour écriture
/* traitements */
lire nom
lire prenom
lire tel
lire email
ligne ← nom&prenom&tel&email
ecrireFichier(fic, ligne)
fermer fic
Fin

7.4.3. Lecture des enregistrements

Les enregistrements sont ici les lignes d’un fichier texte, un enregistrement étant
équivalent à une ligne. La lecture d’une ligne se fait via l’instruction lireFichier. Lire lit
l’enregistrement présent à la position actuelle du fichier, puis se place sur l’enregistrement
suivant. À l’ouverture du fichier, lireFichier lit la première ligne. Un nouveau lireFichier lira
la deuxième et ainsi de suite jusqu’à la fin. C’est pour cela que la lecture est dite séquentielle.

La syntaxe est la suivante :


lireFichier(nom_logique, variable)

La variable en second paramètre reçoit l’enregistrement, la ligne lue. Dans l’exemple


suivant, un enregistrement du fichier des adresses de l’exemple ci-dessus est lu, partant du
principe que la largeur est fixe, puis l’enregistrement est découpé pour récupérer le nom, le
prénom, le téléphone et l'email, converti en entier.

Algorithme ouvrirFichier
Variables
fic : fichier séquentiel
nom, prenom, tel, email, nomF, ligne : chaîne
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour lecture
/* traitements */
lireFichier(fic, ligne)
123

nom ← milieu(ligne,1,20)
prenom ← milieu(ligne,21,15)
tel ← milieu(ligne,36,10)
email ← milieu(ligne,46,20)
afficher nom, prenom, tel, email
fermer fic
Fin

Que faire cependant quand on ne connaît pas à l’avance le nombre de lignes du


fichier? Comment savoir si la fin du fichier a été atteinte ?
Vous avez deux possibilités :
 Selon certains formalismes algorithmiques, lireFichier est une fonction qui retourne
un booléen, donc vrai ou faux. Si vous tentez de lire un enregistrement et qu’il n’y en
a plus, lireFichier retourne faux. Autrement dit, tant que lireFichier est vrai, on peut
continuer à lire les lignes suivantes.
 La fonction eof() parfois appelée aussi finFichier() retourne un booléen qui indique si
la fin du fichier a été atteinte ou non. Cette fonction prend en paramètre le nom
logique du fichier. Elle retourne vrai si la fin du fichier a été atteinte, donc s’il ne reste
plus d’enregistrements à lire.

L’algorithme suivant va lire tout le fichier des adresses et placer les noms, prenoms, tel
et email dans un tableau à deux dimensions. Chaque ligne du tableau sera alors occupée par une
ligne complète (un enregistrement) du fichier. Comme on ne connaît pas à l’avance le nombre
d’éléments, on se limitera arbitrairement à 100 lignes.

Algorithme lireFichier
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
adresse : tableau[1..100] [1..4] de chaînes
i, j : entiers
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour lecture

/* traitements */
i←0
tant_que (non eof(fic)) faire
{
124

lireFichier(fic, ligne)
adresse[i][0] ← milieu(ligne,1,20)
adresse[i][1] ← milieu(ligne,21,15)
adresse[i][2] ← milieu(ligne,36,10)
adresse[i][3] ← milieu(ligne,46,20)
i ← i+1
}
fermer fic
Fin

7.5. Stratégies de traitement

Il existe globalement deux manières de traiter les fichiers textes :

 l’une consiste à s’en tenir au fichier proprement dit, c'est-à-dire à modifier directement
(ou presque) les informations sur le disque dur. C’est parfois un peu acrobatique,
lorsqu’on veut supprimer un élément d’un fichier : on programme alors une boucle
avec un test, qui recopie dans un deuxième fichier tous les éléments du premier fichier
sauf un ; et il faut ensuite recopier intégralement le deuxième fichier à la place du
premier fichier.

 l’autre stratégie consiste, comme on l’a vu, à passer par un ou plusieurs tableaux. En
fait, le principe fondamental de cette approche est de commencer, avant toute autre
chose, par recopier l’intégralité du fichier de départ en mémoire vive. Ensuite, on ne
manipule que cette mémoire vive (concrètement, un ou plusieurs tableaux). Et lorsque
le traitement est terminé, on recopie à nouveau dans l'autre sens, depuis la mémoire
vive vers le fichier d’origine.

Les avantages de la seconde technique sont nombreux, et 99 fois sur 100, c'est ainsi
qu'il faudra procéder :

 la rapidité : les accès en mémoire vive sont des milliers de fois plus rapides
(nanosecondes) que les accès aux mémoires de masse (millisecondes au mieux pour
un disque dur). En basculant le fichier du départ dans un tableau, on minimise le
nombre ultérieur d'accès disque, tous les traitements étant ensuite effectués en
mémoire.
125

• la facilité de programmation : bien qu’il faille écrire les instructions de recopie du


fichier dans le tableau, pour peu qu’on doit tripoter les informations dans tous les sens,
c’est largement plus facile de faire cela avec un tableau qu’avec des fichiers.

Pourquoi, alors, demanderez-vous, ne fait-on pas cela à tous les coups ? Y a-t-il des
cas où il vaut mieux en rester aux fichiers et ne pas passer par des tableaux ?

La recopie d’un très gros fichier en mémoire vive exige des ressources qui peuvent
atteindre des dimensions considérables. Donc, dans le cas d'immenses fichiers (très rares,
cependant), cette recopie en mémoire peut s'avérer problématique.

Toutefois, lorsque le fichier contient des données de type non homogènes (chaînes,
numériques, etc.) cela risque d’être coton pour le stocker dans un tableau unique : il va falloir
déclarer plusieurs tableaux, dont le maniement au final peut être aussi lourd que celui des
fichiers de départ.

A moins d'utiliser une ruse : créer des types de variables personnalisées, composées
d’un «collage » de plusieurs types existants (10 caractères, puis un numérique, puis 15
caractères, etc.). Ce type de variable s'appelle un type structuré.

7.6. Exercices
Exercice 7.1
Quel résultat cet algorithme produit-il ?

Algorithme exercice71
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
Debut
nomF ← "exemple.txt"
ouvrir nomF dans fic pour lecture
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
afficher(ligne)
}
fermer fic
Fin
126

Exercice 7.2
Ecrire un algorithme qui produit un résultat similaire au précédent, mais le fichier
texte "exemple.txt" est cette fois de type délimité (caractère de délimitation : /). On produira à
l'écran un affichage où pour des raisons esthétiques, ce caractère sera remplacé avec des
espaces.

Exercice 7.3
On travaille avec le fichier du carnet d’adresses en champs de largeur fixe. Ecrire un
algorithme qui permet à l’utilisateur de saisir au clavier un nouvel individu qui sera ajouté à
ce carnet d’adresses.

Exercice 7.4
Ecrire un algorithme permettant de créer séquentiellement un fichier « répertoire »
comportant pour chaque personne :
 nom (20 caractères maximum) ;
 prénom (20 caractères maximum) ;
 âge (entier) ;
 numéro de téléphone (10 caractères maximum)

Les informations relatives aux différentes personnes seront lues au clavier.

Exercice 7.5
Ecrire un algorithme permettant, à partir du fichier créé par l’exercice 7.4, de retrouver
les informations correspondant à une personne de nom donné.

Exercice 7.6
On dispose d’un fichier disque dont le contenu doit être affiché. Chaque
enregistrement du fichier contient les informations suivantes :
matricule nom de l’employé nombre d’heures prestées
Ecrire un algorithme permettant d’afficher tout le contenu du fichier.
127

Exercice 7.7
Ecrire un algorithme permettant, à partir du fichier créé par l’exercice 7.6, d’afficher le
nombre total d’heures prestées à la fin de l’état.

Exercice 7.8
On dispose d’un fichier disque dont chaque enregistrement contient les informations
suivantes :
no client code article quantité prix unitaire

Ecrire un algorithme permettant de calculer le prix d’achat de chaque client et


d’afficher pour chaque client :
no client code article quantité prix d’achat

Il faut également afficher le nombre total des clients ainsi que le montant total dû par
l’ensemble des clients à la fin de l’état.

Exercice 7.9
Le contenu d’un fichier disque doit être affiché. Chaque enregistrement contient les
informations suivantes :
matricule nom code sexe montant

Le code sexe sera M ou F selon qu’il s’agit d’un homme ou d’une femme.
a) Afficher les noms et montants uniquement pour les femmes.
b) Afficher uniquement les noms des employés qui ont un montant supérieur ou égal à 1000
dollars.
c) Afficher uniquement les matricules des hommes qui ont un montant inférieur à
1500 dollars
d) Afficher uniquement les matricules des hommes qui ont un montant supérieur à 1000
dollars et les matricules des femmes qui ont un montant inférieur à 2500 dollars.

Exercice 7.10
Le contenu d’un fichier agents. Chaque enregistrement contient les informations
suivantes :
matricule nom code sexe nombre d’heures
128

Le code sexe sera M ou F selon qu’il s’agit d’un homme ou d’une femme. Pour
chaque cas suivant, afficher :
matricule nom salaire brut
a) Calculer le salaire brut des femmes, sachant que le salaire horaire est de 50 dollars
b) Calculer le salaire brut des hommes qui ont travaillé plus de 20 heures, le taux horaire
de 60 dollars et d’afficher pour chacune d’eux :
c) Calculer le salaire brut de tous les employés, sachant que le salaire horaire est de 50
dollars pour les femmes et 60 dollars pour les hommes. Pour chaque employé, il faut
afficher :
d) Calculer le salaire brut et le salaire net de tous les employés, sachant que :
a. le salaire horaire est de 60 dollars pour les hommes qui ont travaillé au moins
20 heures ;
b. le salaire horaire est de 50 dollars pour les femmes qui ont travaillé plus de 10
heures ;
c. le salaire horaire est de 40 dollars pour les autres agents ;
d. le taux d’impôt est de 20% pour les hommes et de 10% pour les femmes sur le
salaire brut.
Pour chaque employé, il faut afficher :
matricule nom nombre heures sal. hor. Sal. brut impôt sal. net

Exercice 7.11
On dispose d’un fichier disque. Chaque enregistrement contient :
 code article
 libellé de l’article
 stock au début de la journée
 achats de la journée
 ventes de la journée
 stock de sécurité

Calculer pour chaque enregistrement le stock en fin de journée et d’afficher :


code article stock fin de journée astérisque

Attention : Si le stock en fin de journée est inférieur au stock de sécurité, il faut en outre
afficher un astérisque à côté de stock fin de journée.
129

Exercice 7.12
On dispose d’un fichier disque des étudiants d’une promotion dont les enregistrements
contiennent :
matricule nom taille en cm poids en kg

Afficher le contenu du fichier ainsi que, à la fin de d’état, la taille et le poids moyens
des étudiants de la promotion.

Exercice 7.13
Un fichier disque de paie de juillet contient les enregistrements dont le format est le
suivant :
matricule nom type-heures nombre heures

Le type-heures est nor, sup, nut selon qu’il s’agit des heures normales,
supplémentaires ou de nuit prestées. Par ailleurs, il est clair qu’un agent peut avoir presté
plusieurs types d’heures durant le mois concerné.

On demande, par type d’heures prestées, de compter le nombre d’enregistrements, de


calculer le nombre d’heures prestées et de calculer le montant à payer, sachant que le taux
horaire est de 15 dollars, 5 dollars et 20 dollars respectivement pour les heures normales,
supplémentaires et de nuit.

Afficher ensuite le résultat du traitement selon le format suivant :


Type-hres nbre enregistrements nbre tot hres taux montant

A la fin de l’état, il faut aussi afficher le montant total dû pour l’ensemble des types
d’heures prestées.

Exercice 7.14
On dispose d’un fichier disque Agents sur disque dont les enregistrements sont
structurés comme suit :
matricule nom grade salaire base prime
Le taux de l’IPR dû à l’Etat par un agent est fonction de son salaire de base, soit :
 10 % si salaire de base inférieur à 1000 dollars
130

 15 % si salaire de base supérieur à 1000 dollars et inférieur à 2500 dollars


 30 % si salaire de base supérieur à 2500 dollars et inférieur à 5000 dollars
 50 % si salaire de base supérieur ou égal à 5000 dollars

Calculer et afficher pour chaque agent :


matricule grade salaire base prime salaire brut impôt salaire net

Donner également, à la fin de l’état, le nombre total d’agents, les montants totaux de
salaire de base, primes, salaire brut, impôts et salaire net.

Exercice 7.15
On travaille avec le fichier du carnet d’adresses en champs de largeur fixe. Ecrire un
algorithme qui permet à l’utilisateur de saisir au clavier un nouvel individu qui sera ajouté à
ce carnet d’adresses. Cependant, le carnet est supposé être trié par ordre alphabétique.
L’individu doit donc être inséré au bon endroit dans le fichier.

Exercice 7.16
Ecrire un algorithme qui permet de modifier un renseignement (pour simplifier, disons
uniquement le nom de famille) d’un membre du carnet d’adresses. Il faut donc demander à
l’utilisateur quel est le nom à modifier, puis quel est le nouveau nom, et mettre à jour le
fichier. Si le nom recherché n'existe pas, l’algorithme devra le signaler.

Exercice 7.17
Ecrire un algorithme qui trie les individus du carnet d’adresses par ordre alphabétique.

Exercice 7.18
Soient adresse1.txt et adresse2.txt deux fichiers dont les enregistrements ont la même
structure. Ecrire un algorithme qui recopie tout le fichier adresse1 dans le fichier adresse3,
puis à sa suite, tout le fichier adresse2 (concaténation de fichiers).

Exercice 7.19
Ecrire un algorithme qui supprime dans notre carnet d'adresses tous les individus dont
le mail est invalide (pour employer un critère simple, on considèrera que sont invalides les
mails ne comportant aucune arobase, ou plus d'une arobase).
131

Exercice 7.20
Les enregistrements d’un fichier contiennent les deux champs nom (chaîne de
caractères) et montant (entier). Chaque enregistrement correspond à une vente conclue par un
commercial d’une société.

Le fichier de départ est déjà trié alphabétiquement par vendeur. Un vendeur peut avoir
plusieurs enregistrements pour avoir réalisé plusieurs ventes. Calculer et afficher, pour chaque
vendeur, le total de ventes.
132

Chapitre 8 : Classes et objets


8.1. Introduction

Comme nous l’avons indiqué au premier chapitre de cet ouvrage, il y a une nette
distinction entre :
 Les langages procéduraux, disposant de la notion de fonction, outil qui permet de
structurer un programme en le décomposant en des parties relativement indépendantes.
 Les langages orientés objet, disposant en plus des notions de classe et d’objet. Dès
lors, comme nous le verrons, les classes permettent également de structurer un
programme en le décomposant en des parties autonomes.

Regardez autour de vous de quoi sont constituées les choses. Par chose, comprenez
tous les objets réels ou abstraits qui vous entourent. Un objet réel est par exemple un livre, un
stylo, un couteau, une voiture, votre écran d’ordinateur, un téléphone, etc. Par abstrait
comprenez une commande, une entreprise, un service, une organisation quelconque, etc.

Du point de vue informatique, le concept d’objet consiste à regrouper dans une même
entité des données qu’on nomme des attributs et des fonctions qu’on nomme méthodes.
Seules les méthodes sont habilitées à manipuler ces données, qu’il s’agisse de les modifier ou
plus simplement d’en utiliser la valeur. On traduit souvent cette propriété en disant que les
données sont encapsulées dans l’objet, autrement dit qu’elles ne sont plus visibles « de
l’extérieur » de l’objet. La seule façon d’exploiter les possibilités offertes par l’objet sera de
faire appel à ses méthodes.

La notion de classe généralise aux objets la notion de type : une classe n’est rien
d’autre qu’une description (unique) pouvant donner naissance à différents objets disposant de
la même structure de données (mêmes noms et types d’attributs) et des mêmes méthodes.
Différents objets d’une même classe se distinguent par les valeurs de leurs attributs; en
revanche, ils partagent les mêmes méthodes.

Généralement, en programmation orientée objet, soit on définit une classe que l’on
pourra utiliser ensuite pour créer un ou plusieurs objets de cette classe, soit on utilise des
classes existantes (fournies avec le langage ou créées par vous-même ou par d’autres
133

développeurs). On retrouve là encore quelque chose de comparable à ce qui se passait avec les
fonctions (cfr chapitre 6).

8.2. Classes
8.2.1. Définition

Une classe est une structure de données particulière ainsi que les opérations permettant
de la manipuler.

Figure 8.1 : Une classe est une boite noire [6]

Les classes doivent être perçues comme des types évolués, qui peuvent représenter un
nombre incroyablement divers de choses: des personnes, des étudiants, des avions, des
ordinateurs, des livres, des bibliothèques, des romans, des joueurs, etc., et même des
évènements ou des échanges.

Utiliser (ou définir) une nouvelle classe, c’est en quelque sorte utiliser (ou définir) un
nouveau type avec des traitements associés. Mais définir un type et les opérations associées
n’est pas suffisant : encore faut-il savoir l’utiliser. Pour les entiers, il suffit de définir une
variable de type entier et de la manipuler. Pour les classes, il faut construire un objet.

8.2.2. Constituants d’une classe

Une classe est constituée des attributs (ou propriétés, ou encore des champs) et des
méthodes (ou opérations, ou encore fonctions membres).

Un attribut est une variable interne à la classe et une méthode n’est rien d’autre qu’une
fonction associée à une classe.
134

Nous conviendrons que la définition d’une classe se fait suivant ce canevas :

classe NomDeLaClasse {
// Déclaration des attributs
// Définition des méthodes
}

Nota : Le nom d’une classe commence par une lettre majuscule.

La structure d’une méthode se présente comme suit :

identificateurDeLaMethode (liste des paramètres) : typeRetourne


{
bloc d’instructions
}

Il est possible d’écrire des instructions à l’extérieur de la déclaration de la classe, en


précisant évidemment le nom de la classe :

classe nomDeLaClasse comporte identificateurDeLaMethode (liste des paramètres) : typeRetourne


{
bloc d’instructions
}

La visibilité (ou encore portée) d’un attribut ou d’une méthode peut être privée (-),
protégée (#) ou publique (+).
 Un attribut ou une méthode sont dits privés (privé) si leur utilisation est interdite en
dehors de la classe.
 Un attribut ou une méthode sont dits publics (public) si leur utilisation est autorisée en
dehors de la classe.
 Un attribut ou une méthode sont dits protégés (protégé) si leur utilisation est autorisée
aux descendants de la classe.

Exemple :
privé jour, mois, annee : entier

8.2.3. Exemple d’une classe


Ecrivons un algorithme qui permet de créer la classe Etudiant.
135

Classe Etudiant {
// Attributs
nom : Chaine
dateNaissance : Date
// Méthodes
ajouterNote(nouvelleNote : réel) : vide
}

Dans l’exemple ci-haut, Chaine et Date, comme d’autres, sont des classes standards.
Pour ce qui est de la classe Chaine, à part les fonctions sur chaine vues au chapitre 6 (cfr.
6.4.1), il y a les méthodes suivantes :
 Chaine() permet de créer une chaine en mémoire
 ecrire() permet d’écrire la chaine sur l’écran
 lire() permet à l’utilisateur de saisir le contenu de la chaine
 iemeCar(entier) fournit le caractère qui est à la position passée en paramètre (le
premier caractère est à la position à 0)
 modifierIeme(entier, caractère) remplace le caractère situé à la position donnée en
paramètre
 concatener(Chaine) modifie la chaine en lui juxtaposant la chaine passée en
paramètre.
 egal(Chaine) compare une chaine de caractères avec la chaine passée en
paramètre.

Pour ce qui est de la classe Date, comme pour la classe Chaine, il y a les méthodes
prédéfinies suivantes :
 Date() permet de créer une date en mémoire initialisée au 01/01/1970
 dateEnChaine() retourne la date sous forme de chaine de caractères
 estBissextile() indique si l’année est bissextile (Vrai ou Faux)
 precede(d: Date) indique si la date est antérieure ou non à celle passée entre
paramètre

8.2.4. Attribut statique

Un attribut static est un attribut qui n’est créé qu’en un seul exemplaire et qui est
commun à tous les objets de la classe.
136

Vous le déclarez comme n’importe quel attribut, sauf que vous lui rajoutez le mot-clé
static après son type. L’attribut static peut être privé ou public. Il peut être important
d’initialiser une valeur par défaut pour un attribut static.

8.3. Objets
8.3.1. Définition

La classe est la définition d’une structure (en poterie, il s’agirait du moule). Les
instances sont les objets créés, concrets en mémoire, qui respectent la définition de la classe
associée.
Une instance possède trois caractéristiques:
 Une identité (au moins une variable l’identifie)
 Un état (défini par un ensemble des données qu’elle contient)
 Un comportement (correspondant à l’ensemble de ses méthodes)

8.3.2. Constructeurs

La création effective de l’instance se fait à l’aide de l’opérateur spécifique new


(nouveau). Ce dernier permet de créer effectivement l’objet.

Un constructeur est une méthode spéciale d’une classe. Il est appelé pour construire
une instance de classe.

Exemples :
Classe Date comporte méthode Date() {
jour ← 1
mois ← 1
annee ← 1970
}

Classe Date comporte méthode Date(paramJour: entier, paramMois: entier, paramAnne : entier)
{
jour ← paramJour
mois ← paramMois
annee ← paramAnne
}
137

L’objectif d’un constructeur est d’initialiser les caractéristiques de l’objet crée par
l’opérateur new.

La classe a déjà été déclarée et l’identificateur de l’instance est connu pour


l’algorithme. Il est alors nécessaire de créer effectivement cet objet, de lui allouer de la place
mémoire.
variableInstance ← new NomDeLaClasse(paramètres)
Exemple :
Algorithme constructionInstances
Variables
d: Date
c : Chaine
e : Etudiant
Debut
d ← new Date(18, 3, 2008) // La variable d est initialisée
c ← new Chaine("Kenaya") // La variable c est initialisée
e ← new Etudiant(c, d) // La variable e est initialisée

Fin

Propriétés du constructeur
 Un constructeur porte le même nom que la classe qu’il doit construire
 Une classe peut posséder plusieurs constructeurs (portant le même nom, celui de la
classe) mais ayant des paramètres différents.

Un constructeur ne retourne pas de valeur, même vide: il n’y a pas de retour. Le


constructeur par défaut est le constructeur qui ne prend aucun paramètre. Les valeurs des
attributs sont des valeurs déterminées par le concepteur de la classe.

8.3.3. Variables et instances

Il est possible que plusieurs variables référencent une même instance.

Algorithme deuxVariablesPourUneDate
Variables
d1, d2: Date
Debut
d1 ← new Date(18, 3, 2008) // La variable d1 est initialisée
d2 ← d1 // d2 et d1 représentent le même objet
Fin
138

8.3.4. Appel d’une méthode

Les instances doivent être imaginées comme des entités indépendantes. Pour activer
une instance, il faut lui envoyer un message: celui-ci déclenche alors l’activité de l’instance
(le déroulement de la méthode associée).

Par définition, un message est le signal envoyé à une instance particulière, avec ou
sans paramètres.

Une méthode, appliquée à une instance particulière, est l’exécution d’un algorithme
déclenché par un message.

L’appel d’une méthode sur un objet receveur est le suivant:


 Si la méthode retourne le vide:
instanceDeClasse.methode()
 Si la méthode retourne une valeur:
resultat ← instanceDeClasse.methode()

Nota : Et pour l’attribut, on écrit :


res ← instanceDeClasse.attribut

Déclaration globale d’une classe :


Classe NomDeLaClasse {
// Attributs :
Déclaration des attributs

// Constructeurs :
Signature des constructeurs

// Méthodes :
Signature des méthodes
}

8.3.5. Opérateur this

L’instance courante est l’instance sur laquelle s’applique la méthode en cours


d’exécution. L’instance courante est nommée this dans le bloc d’instructions de la méthode.
139

Les attributs et les méthodes de l’instance courante sont précédés par this. Il est
facultatif (mais plus clair, et donc recommandé) de faire précéder les attributs et les méthodes
par this.

Classe Date comporte méthode Date(paramJour: entier, paramMois: entier, paramAnne : entier)
{
this.jour ← paramJour
this.mois ← paramMois
this.annee ← paramAnnee
}

Nota : Il existe un cas où l’opérateur this est obligatoire : c’est quand il y a ambiguïté entre le
nom d’un paramètre et d’un attribut (s’ils portent le même nom). Il est nécessaire de précéder
l’attribut par l’opérateur this.

Classe Date comporte méthode Date(jour: entier, mois: entier, annee : entier)
{
this.jour ← jour // jour ← jour : l’attribut n’est pas modifié
this.mois ← mois
this.annee ← annee
}

8.3.6. Accesseurs

Il est recommandé au développeur d’une classe de cacher le nom et la nature des


attributs de celle-ci. Néanmoins, il est fréquent de fournir aux utilisateurs des méthodes
simples pour accéder à ces attributs (en lecture ou en modification). Pour chacun de ses
attributs, une classe peut posséder une ou deux méthodes appelées accesseurs : une en lecture
(get) et l’autre en écriture (set).

Les accesseurs sont les méthodes les plus simples permettant d’accéder aux attributs
de l’extérieur de la classe. Les accesseurs, s’ils sont disponibles pour une classe, constituent
un moyen de récupérer la valeur d’un attribut ou de la changer.

a. Accesseur en lecture

Un accesseur en lecture est une méthode permettant de connaitre la valeur d’un


attribut. La valeur retournée est du type de l’attribut.
140

Par exemple, la classe Date possède 3 attributs : jour, mois et annee de type entier. Les
accesseurs en lecture associés sont :
 classe Date comporte méthode getJour() : entier
 classe Date comporte méthode getMois() : entier
 classe Date comporte méthode getAnnee() : entier

Ecrivons un algorithme utilisant ces 3 méthodes :


Algorithme utilisationAccesseursLecture
Variables
d : Date
leJour, leMois, lAnnee : entier
Début
d ← new Date(29, 6, 2010)
leJour ← d.getJour()
leMois ← d.getMois()
lAnnee ← d.getAnnee()
Fin

Ecrivons maintenant les 3 accesseurs en lecture. Pour cela, il faut simplement se


rappeler qu’à l’exécution d’une méthode, seuls les attributs de l’objet manipulé (this), les
paramètres et les variables locales de la méthode sont connus.

Classe Date comporte méthode getJour() : entier


{
retourne jour // Retourne la valeur de l’attribut jour
}

Classe Date comporte méthode getMois() : entier


{
retourne mois // Retourne la valeur de l’attribut mois
}

Classe Date comporte méthode getAnnee() : entier


{
retourne annee // Retourne la valeur de l’attribut annee
}

b. Accesseur en écriture
Un accesseur en écriture est une méthode permettant de modifier la valeur d’un
attribut en lui passant la nouvelle valeur en paramètre. Ce dernier est du type de l’attribut à
modifier.
141

Par exemple, la classe Date possède 3 attributs : jour, mois et annee de type entier. Les
accesseurs en écriture associés sont :
 classe Date comporte méthode setJour(j : entier) : entier
 classe Date comporte méthode setMois(m : entier) : entier
 classe Date comporte méthode setAnnee(a : entier) : entier

Voici un exemple d’utilisation des accesseurs en écriture.

Algorithme utilisationAccesseursEcriture
Variables
d : Date
Début
d ← new Date()
d. setJour(29)
d.setMois(6)
d.setAnnee(2010)
Fin

Classe Date comporte méthode setJour(j : entier) : entier


{
jour ← j
}

Classe Date comporte méthode setMois(m : entier) : entier


{
mois ← m
}

Classe Date comporte méthode setAnnee(a : entier) : entier


{
annee ← a
}

D’après la définition de this, il est possible d’écrire différemment les accesseurs en


spécifiant les attributs avec this. L’exemple concerne l’attribut jour, il est identique avec mois
et annee.

Classe Date comporte méthode getJour() : entier


{
retourne this.jour // Retourne la valeur de l’attribut jour
}
142

Classe Date comporte méthode setJour(j : entier) : entier


{
this.jour ← j
}

Trois caractéristiques des accesseurs :


 Le nom des accesseurs se déduit automatiquement du nom de l’attribut associé. Pour
ce faire, il suffit de faire précéder le nom de l’attribut par get pour la lecture et par set
pour l’écriture.
 La méthode get retourne la valeur de l’attribut sans la modifier, la méthode set la
modifie (et retourne vide)
 Les accesseurs sont utilisables par l’utilisateur de la classe.

8.3.7. Ecriture d’une classe

Nous complétons la définition de la classe Etudiant, ci-dessous, en donnant des détails


sur les différentes méthodes.

Classe Etudiant {
// Attributs
nom : Chaine
dateNaissance : Date
// Méthodes
Etudiant()
Etudiant(nom : Chaine, dateNaissance : Date)
getNom() : Chaine
getDateNaissance () : Date
ajouterNote(nouvelleNote : réel) : vide
afficherEt() : vide
}

a. Constructeurs

Le premier constructeur, générique, sera appelé avec un new Etudiant(), et initialise les
4 attributs :
Classe Etudiant comporte méthode Etudiant()
{
143

nom ← new Chaine()


dateNaissance ← new Date()
}

Le second constructeur permet de préciser les valeurs des attributs et l’initialisation se


fait avec this :
Classe Etudiant comporte méthode Etudiant(ch : Chaine, d : Date)
{
this.nom ← new Chaine(ch)
this.dateNaissance ← new Date(d)
}

b. Accesseurs
Ils permettent de retourner le nom ou la date de naissance de l’étudiant :
Classe Etudiant comporte méthode getNom() : Chaine
{
retourne nom
}

Classe Etudiant comporte méthode getDate() : Date


{
retourne dateNaissance
}

c. Autres méthodes

Classe Etudiant comporte méthode ajouterNote(nouvelleNote : réel) : vide


{
afficher(nouvelleNote)
}

La méthode suivante permet d’afficher les caractéristiques d’un étudiant :


Classe Etudiant comporte méthode afficherEt() : vide
{
nom.ecrire()
dateNaissance.ecrire()
}
144

8.3.8. Tableaux

En orienté objet, un tableau est défini en deux temps:


 Déclaration de variable:
x: tableau[] d’entiers
 Corps du programme:
x ← new entier[5]
Pour le reste, se référer au chapitre 5 de cet ouvrage.

8.4. Exemple d’application

L’objectif de cet exemple reste avant tout la conception et l’écriture d’un algorithme
grâce à l’utilisation des classes Etudiant, Date et Chaine.

8.4.1. Saisir les notes

Définissons l’algorithme de saisie des notes. Commençons simplement par écrire une
fonction qui permet de saisir une note pour un seul étudiant etud passé en paramètre.

fonction saisirUneNote(etud : Etudiant) : vide


Variables
nouvelleNote: réel
Debut
etud.getNom().afficher()
ecrire("Quelle est la nouvelle note ?")
lire(nouvelleNote)
etud.ajouterNote(nouvelleNote) // Utilisation de la méthode de la classe Etudiant
Fin

Il suffit de parcourir le tableau des étudiants et de saisir la note de chacun (grâce à la


fonction précédente).

fonction saisirNotes(liste : tableau d’Etudiant[], nbEtudiant : entier) : vide


Variables
i: entier
Debut
i ←0
tant_que (i < nbEtudiant) faire
{
saisirUneNote(liste[i] ) // Appel de la fonction
i ←i+1
}
145

Fin

8.4.2. Visualiser les noms

Pour afficher les noms, il suffit de parcourir le tableau et d’utiliser la méthode


getNom() de la classe Etudiant pour obtenir une chaîne, sur laquelle la méthode ecrire() de la
classe Chaine.

fonction afficher(liste : tableau d’Etudiant[], nbEtudiant : entier) : vide


Variables
i: entier
Debut
i ←0
tant_que (i < nbEtudiant) faire
{
liste[i].getNom().ecrire()
i ←i+1
}
Fin

8.4.3. Menu

En mode texte, nous rassemblons les différentes fonctions précédentes en une seule
qui fait appel aux autres.

fonction menu(liste : tableau d’Etudiant[], nbEtudiant : entier) : vide


Variables
choixMenu: entier
Debut
afficherMenu()
lire(choixMenu)
tant_que (choixMenu <> 3) faire
{
si (choixMenu = 1) alors
{
afficher(liste, nbEtudiant )
}
sinon si (choixMenu = 2) alors
{
saisirNotes(liste, nbEtudiant )
}
sinon
{
ecrire("Erreur de saisie !")
}
afficherMenu()
lire(choixMenu)
}
146

Fin

Plutôt que d’écrire deux fois le menu dans l’algorithme précédent, il est préférable de
le mettre dans une fonction à part.

fonction afficherMenu () : vide


Debut
afficher("**********************************")
afficher("1. Afficher les étudiants")
afficher("2. Saisir une note pour chaque étudiant")
afficher("3. Quitter")
afficher("**********************************")
afficher("Votre choix : ")
Fin

Et enfin la classe qui permet de gérer les notes des étudiants :


Classe GestionDesNotesDesEtudiants{
public principal() : vide
{
listeEtudiant: tableau[] d’Etudiants
listeEtudiant ← new Etudiant[5]
listeEtudiant[0] ← new Etudiant("Donel", new Date(18,3,2008))
listeEtudiant[1] ← new Etudiant("Amel", new Date(29,6,2010))
listeEtudiant[2] ← new Etudiant("Grael", new Date(12,9,2012))
listeEtudiant[3] ← new Etudiant("Coel", new Date(3,5,2014))
listeEtudiant[4] ← new Etudiant("Anael", new Date(18,8,2016))
menu(listeEtudiant, 5)
}

menu(liste : tableau d’Etudiant[], nbEtudiant : entier) : vide


afficherMenu () : vide
saisirNotes(liste : tableau d’Etudiant[], nbEtudiant : entier) : vide
saisirUneNote(etud : Etudiant) : vide
afficher(liste : tableau d’Etudiant[], nbEtudiant : entier) : vide
}

8.5. Exercices
Exercice 8.1
Une boulangerie est ouverte de 7 heures à 13 heures et de 16 heures à 20 heures, sauf
le lundi après-midi et le mardi toute la journée. On suppose que l'heure h est un entier entre 0
et 23. Le jour j code 0 pour lundi, 1 pour mardi, etc.

Ecrire un algorithme orienté objet qui demande le jour et l'heure, puis affiche si la
boulangerie est ouverte.
147

Exercice 8.2
Ecrire un algorithme orienté objet qui aide un utilisateur d'internet à calculer le prix de
la connexion téléphonique. Le programme demandera à l'utilisateur d'entrer l'heure à laquelle
il s'est connecté et l'heure à laquelle il s'est déconnecté. Vous pouvez faire les simplifications
suivantes:
• Il n'est pas nécessaire d'indiquer les minutes. On calcule donc avec des heures entières.
• L'heure du début de la connexion est toujours inférieure à l'heure de la fin de la
connexion.

Cela veut donc dire que l'utilisateur n'est jamais connecté avant minuit jusqu'à après
minuit et que la durée maximale d'une connexion est de 23 heures.

Les tarifs de connexion sont les suivants:


• Tarif 1 de 7h à 17h : 1 dollar/heure
• Tarif 2 de 0h à 7h et de 17h à 24h : 0.50 dollar/heure

Modulariser l’algorithme sous forme de méthodes auxiliaires.

Exemples d'exécution:
Début de la connexion : 5
Fin de la connexion : 7
Vous avez été connecté 2 heures pour 1 dollar

Début de la connexion : 6
Fin de la connexion : 8
Vous avez été connecté 2 heures pour 1.50 dollar

Début de la connexion : 8
Fin de la connexion : 10
Vous avez été connecté 2 heures pour 2 dollars

Début de la connexion : 0
Fin de la connexion : 23
Vous avez été connecté 23 heures pour 16.50 dollars
148

Début de la connexion : 10
Fin de la connexion : 5
Bizarre, le début est après la fin ...

Début de la connexion : 10
Fin de la connexion : 10
Bizarre, vous n'avez pas été connecté du tout ...

Exercice 8.3
Ecrire un algorithme orienté objet récursif et itératif qui permet de calculer la
factorielle d’un nombre.

Exercice 8.4
Écrire une classe nommée Carac, permettant de conserver un caractère, Elle disposera:
 d’un constructeur à un paramètre fournissant le caractère voulu ;
 d’un constructeur sans paramètre qui attribuera par défaut la valeur « espace » au
caractère ;
 d’une méthode nommée estVoyelle fournissant la valeur vrai lorsque le caractère
concerné est une voyelle et la valeur faux dans le cas contraire.
Écrire un petit programme utilisant cette classe.

Exercice 8.5
Écrire une classe Rectangle disposant :
 de trois constructeurs : le premier sans paramètre créera un rectangle dont les deux
dimensions sont égales à 1 ; le second à un paramètre sera utilisé à la fois pour les
deux dimensions, considérées comme égales ; le troisième à deux paramètres
correspondant aux deux dimensions du rectangle. Les dimensions seront de type réel ;
 d’une méthode périmètre fournissant en résultat le périmètre du rectangle ;
 d’une méthode surface fournissant en résultat la surface du rectangle ;
 d’une méthode agrandit disposant d’un paramètre de type réel correspondant à la
valeur par laquelle il faut multiplier les dimensions du rectangle.
Écrire un petit programme d’utilisation.
149

Exercice 8.6
On se propose d’établir les résultats d’examen d’un ensemble d’étudiants. Chaque
étudiant sera représenté par un objet de type Etudiant, comportant obligatoirement les champs
suivants :
 le nom de l’étudiant (type chaine),
 son admissibilité à l’examen, sous forme d’une valeur d’un type énuméré comportant
les valeurs suivantes : N (non admis), P (passable), AB (Assez bien), B (Bien), TB
(Très bien).

Les noms des étudiants sont contenus dans un fichier. On demande de définir
convenablement la classe Etudiant et d’écrire un programme principal qui :
 pour chaque étudiant, lit dans le fichier 3 notes d’examen, en calcule la moyenne et
renseigne convenablement le champ d’admissibilité, suivant les règles usuelles :
 moyenne < 10 : Non admis
 10 <= moyenne <12 : Passable
 12 <= moyenne <14 : Assez bien
 14 <= moyenne <16 : Bien
 16 <= moyenne : Très bien
 affiche l’ensemble des résultats en fournissant en clair la mention obtenue.
150

Chapitre 9 : Relations multi-classes


9.1. Héritage
9.1.1. Définition et exemple

Une classe conçue par héritage est la spécialisation d’une classe existante : elle
possède par définition toutes les propriétés de la première classe (attributs et méthodes) plus
d’autres propriétés qui la distinguent. Les deux classent définissent alors une relation de
généralisation.

Une classe mère, appelée aussi superclasse, est la classe qui léguera de ses propriétés
par héritage.

Une classe fille, appelée aussi sous-classe, est une nouvelle classe ayant acquis par
définition de l’héritage, tous les attributs et toutes les méthodes de la classe mère. Les classes
filles « spécialisent » ou « héritent » la classe mère.

Avec l’héritage, vous pouvez concevoir des classes de plus en plus spécialisées. De
même si vous devez concevoir des classes dont les propriétés sont très proches, plutôt que de
tout reprogrammer depuis zéro, vous pouvez concevoir une classe de base (la superclasse) et
créer deux classes qui héritent de celle-ci.

Pour indiquer que la classe B est une sous-classe de la classe A, nous allons l’un des
mot-clés : étend, spécialise, dériveDe ou hériteDe.

La déclaration textuelle :
Classe B étend A {
Attributs :
Déclaration des nouveaux attributs
Constructeurs :
Signatures des constructeurs
Méthodes :
Signatures des nouvelles méthodes
}

Exemple : Soit la classe mère suivante :


151

Class Date {
// attributs
privé jour, mois, annee : entiers
// méthodes
public Date()
{
jour ← j
mois ← mois
annee ← a;
}
public affecter(j: entier, m: entier, a: entier) : vide
{
jour ← j
mois ← m
annee ← a
}

public getJour() : entier


{
returne jour
}
public getMois() : entier
{
returne mois
}
public getAnnee(): entier
{
returne annee
}
public imprimer() : vide
{
afficher(jour+"/"+mois+"/"+annee)
}
}

La classe DateAnniversaire est une sous-classe de la classe Date :


Classe DateAnniversaire étend Date {
prive jour, mois, annee : entier
// attributs supplémentaires
privé nom, prenom: Chaine
// méthodes modifiées
public DateAnniversaire(j: entier, m: entier, a: entier, n : Chaine, p : Chaine)
{
jour ← j
mois ← m
annee ← a
nom ← n
prenom ← p
}
public affecter(j: entier, m: entier, a: annee, nom: Chaine, p : Chaine) : vide
{
jour ← j
mois ← m
152

annee ← a
nom ← n
prenom ← p
}
public void imprimer() : vide
{
afficher(prenom+" "+nom+" est ne le "+jour+"/"+mois+"/"+annee)
}
}

9.1.3. Opérateur super

Au même titre que l’opérateur this permet de faire référence à l'objet en cours,
l’opérateur super permet de désigner la superclasse, c'est-à-dire qu'à l'aide de l’opérateur
super, il est possible de manipuler les attributs et les méthodes de la superclasse.

Pour manipuler une propriété de la superclasse, il suffit d'utiliser la syntaxe suivante:


super.nomAttribut
Exemple : super.jour ← 18

De la même façon, pour manipuler une méthode de la superclasse, il suffit d'utiliser la


syntaxe suivante:
super.nomDeLaMethode()
Exemple : super.getJour()

Enfin, il est possible de faire appel au constructeur de la classe parente en fournissant


des arguments à l’opérateur super de la façon suivante:
super(parametre1, parametre2,...)

Exemple : super() //l’initialisation se fait au 01/01/1970 par défaut

9.1.4. Polymorphisme

Lorsqu'une classe hérite de sa superclasse, elle hérite de ses méthodes, c'est-à-dire


qu'elle possède les mêmes méthodes que sa superclasse.

Vous avez le droit, et c’est souvent le cas, de redéfinir une méthode d’une superclasse
dans une classe dérivée, avec le même nom de méthode.
153

Il est possible de redéfinir totalement une méthode en la redéfinissant (même nombre


et type d'arguments que la méthode de la superclasse). De cette façon, la méthode originale
est ignorée au profit de sa redéfinition.

9.1.5. Ajout d’un comportement à une méthode de la superclasse

La redéfinition d'une méthode consiste à réécrire totalement la méthode initiale. Il est


parfois utile de simplement ajouter un comportement au comportement original, pour cela
l'utilisation de l’opérateur super s'avère nécessaire. En appelant le constructeur de la
superclasse dans le corps de la méthode qui la redéfinit, et en ajoutant de nouvelles
instructions, la méthode originale est dotée de comportements supplémentaires.

La classe sous-classe DateAnniversaire peut être réécrite comme suit :

Class DateAnniversaire étend Date {


privé nom, prenom: Chaine
public DateAnniversaire(j: entier, m: entier, a: entier, n : Chaine, p : Chaine)
{
super(j,m,a)
nom ← n
prenom ← p
}
public affecter(j: entier, m: entier, a: annee, nom: Chaine, p : Chaine) : vide
{
Super.affecter(j,m,a)
nom ← n
prenom ← p
}

public void imprimer() : vide


{
afficher(prenom+" "+nom+" est ne le "+super.jour+"/"+ super.mois+"/"+
super.annee)
}
}

Pour faire le test, nous définissons la classe suivante :


Class TestDate {
public principall(): vide
{
DateAnniversaire d ← new DateAnniversaire(0,0,0,"","")
d.affecter(18,3,2008,"Djungu","Donel")
d.imprimer()
}
154

9.2. Classes et méthodes abstraites

Il y a des fois où vous avez besoin de définir un prototype de classe dans laquelle vous
allez déclarer des méthodes, mais pas forcément leur implémentation. Par exemple, vous
voulez créer des classes représentant des figures géométriques afin de concevoir un logiciel de
conception assistée par ordinateur. Dans ces logiciels (2D ou 3D), les différentes figures
tracées ont toutes leurs propriétés comme leurs dimensions, surface, périmètre, volume,
couleur de remplissage, couleur du contour, etc. Les valeurs de ces attributs varient d’une
figure à l’autre, c’est normal, mais certaines méthodes peuvent être identiques comme celles
pour la couleur, et d’autres non comme le calcul des surfaces, volumes et périmètres. Pourtant
toutes les figures (carrés, rectangles, polygones, triangles, trapèzes, losanges, etc) doivent
disposer de ces méthodes. Comment décrire ceci en objet ?

La solution consiste à écrire une classe de base qui deviendra la superclasse de toutes
les figures géométriques, et qui va contenir tous les attributs de base comme la position de
départ x, y du tracé de la figure, ses couleurs, mais aussi toutes les méthodes non seulement
de base mais qui doivent aussi obligatoirement être implémentées dans toutes les classes qui
en dérivent. Les méthodes de calcul de surface et de périmètre doivent être déclarées dans
cette classe. Pourtant elles ne contiendront rien comme code : ce sera à la classe dérivée de les
programmer.

Cette classe de base contenant des méthodes sans implémentation ne pourra pas être
instanciée, vous ne pourrez pas créer d’objet à partir d’elle, car elle est de fait inutilisable et
ne sert que de base pour les méthodes dérivées.

Une classe non instanciable et contenant des méthodes non implémentées, uniquement
destinée à être dérivée, est appelée une classe abstraite. Les méthodes non implémentées
qu’elle contient sont appelées méthodes abstraites.
1. Pour créer une classe abstraite, vous rajoutez le mot-clé "abstraite" après le nom de la
classe.
2. Pour créer une méthode abstraite, vous rajoutez le mot-clé "abstraite" avant son nom.
155

Classe abstraite Figure {


privé x :réel
privé y :réel
privé cContour :chaîne // couleur contour
privé cRemp :Chaîne //couleur remplissage
privé surface :réel
privé périmètre :réel

public setcolorC(couleur : Chaine) : vide


{
this.cContour ←couleur
}
...
abstraite getSurface() :réel
abstraite getPerimètre() :réel
...
}

À partir du moment où une classe contient une méthode abstraite, elle est elle-même
abstraite. La classe Figure est abstraite: elle contient des méthodes abstraites, sans
implémentation. Elle contient aussi des méthodes qui ne sont pas abstraites comme
setcolorC() qui n’aura pas forcément à être réimplémentée dans les classes dérivées.

Il est de ce fait impossible de créer un objet de type Figure. Vous devez maintenant
créer les classes qui en héritent. Voici deux exemples simplifiés de classes : Disque et
Rectangle. Vous devez implémenter dedans les méthodes abstraites de la superclasse.

Classe Disque étend Figure {


privé rayon : réel

public Disque(x1,y1,r)
{
this.x ← x1
this.y ← y1
this.rayon ← r
}
public getSurface() : réel
{
retourne PI*this.rayon*this.rayon
}
public getPerimètre() : réel
{
retourne 2*PI*this.rayon
}
}
156

Classe Rectangle étend Figure{


privé largeur :réel
privé hauteur :réel
Rectangle(x2,y2,l,h)
{
this.x ← x2
this.y ← y2
this.largeur ← l
this.hauteur ← h
}
public getSurface() : réel
{
retourne this.largeur*this.hauteur
}
public getPerimètre() : réel
{
retourne 2*(this.largeur+this.hauteur)
}
}

Nota: Vous êtes obligé d’implémenter dans la classe dérivée les méthodes abstraites de la
superclasse. Si vous ne souhaitez pas le faire, vous devez de nouveau déclarer la méthode
comme abstraite et la classe dérivée sera elle-même abstraite.

9.3. Interfaces

Les classes abstraites sont des classes comportant des méthodes implémentées ou non.
Elles servent généralement de superclasses à d’autres. Il est possible de pousser le
raisonnement plus loin : qu’est-il nécessaire de faire pour créer une classe servant uniquement
et entièrement de prototype à une classe ? Cette classe doit avoir les propriétés suivantes :
1. Non instanciable
2. Abstraite
3. Ne contenant que des méthodes abstraites.

Ainsi toute classe dérivant de cette classe spéciale devrait obligatoirement


implémenter toutes les méthodes. Quel est l’intérêt ? Celui de définir un modèle unique et
complet de méthodes pour les classes qui décident de les utiliser.

Ces types particuliers de classes s’appellent des interfaces. En pratique, une classe
n’hérite pas d’une interface : mis à part les définitions des méthodes une interface ne contient
pas de code. Pour déclarer une classe, vous utilisez le mot-clé Interface à la place de classe.
Par exemple, vous voulez créer une interface qui déclare toutes les méthodes de base pour la
157

lecture d’un fichier multimédia : lecture, pause, stop, avance rapide, retour rapide, piste
précédente, piste suivante. L’interface ressemblerait à ceci (les paramètres des méthodes ne
sont ici pas précisés):

Interface Lecture {
public Lecture()
public pause() : vide
public stop() : vide
public avance() : vide
public retour() : vide
public précédent() : vide
public suivant() : vide
}

On dit qu’une classe qui décide d’utiliser une interface implémente les méthodes de
l’interface, donc implémente l’interface. Vous utilisez ce même mot-clé pour le préciser.

Classe Tito implémente interface

Vous pouvez décider d’implémenter plusieurs interfaces au sein de votre classe, dans
ce cas vous séparez les noms des interfaces par des virgules.

Classe Tito implémente interface1, interface2, interfacen

Vous devez implémenter toutes les méthodes de l’interface dans la classe. Si vous ne
le faites pas, la méthode qui n’est pas implémentée doit être déclarée abstraite, et la classe
devient abstraite, donc non instanciable.

La classe Musique récupère l’interface Lecture :


Classe Musique implémente Lecture {
privé morceau :Chaîne
privé piste :Chaîne
privé position : entier
privé duree : entier

public Musique(m,p : Chaîne)


{
158

this.morceau ← m
this.piste ← p
position ← 0
// Méthode de calcul :durée du morceau en secondes
duree ← duree_morceau(morceau)
}
// Début d’implémentation de l’interface
public lecture() : vide
{
...
}
public pause() : vide
{
...
}
public stop() : vide
{
...
}
// Continuez ici
...
}

9.4. Gestion d’une pharmacie

Nous considérons une application multi-classes qui permet d’assurer la gestion d’une
pharmacie. Pour ce faire, il y a les classes Client et Medicament. Puisque, d’une part, un client
peut acheter un ou plusieurs médicaments et, d’autre part, un médicament peut être acheté par
un ou plusieurs clients, nous construisons une troisième chasse, appelée Pharmacie. Cette
dernière permet d’assurer le lien entre les classes Client et Medicament. C’est à partir de la
classe Pharmacie que s’effectuent les opérations suivantes :
 Achat des médicaments par les clients
 Approvisionnement en médicaments et
 Affichage des clients ainsi que des médicaments

9.4.1. Classe Medicament

Un médicament est caractérisé par un nom (de type Chaine), un prix (de type réel) et
un stock (de type entier).

class Medicament {
// Un médicament a un nom, un prix et une quantité en stock
privé nom : Chaine
privé prix : réel
159

privé stock : entier

public Medicament(nom : Chaine, prix : réel, stock : entier)


{
this.nom ← nom
this.prix ← prix
this.stock ← stock
}

public augmenterStock(quantite : entier) : vide


{
stock ← stock + quantite
}

public diminuerStock(int quantite: entier) : vide


{
stock ← stock - quantite
}

public getStock(): entier


{
retourne stock
}

public double getPrix(): reel


{
retourne prix
}

public String getNom(): Chaine


{
retourne nom
}
}

9.4.2. Classe Client

Un client est caractérisé par un nom et un crédit. Le crédit représente la somme que ce
client doit à la pharmacie. Le crédit peut être négatif si le client a versé plus d'argent que le
montant.

class Client {
// Un client est caractérisé par son nom et un crédit.
privé nom: Chaine
privé credit: réel

public Client(nom : Chaine, credit : réel)


{
this.nom ← nom
this.credit ← credit
}

public augmenterCredit(montant : réel) : vide


160

{
credit ← credit + montant
}

public diminuerCredit(montant : réel) : vide


{
credit ← credit - montant
}

public getCredit() : réel


{
retourne credit
}

public getNom() : Chaine


{
retourne nom
}
}

9.4.3. Classe Pharmacie

La classe Pharmacie permet de faire le lien entre les classes Client et


Medicament. A part la méthode principale, elle contient les méthodes suivantes:
 affichage() : permet d'afficher les clients et leurs crédits respectifs ainsi que les
médicaments et leurs stocks respectifs.
 approvisionner() : permet d'approvisionner le stock d'un médicament. Le nom du
médicament à approvisionner ainsi que la quantité à ajouter au stock doivent être lus
depuis le terminal. Lorsque le nom du médicament est introduit, il faut vérifier qu'il
s'agit bien d'un nom connu dans la liste des médicaments de la pharmacie.
L’algorithme doit boucler jusqu'à l’introduction d'un nom correct. Cette procédure de
vérification sera prise en charge par la méthode lireMedicament() décrite plus bas.
 achat() : permet de traiter un achat fait par un client. L'achat porte sur un médicament
donné dans une quantité donnée. Pour cette transaction le client paie un certain prix.
Une opération d'achat aura pour effet de déduire la quantité achetée du stock du
médicament correspondant et d'augmenter le crédit du client (d'un montant équivalent
au montant de l'achat moins la somme payée). Les noms du client et du médicament
doivent être lus depuis le terminal. L’algorithme doit boucler jusqu'à l’introduction de
noms connus aussi bien pour les clients que les médicaments. Ces procédures de
vérification seront prises en charge par les méthodes lireClient() et lireMedicament().
La quantité achetée et le montant payé sont aussi lus depuis le terminal. Ils seront
supposés corrects.
161

 quitter() : affiche le message ''Fin de traitement!''.


162

Nous définirons une méthode auxiliaire lireClient() prenant comme paramètre un


tableau de clients. Elle permettra de lire le nom d'un client depuis le terminal et de vérifier si
ce client existe dans le tableau des clients. Dans ce cas le client sera retourné. Cette méthode
doit boucler jusqu'à ce qu'un client soit trouvé. Elle sera utilisée par la méthode achat(). Une
méthode similaire, lireMedicament() sera fournie pour les médicaments. Elle sera utilisée par
les méthodes achat() et approvisionnement().

public classe Pharmacie {


public static principal(): void
{
clients: tableau[] de Clients
medicaments: tableau[] de Medicaments

clients ← new Client[5]


clients[0] ← new Client("Donel", 0.0)
clients[1] ← new Client("Amel", 0.0)
clients[2] ← new Client("Grael", 0.0)
clients[3] ← new Client("Coel", 0.0)
clients[4] ← new Client("Anael", 0.0)

medicaments ← new Medicament[4]


medicaments[0] ← new Medicament("Aspirine", 20.40, 5)
medicaments[1] ← new Medicament("Maladox", 19.15, 5)
medicaments[2] ← new Medicament("Doliprane", 20.40, 5)
medicaments[3] ← new Medicament("Tranxene", 19.15, 5)

choix : entier
faire {
choix ← menu()
suivant_que (choix) faire
{
1: achat(clients, medicaments)
2: approvisionnement(medicaments)
3: affichage(clients, medicaments)
4: quitter()
}
} tant_que(choix < 4)
}
// Les méthodes utilitaires
static menu() : entier
{
choix ← 0 : entier
afficher()
afficher("1 : Achat de médicament")
afficher("2 : Approvisionnement en médicaments")
afficher("3 : Etats des stocks et des crédits")
afficher("4 : Quitter")
tant_que ((choix != 1) et (choix != 2) et (choix != 3) et (choix != 4))
{
163

afficher("Quel est votre choix ?")


lire(choix)
}
retourne choix
}

// Méthode auxiliaire de principal permettant à un client d'acheter un médicament


static achat(clients: Client[], medicaments: Medicament[]): vide
{
paiement : réel
quantite : entier
client : Client
medicament : Medicament

client ← lireClient(clients)
medicament ← lireMedicament(medicaments)
paiement ← lirePaiement()
quantite ← lireQuantite()
si (quantite <= medicament.getStock())
{
medicament.diminuerStock(quantite)
client.augmenterCredit((medicament.getPrix() * quantite) - paiement)
} sinon
afficher("Achat impossible. Quantité insuffisante")
}

// Méthode auxiliaire de principal permettant d'augmenter le stock d'un médicament


static approvisionnement(medicaments: Medicament[]): vide
{
quantite : entier
medicament : Medicament

medicament ← lireMedicament(medicaments)
afficher("Donner la Quantité : ")
lire(quantite)
medicament.augmenterStock(quantite)
}

// Méthode auxiliaire de principal permettant d'afficher les données stockées dans les tableaux
clients et medicaments
static affichage(clients: Client[],medicaments: Medicament[]): vide
{
i: entier
afficher("Affichage des stocks")
pour i ← 0 à medicaments.longueur()-1 faire
{
afficher ("Stock du médicament " + medicaments[i].getNom(), " est ",
medicaments[i].getStock())
}
afficher("Affichage des crédits")
pour i ← 0 à clients.longueur()-1 faire
{
afficher("Crédit du client ", clients[i].getNom(), " est " , clients[i].getCredit())
}
}
164

// Retourne l'objet Client associé à un nom


// Le nom est lu et redemandé tant qu'il ne correspond pas au nom d'un client contenu dans le
tableau clients
static lireClient(clients : Client[]) : Client
{
i: entier
nom: Chaine
trouve ← faux: booléen
c ← nulle : Client
afficher("Nom du client?")
faire{
lire(nom)
pour i ← 0 à (!trouve et i < clients.longueur()) faire
{
si ((clients[i].getNom()).egal(nom)) alors
{
trouve ← vrai
c ← clients[i]
}
}
si (!trouve) alors
afficher("Client inconnu. Veuillez recommencer")

} tant_que(!trouve)
retourne c
}
// Retourne l'objet Medicament associé à un nom
// Le nom est lu et redemandé tant qu'il ne correspond pas au nom d'un médicament contenu
dans le tableau medicaments
static lireMedicament(medicaments: Medicament[]): Medicament
{
i: entier
nom: Chaine
trouve ← faux: booléen
m ← nulle : Medicament
afficher("Nom du médicament?:")
faire{
lire(nom)
pour i ← 0 à (!trouve et i < medicaments.longueur()) faire
{
si ((medicaments[i].getNom()).egal(nom)) alors
{
trouve ← vrai
m ← medicaments[i]
}
}
si (!trouve) alors
afficher("Medicament inconnu. Veuillez recommencer")

} tant_que(!trouve)
retourne m
}

static lirePaiement() : réel


{
165

paiement : réel
afficher("Quel est le montant du paiement?");
lire(paiement)
retourne paiement
}

static lireQuantite() : entier


{
quantite : entier
afficher("Quelle est la quantité achetée?");
lire(quantite)
retourne quantite
}

static quitter() : vide


{
afficher("Fin de traitement!")
}
}

9.5. Gestion des employés d’une entreprise

Le directeur d'une entreprise de produits chimiques souhaite gérer les salaires et


primes de ses employés au moyen d'un algorithme orienté objet.

9.5.1. Classe Employe

Un employé est caractérisé par son nom, son prénom, son âge et sa date d'entrée en
service dans l'entreprise.

Nous allons codés une classe abstraite Employe dotée des attributs nécessaires, d'une
méthode abstraite calculerSalaire (ce calcul dépendra en effet du type de l'employé) et d'une
méthode getNom retournant une chaine de caractère obtenue en concaténant la chaine de
caractères "L'employé " avec le prénom et le nom.

Dotons également la classe d'un constructeur prenant en paramètre l'ensemble des


attributs nécessaires.

Classe abstraite Employe {


privé nom: Chaine
privé prenom: Chaine
privé age: entier
privé date: Date
public Employe(prenom: Chaine, nom: Chaine, age: entier, date: Date)
{
166

this.nom ← nom
this.prenom ← prenom
this.age ← age;
this.date ← date
}
public abstraite calculerSalaire() : réel
public getTitre() : Chaine
{
retourne "L'employé "
}
public getNom(): Chaine
{
return getTitre() &prenom & " " &nom
}
}

9.5.2. Calcul de salaire

Le calcul du salaire mensuel dépend du type de l'employé. On distingue les types


d'employés suivants :
 Ceux affectés à la Vente. Leur salaire mensuel est le 20 % du chiffre d'affaire qu'ils
réalisent mensuellement, plus 400 dollars.
 Ceux affectés à la Représentation. Leur salaire mensuel est également le 20 % du
chiffre d'affaire qu'ils réalisent mensuellement, plus 800 dollars.
 Ceux affectés à la Production. Leur salaire vaut le nombre d'unités produites
mensuellement multipliées par 5.
 Ceux affectés à la Manutention. Leur salaire vaut leur nombre d'heures de travail
mensuel multipliées par 65 dollars.

Dès lors, hiérarchisons les classes pour les employés en respectant les conditions
suivantes :
 La super-classe de la hiérarchie doit être la classe Employe.
 Les nouvelles classes doivent contenir les attributs qui leur sont spécifiques ainsi que
le codage approprié des méthodes calculerSalaire et getNom, en changeant le mot
"employé" par la catégorie correspondante.
 Chaque sous classe est dotée de constructeur prenant en argument l'ensemble des
attributs nécessaires.
 Introduisons des classes intermédiaires pour éviter au maximum les redondances
d'attributs et de méthodes dans les sous-classes.
167

// La classe Commercial (regroupe Vendeur et Représentant)

Classe abstraite Commercial étend Employe {


privé chiffreAffaire : réel
public Commercial(prenom: Chaine, nom: Chaine, age : entier, date : Date, chiffreAffaire :
réel)
{
super(prenom, nom, age, date)
this.chiffreAffaire ← chiffreAffaire
}
public getChiffreAffaire() : réel
{
retourne chiffreAffaire
}
}

// La classe Vendeur

Classe Vendeur étend Commercial {


privé static pourcentVeudeur ← 0.2 : réel
privé static bonusVendeur ← 400 : entier
public Vendeur(prenom: Chaine, nom: Chaine, age : entier, date : Date, chiffreAffaire : réel)
{
super(prenom, nom, age, date, chiffreAffaire)
}
public double calculerSalaire() : réel
{
retourne (pourcentVeudeur * getChiffreAffaire()) + bonusVendeur
}
public String getTitre() : Chaine
{
reoturne "Le vendeur "
}
}

// La classe Représentant

Classe Représentant étend Commercial {


privé static pourcentReprésentant ← 0.2 : réel
privé static bonusReprésentant ← 800 : entier
public Représentant (prenom: Chaine, nom: Chaine, age : entier, date : Date, chiffreAffaire :
réel)
{
super(prenom, nom, age, date, chiffreAffaire)
}
public double calculerSalaire() : réel
{
retourne (pourcentReprésentant * getChiffreAffaire()) + bonusReprésentant
}
public String getTitre() : Chaine
{
reoturne "Le représentant "
168

}
}

// La classe Technicien (Production)

Class Technicien étend Employe {


Privé static facteurUnite ← 5.0 : réel
privé unites : entier
public Technicien(prenom: Chaine, nom: Chaine, age: entier , date : Date, unites : entier)
{
super(prenom, nom, age, date)
this.unites ← unites;
}
public calculerSalaire() : réel
{
retourne facteurUnite * unites
}
public getTitre() : Chaine
{
retourne "Le technicien "
}
}

// La classe Manutentionnaire
Class Manutentionnaire étend Employe {
Privé static salaireHoraire ← 65.0 : réel
privé heures : entier
public Manutentionnaire (prenom: Chaine, nom: Chaine, age: entier, date : Date, heures :
entier)
{
super(prenom, nom, age, date)
this.heures ← heures
}
public calculerSalaire() : réel
{
retourne salaireHoraire * heures
}
public getTitre() : Chaine
{
retourne "Le manutentionnaire "
}
}

9.5.3. Employés à risques

Certains employés des secteurs production et manutention sont appelés à fabriquer et


manipuler des produits dangereux.
169

Après plusieurs négociations syndicales, ces derniers parviennent à obtenir une prime
de risque mensuelle.

Complétons notre description en introduisant deux nouvelles sous-classes d'employés.


Ces sous-classes désigneront les employés des secteurs production et manutention travaillant
avec des produits dangereux.

Ajoutons également une interface pour les employés à risque permettant de leur
associer une prime mensuelle fixe de 200 dollars.

// L'interface d'employés à risque

Interface ARisque {
prime ← 200 : entier
}

// Une première sous-classe d'employé à risque


Classe TechnARisque étend Technicien implemente ARisque {
public TechnARisque(prenom: Chaine, nom: Chaine, age: entier, date: Date, unites: entier)
{
super(prenom, nom, age, date, unites)
}
public calculerSalaire() : réel
{
retourne super.calculerSalaire() + prime
}
}

// Une autre sous-classe d'employé à risque


Classe ManutARisque étend Manutentionnaire implemente ARisque {
public ManutARisque(prenom: Chaine, nom: Chaine, age: entier, date: Date, heures: entier)
{
super(prenom, nom, age, date, heures);
}
public calculerSalaire() : réel
{
retourne super.calculerSalaire() + prime
}
}

9.5.4. Collection d'employés

Satisfait de la hiérarchie proposée, notre directeur souhaite maintenant l'exploiter pour


afficher le salaire de tous ses employés ainsi que le salaire moyen.
170

Ajoutons ainsi une classe Personnel contenant une "collection" d'employés.


Définissons ensuite les méthodes suivantes à la classe Personnel :
 ajouterEmploye(Employe) : vide
qui ajoute un employé à la collection.
 calculerSalaires() : vide
qui affiche le salaire de chacun des employés de la collection.
 salaireMoyen() : réel
qui affiche le salaire moyen des employés de la collection.

// La classe Personnel
Classe Personnel {
privé staff: tableau[] d’Employes
privé nbreEmploye: entier
privé static maxEmploye ← 200: entier

public Personnel()
{
staff ← new Employe[maxEmploye ]
nbreEmploye ← 0
}
public void ajouterEmploye(Employe emp) : vide
{
nbreEmploye ← nbreEmploye + 1
si (nbreEmploye <= maxEmploye )
{
staff[nbreEmploye - 1] ← emp
} sinon
{
afficher ("Pas plus de " & maxEmploye & " employés")
}
}

public salaireMoyen() : réel


{
i: entier
somme ← 0.0 : réel
pour i ← 0 à nbreEmploye-1 faire
{
somme ← somme + staff[i].calculerSalaire()
}
retourne somme / nbreEmploye
}
public afficherSalaires() : vide
{
pour i ← 0 à nbreEmploye-1 faire
{
171

afficher(staff[i].getNom() & " gagne " & staff[i].calculerSalaire() & "


dollars.");
}
}
}

9.5.5. Classe Salaires

Testons la classe Personnel pour calculer le salaire de chaque employé :


Classe Salaires {
public static principal() : vide
{
p : Personnel
p ← new Personnel()
p.ajouterEmploye(new Vendeur("Donel", "Business", 35, "1995", 30000));
p.ajouterEmploye(new Representant("Amel", "Vendtout", 25, "2001", 20000));
p.ajouterEmploye(new Technicien("Grael", "Bosseur", 28, "1998", 1000));
p.ajouterEmploye(new Manutentionnaire("Coel", "Stocketout", 32, "1998", 45));
p.ajouterEmploye(new TechnARisque("Anael", "Flippe", 28, "2000", 1000));
p.ajouterEmploye(new ManutARisque("Kenaya", "Abordage", 30, "2001", 45));
p.afficherSalaires();
afficher("Le salaire moyen dans l'entreprise est de " & p.salaireMoyen() & "
dollars.");
}
}

Nous devrions obtenir quelque chose comme :

Le vendeur Donel Business gagne 6400.0 dollars.


Le représentant Amel Vendtout gagne 4800.0 dollars.
Le technicien Grael Bosseur gagne 5000.0 dollars.
Le manutentionnaire Coel Stocketout gagne 2925.0 dollars.
Le technicien Anael Flippe gagne 5200.0 dollars.
Le manutentionnaire Kenaya Abordage gagne 3125.0 dollars.
Le salaire moyen dans l'entreprise est de 4575.0 francs.

9.6. Exercices
Exercice 9.1
Réaliser une classe Repertoire permettant de gérer un répertoire téléphonique
associant un numéro de téléphone (chaîne de caractères) à un nom.

La classe Repertoire devra disposer des fonctionnalités suivantes :


• constructeur recevant un argument de type entier précisant le nombre maximum
d’abonnés que pourra contenir le répertoire (cette particularité évite d’avoir à se
soucier d’une gestion dynamique du répertoire),
172

• méthode addAbonne permettant d’ajouter un nouvel abonné ; elle renverra la valeur


faux si le répertoire est plein, la valeur vrai sinon,
• méthode getNumero fournissant le numéro associé à un nom d’abonné fourni en
argument,
• méthode getNAbonnes qui fournit le nombre d’abonnés figurant dans le répertoire,
• méthode getAbonne fournissant l’abonné dont le rang est fourni en argument,
• méthode getAbonnesTries fournissant un tableau des références des différents
abonnés, rangés par ordre alphabétique (pour simplifier, on supposera que les noms
sont écrits en minuscules, sans caractères accentués).
Écrire un petit programme de test.

Exercice 9.2
Ecrire une classe de Personne définie par un nom et un âge. Ecrire une classe Couple
qui permet de réunir et de séparer deux personnes. Donner un exemple d’utilisation.

Exercice 9.3
Une pharmacie peut être vue comme une classe d'objets ayant pour attribut un
tableau de clients et un tableau de médicaments.
173

Il vous est demandé de :


 Modifier la classe Pharmacie de sorte à la doter des attributs susmentionnés.
 Transformer les méthodes statiques se rapportant uniquement aux attributs de
Pharmacie en des méthodes d'instances.
Indication: Si vous avez respecté les directives de la première question, les méthodes
lireClient() et lireMedicament(), par exemple, deviennent des méthodes d'instance de
la classe Pharmacie.
 Adapter la méthode principal() de la classe GestionPharmacie de manière appropriée.
 Placer les méthodes auxiliaires qui n'ont pu être transformées en méthodes d'instance
de Pharmacie dans GestionPharmacie.
174

Chapitre 10 : Complexité algorithmique


10.1. Définitions

L'analyse de la complexité d'un algorithme consiste en l'étude formelle de la quantité


de ressources (par exemple de temps ou d'espace) nécessaire à l'exécution de cet algorithme.

10.1.1. Opérations élémentaires

Étant donné un algorithme, nous appelons opérations élémentaires:


 un accès en mémoire pour lire ou écrire la valeur d’une variable ou d’une case d’un
tableau ;
 une opération arithmétique entre entiers ou entre réels : addition, soustraction,
multiplication, division, calcul du reste dans une division entière ;
 une comparaison entre deux entiers ou deux réels

Exemple : Si on considère l’instruction c ← a + b, on peut compter quatre opérations


élémentaires:
 l’accès en mémoire pour lire la valeur de a ;
 l’accès en mémoire pour lire la valeur de b ;
 l’addition de a et b ;
 l’accès en mémoire pour écrire la nouvelle valeur de c

10.1.2. Instance

Pour un problème donné, on appelle instance ou taille de l’entrée tout jeu de données
de ce problème. Par exemple, pour un problème de tri, on obtient une instance en spécifiant la
valeur numérique des nombres à trier.

Pour la plupart des problèmes, plus la taille de l’entrée est grande, plus il faudra du
temps pour trouver la solution. Par exemple, il est évident qu’on mettra plus de temps à trier
une liste d’un million d’éléments plutôt qu’une liste de 3 éléments.

Il est alors naturel d’évaluer le temps de calcul d’un algorithme en fonction de la taille
de son entrée.
175

10.1.3. Ordre de grandeur

Soient f et g deux fonctions positives d’une même variable entière x. La fonction f est
dite avoir un ordre de grandeur au plus égal à celui de la fonction g s’il existe un entier
strictement positif k et un entier N tels que, pour tout n ≥ N, on ait
f(n) ≤ k g(n)
On écrira : f = O(g) (notation de Landau)

Les deux fonctions sont dites avoir même ordre de grandeur si l’ordre de grandeur de
l’une est au moins égal à l’ordre de grandeur de l’autre et réciproquement ; on pourra écrire :
f = Ө(g)
Par exemple, les fonctions f(n) = 3n2 – 5n + 4 et g(x) = n2 ont même ordre de
grandeur. On dira aussi que g est un ordre de grandeur de f.

10.2. Généralités

Nous allons maintenant introduire la notion de complexité algorithmique, sorte de


quantification de la performance d'un algorithme.

10.2.1. But d'un calcul de complexité

L'objectif premier d'un calcul de complexité algorithmique est de pouvoir comparer


l’efficacité d’algorithmes résolvant le même problème. Dans une situation donnée, cela
permet donc d'établir lequel des algorithmes disponibles est le plus optimal.

Si nous devons par exemple trier une liste de nombres, est-il préférable d'utiliser un tri
par sélection ou un tri à bulles ?

Ce type de question est primordial, car pour des données volumineuses la différence
entre les durées d'exécution de deux algorithmes ayant la même finalité peut être de l'ordre de
plusieurs jours.

Pour faire cela, nous chercherons à estimer la quantité de ressources utilisée lors de
l'exécution d'un algorithme.
176

Les règles que nous utiliserons pour comparer et évaluer les algorithmes devront
respecter certaines contraintes très naturelles. Nous demanderons principalement qu'elles ne
soient pas tributaires des qualités d'une machine ou d'un choix de technologie.

En particulier, cela signifiera que ces règles seront indépendantes des facteurs
suivants:

 du langage de programmation utilisé pour l'implémentation de l’algorithme.


 du processeur de l'ordinateur sur lequel sera exécuté le code.
 de l'éventuel compilateur ou traducteur employé.

Le premier réflexe qui consisterait à coder les algorithmes sur un ordinateur puis à
comparer leurs durées d’exécution n’est donc pas le bon. Il ne vérifie en effet pas les
contraintes précédentes et ne permet donc pas de juger leurs qualités intrinsèques.

Nous allons donc effectuer des calculs sur l’algorithme en lui-même, dans sa version
"papier". Les résultats de ces calculs fourniront une estimation du temps d’exécution de
l’algorithme, et de la taille mémoire occupée lors de son fonctionnement.

10.2.2. Types de complexité

On distinguera deux sortes de complexité, selon que l'on s'intéresse au temps


d'exécution ou à l'espace mémoire occupé.

a. Complexité en temps

Réaliser un calcul de complexité en temps revient à décompter le nombre d’opérations


élémentaires (affectation, calcul arithmétique ou logique, comparaison…) effectuées par
l’algorithme.

Pour rendre ce calcul réalisable, nous émettrons l'hypothèse que toutes les opérations
élémentaires sont à égalité de coût. En pratique, ce n'est pas tout à fait exact mais cette
approximation est cependant raisonnable.

Nous pourrons donc estimer que le temps d'exécution de l'algorithme est proportionnel
au nombre d’opérations élémentaires.
177

b. Complexité en espace

La complexité en espace est quant à elle la taille de la mémoire nécessaire pour stocker
les différentes structures de données utilisées lors de l'exécution de l'algorithme.

Nous nous intéresserons peu à cette problématique dans la suite de cet ouvrage, nous
nous contenterons juste de l'évoquer de temps à autre.

10.2.3. De quoi est fonction la complexité ?

La complexité d'un algorithme va naturellement être fonction de la taille des données


passées en paramètres. Cette dépendance est logique, plus ces données seront volumineuses,
plus il faudra d'opérations élémentaires pour les traiter. Par exemple, pour un algorithme de tri
cette taille sera le nombre de valeurs à trier.

On appelle complexité d’un algorithme A tout ordre de grandeur du nombre


d’opérations élémentaires effectuées pendant le déroulement de l’algorithme.

En règle générale, on exprime ce nombre d’opérations en fonction de paramètres


associés aux instances à traiter.

Nous supposerons que nos algorithmes n'ont qu'une donnée, dont la taille est
nécessairement un entier naturel. La complexité en temps d’un algorithme sera donc une
fonction de 𝑁 dans R+. Nous la noterons en général T (pour Temps).

Souvent la complexité dépendra aussi de la donnée en elle- même et pas seulement de


sa taille. En particulier, la façon dont sont réparties les différentes valeurs qui la constituent.

Imaginons par exemple que l'on effectue une recherche séquentielle d’un élément dans
une liste non triée. Le principe de l'algorithme est simple, on parcourt un par un les éléments
jusqu'à trouver, ou pas, celui recherché. Ce parcours peut s’arrêter dès le début si le premier
élément est "le bon". Mais on peut également être amené à parcourir la liste en entier si
l’élément cherché est en dernière position, ou même n'y figure pas. Le nombre d'opérations
élémentaires effectuées dépend donc non seulement de la taille de la liste, mais également de
la répartition de ses valeurs.
178

Cette remarque nous conduit à préciser un peu notre définition de la complexité en


temps. En toute rigueur, on devra en effet distinguer trois formes de complexité en temps :

 la complexité dans le meilleur des cas : c'est la situation la plus favorable, qui
correspond par exemple à la recherche d'un élément situé à la première position d'une
liste, ou encore au tri d'une liste déjà triée.
 la complexité dans le pire des cas : c'est la situation la plus défavorable, qui
correspond par exemple à la recherche d'un élément dans une liste alors qu'il n'y figure
pas, ou encore au tri par ordre croissant d'une liste triée par ordre décroissant.
 la complexité en moyenne : on suppose là que les données sont réparties selon une
certaine loi de probabilités.

On calculera le plus souvent la complexité dans le pire des cas, car elle est la plus
pertinente. Il vaut mieux en effet toujours envisager le pire.

Exemple : Soit un algorithme effectuant f(n) = 3n2 – 5n + 4 opérations élémentaires. Sa


complexité est de l’ordre de O(n2).

Dernière chose importante à prendre en considération, si la donnée en elle-même est


un nombre entier, la façon de le représenter influera beaucoup sur l’appréciation de la
complexité.

Par exemple, si n = 4096 on peut considérer que la taille de n est :

 la valeur de n en elle-même, la façon la plus naturelle de voir les choses, c’est-à-dire


4096
 le nombre de chiffres que comporte l'écriture en binaire de n, c’est-à-dire 13
 le nombre de chiffres que comporte l'écriture en décimal de n, c’est-à-dire 4

Vu la finalité informatique de nos algorithmes, nous choisirons souvent dans ce cas-là


le nombre de chiffres dans l'écriture binaire de l'entier n.

10.3. Sommes usuelles

Nous rappelons ici sans démontrer quelques égalités bien connues relatives à certaines
sommes. Elles nous seront fort utiles lors de nos calculs de complexités.
179

a. Somme des n termes constants

Soit n élément de N∗ et c élément de R. On a


𝑛

∑ 𝑐 = 𝑛𝑐
𝑘=1
b. Somme des n premiers entiers

Soit n élément de N∗. On a


𝑛
𝑛(𝑛 + 1)
∑𝑘 =
2
𝑘=1

c. Somme des n premiers carrés d'entiers

Soit n élément de N∗. On a


𝑛
𝑛(𝑛 + 1)(2𝑛 + 1)
∑ 𝑘2 =
6
𝑘=1

d. Somme des n premiers termes d'une suite géométrique

Soit n élément de N∗ et q élément de R. Si q≠1, on a


𝑛
1 − 𝑞 𝑛+1
∑ 𝑞𝑘 =
1−𝑞
𝑘=0

10.4. Calculs de la complexité

10.4.1. Application des règles

Pour calculer la complexité d’un algorithme :


1. on calcule la complexité de chaque “partie” de l’algorithme ;
2. on combine ces complexités comme suit :
a. Appel séquentiel
f(…)
{
g(…)
h(…)
}

O(f) = O(g) + O(h )


180

b. Appel conditionnel
f(…)
{
si (…) alors
g(…)
sinon
h(…)
}

O(f) = max(O(g), O(h ))

Nota : Attention aux appels itératifs


f(n : entier)
{
pour i ← 0 à n-1 faire
{
g(…)
}
}

Nous aurons O(f) = n*O(g). Cependant, il n’est toujours pas le cas, c’est-à-dire que
lorsque l’appel à la fonction g(…) est dépendant de l’indice de boucle :
f(n : entier)
{
pour i ← 0 à n-1 faire
{
g(i)
}
}

Nous devons réécrire le coût en comptabilisant les différents appels, ainsi nous avons :
O(f) = ∑𝑛−1
𝑖=0 𝑂(𝑔( 𝑖))

3. on simplifie le résultat grâce aux règles de simplifications qu’on a vues :


a. élimination des constantes, et
b. conservation du (des) terme(s) dominant(s).

10.4.2. Classification des algorithmes

Les algorithmes usuels peuvent être classés en un certain nombre de grandes classes de
complexité.
181

 Les algorithmes sub-linéaires ou logarithmiques, dont la complexité est en général en


O(log n). C'est le cas de la recherche d'un élément dans un ensemble ordonné fini de
cardinal n.
 Les algorithmes linéaires en complexité O(n) ou en O(n*log n) sont considérés
comme rapides, comme l'évaluation de la valeur d'une expression composée de n
symboles ou les algorithmes optimaux de tri.
 Plus lents sont les algorithmes quadratiques et cubiques de complexité située entre
O(n2) et O(n3), c'est le cas de la multiplication des matrices et du parcours dans les
graphes.
 Au-delà, les algorithmes polynomiaux en O(nk) pour k > 3 sont considérés comme
lents, sans parler des algorithmes exponentiels (dont la complexité est supérieure à
tout polynôme en n) que l'on s'accorde à dire impraticables dès que la taille des
données est supérieure à quelques dizaines d'unités.

10.4.3. Quelques exemples

a. Conversion

La fonction suivante convertit un nombre de secondes en heures, minutes, secondes :

fonction conversion(n : entier) : vide


Variables
h, m, s : entier
Debut
h ← n / 3600
m ← (n - 3600*h) / 60
s ← n MOD 60
afficher h,m,s
Fin

Cet algorithme ne comporte pas de structures de contrôle. On peut dénombrer cinq


opérations arithmétiques et trois affectations. On a donc T(n) = 8 et T(n) = O(1) (complexité
constante).

b. Calcul itératif de la somme des n premiers entiers

Cette fonction utilise une structure pour… faire pour calculer la somme des n premiers
entiers :

fonction sommeEntiers(n : entier) : entier


182

Variables
i, somme : entier
Debut
somme ← 0

pour i ← 0 à n-1 faire


{
somme ← somme+i
}
retourne somme
Fin

Ici chaque itération a le même nombre d’opérations, à savoir cinq : deux affections (i
et somme), deux additions (i et somme) et une comparaison.

On a d'autre part une affectation, lors de l'initialisation de la variable somme. Ainsi


T(n) = 5n+1 et T(n) = O(n) (complexité d’ordre n).

c. Recherche séquentielle d'un élément dans un tableau

La fonction suivante recherche l'élément x dans la liste tab. Si x appartient à tab, elle
retourne l'indice de la première occurrence de x dans tab, sinon elle retourne -1.

Son fonctionnement est simple, les éléments de la liste sont parcourus un par un grâce
à une structure pour… faire :

fonction recherche(tab : tableau[] d’entiers, n : entier, x : entier) : entier


Debut
pour i ← 0 à n-1 faire
{
si (tab[i] = x) alors
{
retourne i
}
}
retourne -1
Fin

Ici la complexité sera fonction de la longueur de la liste, que nous noterons n. Dans le
pire des cas l'élément recherché n'appartient pas à la liste, et il a fallu la parcourir en entier
pour arriver à cette conclusion, c'est-à-dire effectuer n itérations.

De plus, chaque itération comporte le même nombre d'opérations élémentaires, à


savoir une affectation, une addition et deux comparaisons. On a donc T(n) = 4n et
T(n) = O(n) (complexité d’ordre n).
183

d. Tri par sélection

Le tri par sélection est un algorithme itératif réalisant le tri par ordre croissant d'une
liste (cfr. 5.3.1).

Il consiste dans un premier temps à mettre à la première place le plus petit élément de
la liste, puis à la seconde place le deuxième plus petit élément, etc.

Pour rappel, sa description est la suivante :

1. Rechercher dans la liste la plus petite valeur et la permuter avec le premier élément de
la liste.
2. Rechercher ensuite la plus petite valeur à partir de la deuxième case et la permuter
avec le second élément de la liste.
3. Et ainsi de suite jusqu’à avoir parcouru toute la liste.

fonction triParSelection(tab : tableau[] d’entiers, n : entier) : vide


Variables
i, j: entiers
minV, taille, temp : entiers
Début
pour i ← 0 à taille-2
{
minV ← i
pour j ← i+1 à taille-1
{
si (tab[j] < tab[minV]) alors
{
minV ← j
}
}
si (minV != i) alors
{
temp ← tab[minV]
tab[minV] ← tab[i]
tab[i] ← temp
}
}
Fin

Ici aussi la complexité sera fonction de la longueur n de la liste. Le pire des cas
correspond à une liste triée par ordre décroissant.

Chaque itération de la boucle principale, la plus externe, ne possède pas le même


nombre d'opérations. Il y a toujours les huit mêmes (les opérations concernant la variable i,
184

l'initialisation de minV et l'échange des valeurs), plus les opérations dues à la boucle la plus
interne, qui elles sont en nombre variable.

La boucle interne a elle par contre le même nombre d'opérations par itération, à savoir
cinq.

Le nombre d'itérations de la boucle interne varie d'une itération à l'autre de la boucle


externe :

 à la première itération de la boucle externe la variable i vaut 0 et la boucle interne


effectue donc n−1 itérations.
 à la seconde itération de la boucle externe la variable i vaut 1 et la boucle interne
effectue donc n−2 itérations.
 etc.

La complexité de cet algorithme sera alors égale à la somme du nombre d'opérations


de chaque itération de la boucle externe. A savoir :

8 + 5𝑥(𝑛 − 1) + 8 + 5𝑥(𝑛 − 2) + ⋯ + 8 + 5𝑥1 = ∑𝑛−1


𝑖=1 (8 + 5𝑥𝑖)

= 8𝑥(𝑛 − 1) + 5𝑥 ∑𝑛−1
𝑖=1 𝑖

(𝑛−1)𝑥𝑛
= 8𝑥(𝑛 − 1) + 5𝑥 2

5 11
= 2 𝑛2 + 𝑛−8
2

Lors de ce calcul, on a utilisé la valeur d'une somme de termes constants et celle de la


somme des premiers entiers (cfr. 10.3 ci-haut).

Conclusion, la complexité dans le pire des cas du tri par sélection est T(n) = 2n2+5n−8
et T(n) = O(n2) (complexité d’ordre n2).

e. Recherche par dichotomie

Si tab est un tableau d'entiers triés de taille n, on peut écrire une fonction qui cherche
si un entier donné se trouve dans le tableau. Comme le tableau est trié, on peut procéder par
dichotomie (cfr 5.4.2): cherchant à savoir si x est dans tab[g..d[, on calcule m = (g+d) DIV 2
185

et on compare x à tab[m]. Si x = tab[m], on a gagné, sinon on réessaie avec tab[g..m[ si


tab[m] > x et dans tab[m+1..d[ sinon.

fonction rechercheDichotomique(tab : tableau[] d’entiers, n : entier, x : entier) : entier


Variables
g, d, m : entiers
Début
g←0
d ← n-1
faire
{
m ← (g + d) DIV 2
si (tab[m] =x ) alors
retourne m
sinon si (x > tab[m]) alors
g←m+1
sinon
g←m-1
} tant_que (g < = d)

retourne -1
Fin

Notons que l'on peut écrire cette fonction sous forme récursive :

// recherche de x dans tab[g..d[


fonction dichoRec(tab : tableau[] d’entiers , x : entier, g : entier, d : entier) : entier
Variables
m : entier
Début

si (g >= d) alors // l'intervalle est vide


retourne -1
m = (g+d) DIV 2
si (tab[m] = x) alors
retourne m
sinon si (t[m] > x) alors
retourne dichoRec(tab, x, g, m);
sinon
retourne dichoRec(tab, x, m+1, d);
Fin

fonction rechercheDichotomique(tab : tableau[] d’entiers, n : entier, x : entier) : entier


Debut
retourne dichoRec(tab, x, 0, n);
Fin

Le nombre maximal de comparaisons à effectuer pour un tableau de taille n est:


T(n) = 1 + T(n/2).
Pour résoudre cette récurrence, on écrit n = 2t, ce qui conduit à
186

T(2t) = T(2t-1)+1 = ⋯ = T(1)+t

D'où un coût en O(t) = O(log n).

10.5. Exercices

Exercice 10.1
Quelle est la complexité de l’algorithme qui permet de faire le produit d’une matrice
carrée d’ordre n par un vecteur de la taille n?

Exercice 10.19
Quelle est la complexité de l’algorithme qui permet de faire le produit de deux
matrices carrées d’ordre n?

.
187

Annexe : Corrigés des exercices


Chapitre 1

Exercice 1.1
Un algorithme permet de rédiger un programme sans être pollué par la complexité et la
technicité d’un langage donné.

Exercice 1.2
Tout débutant en programmation a besoin de l’algorithmique. Elle peut également
servir :
 à celui qui apprend à programmer directement dans un langage donné. Elle lui
permettra d’accompagner son étude, en dégageant les concepts fondamentaux et en
prenant un peu de recul par rapport au langage de programmation;
 à celui qui maîtrise déjà la programmation dans un langage donné et qui désire «passer
à un autre langage»

Exercice 1.3
Non, pour ce qui est de l’algorithmique au sens mathématique, il faut seulement être
un peu intuitif, méthodique et rigoureux.

Exercice 1.4
Oui, c’est le cas avec le logiciel AlgoBox.

Exercice 1.5
Non, AlgoBox ne supporte pas l’orienté objet.

Chapitre 2

Exercice 2.1

Affectation Valeur de a Valeur de b


a←5 5 0
b←a+3 5 8
a←7 7 8
188

Exercice 2.2

Affectation Valeur de a Valeur de b Valeur de c


a←3 3 0 0
b←5 3 5 0
c←a+b 3 5 8
a←1 1 5 8
c←b–a 1 5 4

Exercice 2.3
Affectation Valeur de a Valeur de b
a←7 7 0
b←1 7 1
a←b 1 1
b←a 1 1

Les deux dernières instructions ne permettent donc pas d’échanger les deux valeurs de
a et b, puisque l’une des deux valeurs (celle de a) est ici écrasée.

Si l’on inverse les deux dernières instructions, cela ne changera rien du tout, hormis le
fait que cette fois c’est la valeur de b qui sera écrasée.

Exercice 2.4
Algorithme exercice24
Variables
a, b, temp : entier
Debut
temp ← a
a←b
b ← temp
Fin

On est obligé de passer par une variable dite temporaire (la variable temp).
189

Exercice 2.5
Soient trois variables a, b et c (supposées du même type). Écrire les instructions
permutant leurs valeurs, de sorte que la valeur de b passe dans a, celle de c dans b et celle de a
dans c.
Algorithme exercice24
Variables
a, b, c, d : entier
Debut
d←c
c←b
b←a
a←d
Fin

Exercice 2.6
Expression valeur
a+b/c 5,42
a+c/b 7,37
(a + c) / b 3,00
a+b/a+b 14,60
(a + b) / (a + b) 1,00

Exercice 2.7
Il ne peut produire qu’une erreur d’exécution, puisqu’on ne peut pas additionner des chaines
des caractères.

Exercice 2.8
A la fin de l’algorithme, c vaudra donc "12345".

Exercice 2.9
On verra apparaître à l’écran 15, puis 75 (qui vaut 15 * 5).

Exercice 2.10
Algorithme exercice210
Variables
nb, carre : entier
Debut
190

afficher "Entrez un nombre :"


lire nb
carre ← nb * nb
afficher "Son carré est : ", carre
Fin

En fait, on pourrait tout aussi bien économiser la variable carre en remplaçant les deux
avant-dernières lignes par :

afficher "Son carré est : ", nb*nb

C'est une question de style; dans un cas, on privilégie la lisibilité de l'algorithme, dans
l'autre, on privilégie l'économie d'une variable.

Exercice 2.11
Algorithme exercice211
Variables
nb1, nb2, somme, produit : entier
Debut
afficher "Entrez un nombre :"
lire nb1
afficher "Entrez un deuxième nombre :"
lire nb2
somme ← nb1 + nb2
afficher "La somme est : ", somme
produit ← nb1 * nb2
afficher "Le produit est : ", produit
Fin

Exercice 2.12
Algorithme exercice212
Variables
nb1, nb2, nb3, nb4, nb5: entier
moy : réel
Debut
lire nb1, nb2, nb3, nb4, nb5
moy ←( nb1+ nb2+ nb3+ nb4+ nb5)/5
afficher "La moyenne est : ", moy
Fin
191

Exercice 2.13
Algorithme exercice213
Variables
prenom, nom : chaine
Debut
afficher "Entrez votre prénom:"
lire prenom
afficher "Entrez ensuite votre nom :"
lire nom
afficher prenom& " "&nom
Fin

Exercice 2.14
Algorithme exercice214
Variables
c1, c2 : entier
Debut
afficher "Entrez la cote de l’examen sur 10 :"
lire c1
afficher "Entrez des travaux pratiques sur 10:"
lire c2
afficher "La cote globale obtenue sur 20 est : ", c1 +c2
Fin

Exercice 2.15
Algorithme exercice215
Variables
franc, doll : réel
Debut
afficher "Entrez la somme en francs congolais :"
lire franc
doll ← franc/1620 // 1 dollar = 1620 FC
afficher doll
Fin

Exercice 2.16
Une seule donnée est introduite, la somme initiale. Prenons 158 $, qui se décomposera
en 15 x 10 $ plus 1 x 5 $ et 3 x 1 $. Analysons les étapes élémentaires utilisées pour calculer
cela. Il faut d’abord garder les premiers chiffres et enlever le denier (avec 158 DIV 10 et 158
MOD 10).
192

Algorithme exercice216
Variables
somme, reste : entier
nb10Doll, nb5Doll nb1Doll : entier
Debut
afficher "Quelle est la somme initiale ?"
lire somme
nb10Doll ← somme DIV 10
reste ← somme DIV 10
nb5Doll ← reste DIV 5
nb1Doll ← reste MOD 5
afficher "Billets de 10 $: ", nb10Doll
afficher "Billets de 5 $: ", nb5Doll
afficher "Billets de 1 $: ", nb1Doll
Fin

Exercice 2.17
Algorithme exercice217
Variables
qte : entier
prixHT, prixTTC, tva : réel
Debut
afficher "Quel est le prix d’un kilo de tomates ?"
lire prixHT
afficher " Quel est le nombre de kilos de tomates achetés ?"
lire qte
afficher "Entrez le taux de TVA :"
lire tva
prixTTC ← nb * prixHT * (1 + tva)
afficher "Le prix toutes taxes est : ", prixTTC
Fin

Exercice 2.18
Algorithme exercice218
Variables
larg, long, perimetre, surface : réel
Debut
afficher "Quelle est la largeur du champ ?"
lire larg
afficher " Et sa longueur ?"
lire long
perimetre ← 2* (long+larg)
193

surface ← long*larg
afficher "Le perimètre est : ", perimetre
afficher "La surface est : ", surface
Fin

Exercice 2.19
Algorithme exercice219
Constantes
vPI = 3.14
Variables
rayon, perimetre, surface : réel
Debut
afficher "Quel est le rayon du cercle ?"
lire rayon
perimetre ← 2*vPI*r
afficher "Le périmètre est : ", perimetre
surface ← vPI*(r^2)
afficher "La surface est : ", surface
Fin

Exercice 2.20
Algorithme exercice220
Constantes
vPI = 3.14
Variables
rayon, surface, volume : réel
Debut
afficher "Quel est le rayon du cercle ?"
lire rayon
surface ← 4*vPI*(r^2)
volume ← 4*vPI*(r^3)/3
afficher "La surface est : ", surface
afficher "Le volume est : ", volume
Fin

Chapitre 3
Exercice 3.1
Algorithme exercice31
Variables
x : réel
Debut
afficher "Entrez un nombre :"
194

lire x
si (x > 0) alors
afficher "Ce nombre est positif"
sinon
afficher "Ce nombre est négatif"
Fin

Exercice 3.2
Algorithme exercice32
Variables
x : entier
Debut
afficher "Entrez un nombre entier :"
lire x
si ((x > 10) et (x < 20)) alors
afficher "Ce nombre est dans la fourchette"
sinon
afficher "Ce nombre est en dehors de la fourchette"
Fin

Exercice 3.3
Algorithme exercice33
Variables
x, y : entier
Debut
afficher "Entrez deux nombres:"
lire x, y
si ((x > 0 et y > 0) ou (x < 0 et y < 0)) alors
afficher "Leur produit est positif"
sinon
afficher "Leur produit est négatif"
Fin

Exercice 3.4
Algorithme exercice34
Variables
x, y, z : chaine
195

Debut
afficher "Entrez successivement trois noms:"
lire x, y, z
si ((x < y) et (y < z)) alors
afficher "Ces noms sont classés alphabétiquement"
sinon
afficher " Ces noms ne sont pas classés "
Fin

Exercice 3.5
Algorithme exercice35
Variables
x: entier
Debut
afficher "Somme avant d’entrer dans le magasin:"
lire x
si (x >= 5) alors
x←x-5
afficher "Somme après passage à la caisse : ", x
Fin

Exercice 3.6
On demandera à l’utilisateur d’affecter la variable caze (qui correspond à la case
obtenue par Donel au cours de sa partie) et l’algorithme donnera en fin d’exécution le gain de
la partie (si elle perd, son gain est de -2).

Algorithme exercice36
Variables
caze, gain: entier
Debut
afficher "Case obtenue par Donel:"
lire caze
si (case >= 8) alors
gain ← 8
sinon
gain ← -2
196

afficher "Gain obtenu par Donel: ", gain


Fin

Exercice 3.7
Algorithme exercice37
Variables
age: entier
Debut
afficher "Entrez l’âge de l’enfant:"
lire age
si (age >= 12) alors
afficher "Catégorie Cadet"
sinon si (age >= 10) alors
afficher "Catégorie Minime"
sinon si (age >= 8) alors
afficher "Catégorie Pupille"
sinon si (age >= 6) alors
afficher "Catégorie Poussin"
Fin

On peut évidemment écrire cet algorithme de différentes façons, ne serait-ce qu’en


commençant par la catégorie la plus jeune.

Exercice 3.8
Algorithme exercice38
Variables
note: entier
Debut
afficher "Entrez la note obtenue:"
lire note
si (note >= 16) alors
afficher "Mention Très bien"
sinon si (note >= 14) alors
afficher " Mention Bien"
sinon si (note >= 12) alors
afficher " Mention Assez bien"
197

sinon si (note >= 10) alors


afficher " Mention Passable"
sinon
afficher " Mention Insuffisant"
Fin

Exercice 3.9
Algorithme exercice39
Variables
note1, note2, note3, note4, note5: entier
moy : réel
Debut
afficher "Entrez 5 notes:"
lire note1, note2, note3, note4, note5
moy ← (note1+ note2+ note3+ note4+ note5)/5
si (moy >= 16) alors
afficher "Mention Très bien"
sinon si (moy >= 14) alors
afficher " Mention Bien"
sinon si (moy >= 12) alors
afficher " Mention Assez bien"
sinon si (moy >= 10) alors
afficher " Mention Passable"
sinon si (moy >= 8) alors
afficher " Admis oral du deuxième groupe "
sinon
afficher "Recalé"
Fin

Exercice 3.10
Algorithme exercice310
Constantes
tv = 0.16
Variables
prixHT, prixTTC, remise : réel
Debut
afficher "Donnez le prix hors taxe: "
lire prixHT
prixTTC ← prixHT * (1 + tva)
198

afficher "Le prix toutes taxes est : ", prixTTC


si (prixTTC < 100) alors
taux ← 0
sinon si (prixTTC < 200) alors
taux ← 1
sinon si (prixTTC < 500) alors
taux ← 2
sinon
taux ← 5
remise ← prixTTC * taux/100
prixTTC ← prixTTC – remise
afficher "La remise est de : ", remise
afficher "Prix après remise : ", prixTTC
Fin

Exercice 3.11
Algorithme exercice311
Variables
a, b, c, delta, x1, x2: réel
Debut
afficher "Introduisez les valeurs de a, b et c:"
lire a, b, c
delta ← ( b * b ) - ( 4 * a * c )
si (delta > 0) alors
{
x1 ← ( -b + racine(delta) ) / ( 2 * a )
x2 ← ( -b - racine(delta) ) / ( 2 * a )
afficher "Les racines sont :", x1, x2
}
sion si (delta = 0) alors
{
x1 ← -b / ( 2 * a )
x2 ← x2
afficher "Les racines sont :", x1, x2
}
sinon
afficher "Pas des racines réelles"
Fin

On pourra aussi tenir compte du fait que la valeur de a pourra être nulle.

Exercice 3.12
Algorithme exercice312
Variables
h, m: entier
Debut
afficher "Entrez les heures, puis les minutes:"
lire h, m
m←m+1
199

si (m = 60) alors
{
m←0
h←h+1
}
si (h =24) alors
h←0
afficher "Dans une minute il sera ", h, "heure(s) ", m, "minute(s)"
Fin

Exercice 3.13
Algorithme exercice313
Variables
n, p: entier
Debut
afficher "Nombre de photocopies:"
lire n
si (n< = 10) alors
p ← n*0.1
sinon si (n < = 30) alors
p ← 10*0.1 + (n-10)*0.09
sinon
p ← 10*0.1 + 20*0.09+ (n-30)*0.08

afficher "Le prix total est : ", p


Fin

Exercice 3.14
Algorithme exercice314
Variables
age: entier
sexe : caractère
x1, x2 : booléen
Debut
afficher "Entrez le sexe (M/F):"
lire sexe
afficher "Entrez l’âge:"
lire age
x1 ← (sexe = "M") et (age > 20)
x2 ← (sexe = "F") et ((age > 18) et (age < 35))
si (x1 ou x2) alors
afficher "Imposable"
sinon
afficher "Non imposable"
Fin

Exercice 3.15
Nous constatons que 3 types de contrats sont proposés. Identifions dans l’ordre les
conditions impliquant un contrat Vert, puis Orange, puis Rouge.
200

Vert age >= 25 et nb = 0


Orange (age < 25 et acc = 0) ou (age >= 25 et (acc = 1 ou acc = 2))
Rouge (age < 25 et (acc = 1 ou acc = 2)) ou (age >= 25 et (acc >= 3 et acc < = 6))

Algorithme exercice315
Variables
age, acc: entier
type : chaine
Debut
afficher "Entrez l’âge:"
lire age
afficher "Entrez le nombre d’accidents:"
lire acc
si (age >= 25 et acc = 0) alors
type ← "Vert"
sinon si ((age < 25 et acc = 0) ou (age >= 25 et (acc = 1 ou acc = 2))) alors
type ← "Orange"
sinon si ((age < 25 et (acc = 1 ou acc = 2)) ou (age >= 25 et (acc >= 3 et acc <= 6)))
alors
type ← "Rouge"
sinon
type ← " Refusé"
afficher "Type d’assurance", type
Fin

Les conditions de cet algorithme peuvent encore s’améliorées comme suit:


si (age >= 25 et acc = 0) alors
type ← "Vert"
sinon si ((age < 25 et acc = 0) ou (age >= 25 et acc <= 2)) alors
type ← "Orange"
sinon
si ((age < 25 et acc <= 2) ou (age >= 25 et acc <= 6)) alors
type ← "Rouge"
sinon
type ← "Refusé"

Exercice 3.16
Algorithme exercice316
Variables
age, perm, nb, assur : entier
x1, x2, x3 : booléen
type : caractère
Debut
afficher "Entrez l’âge: "
lire age
afficher "Entrez le nombre d'années de permis: "
lire perm
afficher "Entrez le nombre d'accidents: "
201

lire acc
afficher "Entrez le nombre d'années d'assurance: "
lire assur
x1 ← age >= 25
x2 ← perm >= 2
x3 ← assur > 1
si (non(x1) et non(x2)) alors
{
si (acc = 0) alors
type ← "Rouge"
sinon
type ← "Refusé"
}
sinon si (((non(x1) et x2) ou (x1 et non(x2))) alors
{
si (acc = 0) alors
type ← "Orange"
sinon si (acc = 1) alors
type ← "Rouge"
sinon
type ← "Refusé"
}
sinon
{
si (acc = 0) alors
type ← "Vert"
sinon si (acc = 1) alors
type ← "Orange"
sinon si (acc = 2) alors
type ← "Rouge"
sinon
type ← "Refusé"
}
si x3 alors
{
si (type = "Rouge") alors
type ← "Orange"
sinon si (type = "Orange") alors
type ← "Orange"
sinon si (type = "Vert") alors
type ← "Bleu"
}
afficher "Votre situation : ", type
Fin

Exercice 3.17
Algorithme exercice317
Variables
nbMinute: entier
tarif1, tarif2 : réel
Debut
afficher "Entrez le nombre de minutes:"
202

lire nbMinute
tarif1 ← 10 + 0.50 * nbMinute
tarif2 ← 15 + 0.42 * nbMinute
si (tarif1 < tarif2) alors
afficher "Choisir Telecom 1"
sinon
afficher " Choisir Telecom 2"
Fin

Exercice 3.18
Algorithme exercice318
Variables
nbJour: entier
tarif1, tarif2 : réel
Debut
afficher "Entrez le nombre de jours:"
lire nbJour
tarif1 ← 150 + 10 * nbJour
tarif2 ← 170 + 5 * nbJour
si (tarif1 < tarif2) alors
afficher "Chambre A"
sinon si (tarif1 = tarif2) alors
afficher "Chambre A ou Chambre B"
sinon
afficher "Chambre B"
Fin

Exercice 3.19
Cet exercice représente dignement la catégorie des énoncés piégés. En effet, rien de
plus facile que d'écrire : si le candidat a plus de 50%, il est élu, sinon s'il a plus de 12,5 %, il
est au deuxième tour, sinon il est éliminé. Mais il ne faut pas oublier que le candidat peut très
bien avoir eu 20 % mais être tout de même éliminé, tout simplement parce que l'un des autres
a fait plus de 50 % et donc qu'il n'y a pas de deuxième tour. Moralité : ne jamais se jeter sur la
programmation avant d'avoir soigneusement mené l'analyse du problème à traiter.

Algorithme exercice319
Variables
a, b, c, d: réel
c1, c2, c3, c4 : booléen
Debut
afficher "Entrez les scores des quatre prétendants :"
lire a, b, c, d
c1 ← a > 50
c2 ← b > 50 ou c > 50 ou d > 50
c3 ← a >= b et a >= c et a >= d
c4 ← a >= 12,5
si c1 alors
203

afficher “Elu au premier tour"


sinon si (c2 ou non(c4) alors
afficher “Battu, éliminé, sorti !!!”
sinon si c3 alors
afficher "Ballotage favorable"
sinon
afficher "Ballotage défavorable"
Fin

Exercice 3.20
L’algorithme pour indiquer si une année est bissextile ou non, est le suivant. Notons
que dire qu’une année est divisible par n consiste à dire que le reste de la division par n est
nul.

Algorithme bissextile
Variables
annee : entier
Debut
afficher "Entrez l’année"
lire annee
si (annee MOD 4 = 0) et ((annee MOD 400 = 0) ou (annee MOD 100) > 0)) alors
afficher annee, " est bissextile"
sinon
afficher annee, " n’est pas bissextile"
Fin

Le test d’année bissextile n’intervient que lors des calculs sur le dernier jour du mois
de février, pour savoir si le lendemain du 28 est le 29 ou le 1er mars. De même, il faut gérer
les cas où les mois ont 30 ou 31 jours, ainsi que le changement d’année lors du mois de
décembre. L’algorithme utilise des structures "suivant … faire" et "si ".

Algorithme exercice320
Variables
jour, mois, annee : entier
Debut
afficher "Date initiale ?"
lire jour, mois, annee
suivant_que mois faire
{
1:{
si (jour=31) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
204

}
2:{
si (annee MOD 4 = 0) et ((annee MOD 400 = 0) ou (annee MOD 100) > 0)) alors
{
si (jour=29) alors
{
jour←1
mois←mois+1
}
sinon
jour←jour+1
}
sinon
{
si (jour=28) alors
{
jour←1
mois←mois+1
}
sinon
jour←jour+1

}
}
3: {
si (jour=31) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
4:{
si (jour=30) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
5:{
si (jour=31) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
6:{
si (jour=30) alors
{
jour ←1
205

mois ← mois+1
}
sinon
jour←jour+1
}
7:{
si (jour=31) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}

8:{
si (jour=31) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
9:{
si (jour=30) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
10 : {
si (jour=31) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
11 : {
si (jour=30) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
12 : {
si (jour=31) alors
{
jour←1
206

mois←1
annee←annee+1
}
sinon
jour←jour+1
}
afficher "Le lendemain est le ",,jour, mois, annee
Fin

Pour éviter les répétitions, nous pouvons regrouper les cas et réécrire l’algorithme
comme suit :
Algorithme exercice320
Variables
jour, mois, annee : entier
Debut
afficher "Date initiale ?"
lire jour, mois, annee
suivant_que mois faire
{
1 : 3 : 5 : 7 : 8 : 10 :{
si (jour=31) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}
4 : 6 : 9 : 11 :{
si (jour=30) alors
{
jour ←1
mois ← mois+1
}
sinon
jour←jour+1
}

2:{
si (annee MOD 4 = 0) et ((annee MOD 400 = 0) ou (annee MOD 100) > 0)) alors
{
si (jour=29) alors
{
jour←1
mois←mois+1
}
sinon
jour←jour+1
}
sinon
{
si (jour=28) alors
{
207

jour←1
mois←mois+1
}
sinon
jour←jour+1

}
}
12 : {
si (jour=31) alors
{
jour←1
mois←1
annee←annee+1
}
sinon
jour←jour+1
}
afficher "Le lendemain est le ",,jour, mois, annee
Fin

Chapitre 4
Exercice 4.1
Algorithme exercice41
Variables
nb: entier
Debut
nb ← 0
afficher "Entrez un entier inférieur à 10"
tant_que ((nb < 0) ou (nb >= 10)) faire
{
lire nb
si ((nb < 0) ou (nb >= 10)) alors
afficher "Saisie erronée. Recommencez”
}
Fin

Exercice 4.2
Algorithme exercice42
Variables
nb: entier
Debut
nb ← 0
afficher "Entrez un nombre entre 10 et 20"
tant_que ((nb < 10) ou (nb > 20)) faire
{
lire nb
208

si (nb < 10) alors


afficher "Plus grand !”
sinon si (nb > 20) alors
afficher "Plus petit !”

}
Fin

Exercice 4.3
Réécrire l’algorithme précédent en utilisant une autre forme de boucle.
Algorithme exercice43
Variables
nb: entier
Debut
nb ← 0
afficher "Entrez un nombre entre 10 et 20"
faire
{
lire nb
si (nb < 10) alors
afficher "Plus grand !”
sinon si (nb > 20) alors
afficher "Plus petit !”

} tant_que ((nb < 10) ou (nb > 20))


Fin

Exercice 4.4
Algorithme exercice44
Variables
i, n: entier
Debut
afficher "Entrez un nombre : "
lire n
afficher "Les 20 nombres suivants sont : "
pour i allant de n+1 à n+20 faire
{
afficher i
}
Fin

Exercice 4.5
Algorithme exercice45
Variables
i, n, som: entier
209

Debut
som ← 0
afficher "Entrez un nombre : "
lire n

pour i allant de 1 à n faire


{
som ← som + i
}
afficher "La somme est : ", som
Fin

Exercice 4.6
Algorithme exercice46
Variables
i, nd, nf: entier
Debut
afficher "Entrez un entier positif : "
lire nd
afficher "Entrez un autre entier positif supérieur au premier: "
lire nf
pour i allant de nd à nf faire
{
afficher "Le double est : ", 2*i
}
Fin

Exercice 4.7
Algorithme exercice47
Variables
i, n: entier
som : réel
Debut
som ← 0.0
afficher "Entrez un nombre : "
lire n
pour i allant de 1 à n faire
{
som ← som + 1/i
}
afficher "La somme est : ", som
Fin
210

Exercice 4.8
Algorithme exercice48
Variables
i, n: entier
Debut
afficher "Entrez un nombre : "
lire n

pour i allant de 1 à 10 faire


{
afficher i ," * ", n, " = ", i*n
}
Fin

Exercice 4.9
Algorithme exercice49
Variables
age, compte: entier
Debut
compte ← 0
pour age allant de 1 à n faire
{
compte ← compte + 100 + (2*age)
}
afficher " Le compte de Donel au nième anniversaire est ", compte
Fin

Exercice 4.10
Algorithme exercice410
Constantes
b = 10000000
s = 5000000
Variables
annee: entier
Debut
annee ← 0
tant_que (s <= b) faire
{
annee ← annee + 1
b ← b + 500 000
s ← b * 1,03
}
211

afficher "Il faut ", annee, "années pour la population du Sankuru dépassera celle de Beni "
Fin

Exercice 4.11
Algorithme exercice411
Variables
i, x, max: entier
Debut
max ← 0
pour i allant de 1 à 20 faire
{
affiher "Entrez un nombre : "
lire x
si (x > max) alors
max ← x
}
afficher "Le nombre le plus grand était : ", max
Fin

Exercice 4.12
Algorithme exercice412
Variables
x, max: entier
Debut
max ← 0
x←0
tant_que (x <> 0) faire
{
affiher "Entrez un nombre : "
lire x
si (x > max) alors
max ← x
}
pour i allant de 1 à 20 faire
{
affiher "Entrez un nombre : "
lire x
si (x > max) alors
max ← x
}
afficher "Le nombre le plus grand était : ", max
Fin
212

Exercice 4.13
Algorithme exercice413
Variables
c1, c2, c3, c4, c5, i, n: entier
moy, max: réel
nom, meilleur : chaine
Debut
max ← 0.0
meilleur ← " "
affiher "Entrez le nombre d’étudiants de la promotion: "
lire n
pour i allant de 1 à n faire
{
affiher "Entrez le nom de l’étudiant : "
lire nom
affiher "Introduisez les 5 notes : "
lire c1, c2, c3, c4, c5
moy ← (c1 + c2 + c3 + c4 + c5)/5
si (moy > max) alors
{
max ← moy
meilleur ← nom
}
}
afficher meilleur, " est le meilleur étudiant avec une moyenne de : ", max
Fin

Exercice 4.14
Algorithme exercice414
Variables
montant, montantV, somdue, reste, nb10, nb5: entier
Debut
montant ← 1
somdue ← 0
tant_que (montant <> 0) faire
{
afficher "Entrez le montant : "
lire montant
somdue ← somdue + montant
}
afficher "Vous devez :", somdue, " dollars"
afficher "Montant versé :"
lire montantV
reste ← montantV – somdue
nb10 ← 0
tant_que (reste >= 10) faire
213

{
nb10 ← nb10 + 1
reste ← reste – 10
}
nb5 ← 0
si (reste >= 5) alors
{
Nb5 ← nb5 + 1
reste ← reste – 5
}
afficher "Rendu de la monnaie :"
afficher "Billets de 10 dollars : ", nb10
afficher "Billets de 5 dollars : ", nb5
afficher "Billets de 1 dollar: ", reste
Fin

Exercice 4.15
Algorithme exercice415
Variables
montant, i, min, max, som : entier
moy : réel
Debut
min ←1000000
max ←0
som←0
pour i allant de 1 à 12 faire
{
affiher "Entrez le montant reçu du ", i, "ième mois"
lire montant
som ← som + montant
si (montant < min) alors
{
min ← montant
}
sinon si (montant > max) alors
{
max ← montant
}
}
moy ← som/12
afficher " La somme mensuelle moyenne reçue:", moy
afficher " Le montant minimal reçu sur l'année:", min
afficher " Le montant maximal reçu sur l'année: ", max
Fin

Exercice 4.16
Algorithme exercice416
Variables
capIni, cap, taux: réel
214

Debut
affiher "Donnez le capital à placer et le taux :"
lire cap, taux
capIni ← cap
tant_que (cap < 2 * capIni) faire
{
cap ← cap * (1 + taux)
afficher "Capital un an plus tard : ", cap
}
Fin

Exercice 4.17
Algorithme exercice417
Variables
i: entier
capIni, cap, taux: réel
Debut
affiher "Donnez le capital à placer et le taux :"
lire cap, taux
capIni ← cap
i← 1
tant_que (cap < 2 * capIni) faire
{
cap ← cap * (1 + taux)
afficher "Capital, à l’année ", i, " : ", cap
}
Fin

Exercice 4.18
L’algorithme va s’arrête lorsqu’on va donner la valeur nulle (" ") au sexe, c’est-à-dire
il n’y a plus de votant.

Algorithme exercice418
Variables
sexe, intention : caractère
hOui, hNon, hAbst, fOui, fNon, fAbst: entier
Debut
sexe ← "M"
hOui, hNon, hAbst, fOui, fNon, fAbst ← 0
tant_que (sexe <> " ") faire
{
affiher "Quel est votre sexe (M/F)?"
lire sexe
affiher "Et l’intention de vote (O/N/A) ?"
lire intention
suivant_que intention faire
{
"O" ou "o": si ((sexe = "M") ou (sexe = "m")) alors
215

hOui ← hOui +1
sinon
fOui ← fOui +1
"N" ou "n": si ((sexe = "M") ou (sexe = "m")) alors
hNon ← hNon +1
sinon
fNon ← fNon +1
"A" ou "a": si ((sexe = "M") ou (sexe = "m")) alors
hAbst ← hAbst +1
sinon
fAbst ← fAbst +1
}
affiher " Les intentions de vote des hommes :"
affiher " Oui :", hOui
affiher " Non :", hNon
affiher " Blanc ou abstention :", hAst
affiher " Les intentions de vote des femmes :"
affiher " Oui :", fOui
affiher " Non :", fNon
affiher " Blanc ou abstention :", fAst
}
Fin

Exercice 4.19
Algorithme exercice419
Variables
f1, f2, f3: entier
Debut
f1 ← 1
f2 ← 1
affiher f1
affiher f2
pour i allant de 3 à 20 faire
{
f3 ← f1 + f2
affiher " La suite des couples depuis au ", i, " ème mois est ", f3
f1 ← f2
f2 ← f3
}
Fin
216

Exercice 4.20
Pour alléger, nous pouvons simplifier les fractions en tenant compte du fait que la
factorielle de n peut s’écrire comme suit :
n! = n*(n-1)*(n-2)*…*(n+1-p)*(n-p)!
Algorithme exercice420
Variables
i, n, p: entier
x, y, t : réel
Debut
afficher "Entrez le nombre de chevaux partants : "
lire n
afficher "Entrez le nombre de chevaux joués : "
lire p
x←1
t←1
pour i allant de 1 à p faire
{
x ← x * (n + i - p)
t←t*i
}
y ← x/t
afficher "Dans l’ordre, une chance sur ", x
afficher "Dans le désordre, une chance sur ", y

Fin

Chapitre 5
Exercice 5.1
Cet algorithme remplit un tableau avec dix valeurs : 0, 1, 4, 9, 16, 25, 36, 49, 81, 100.
Il les écrit ensuite à l’écran. Simplification :
Algorithme exercice51
Variables
tab : tableau[10] d’entiers
i : entier
Debut
pour i ← 0 à 9 faire
{
tab[i]← i * i
afficher tab[i]
}
Fin

Exercice 5.2
Cet algorithme remplit un tableau avec les dix valeurs : 1, 3, 5, 7, 9, 11, 13, 15, 17, 19.
Il les écrit ensuite à l’écran. Simplification :
217

Algorithme exercice52
Variables
tab : tableau[10] d’entiers
i : entier
Debut
tab[0]← 1
pour i ← 1 à 9 faire
{
tab[i]← tab[i-1]+2
afficher tab[i]
}
Fin

Exercice 5.3
Cet algorithme remplit un tableau avec les dix valeurs : 1, 1, 2, 3, 5, 8, 13, 21, 34, 55.
Il les écrit ensuite à l’écran. Simplification :
Algorithme exercice53
Variables
tab : tableau[10] d’entiers
i: entier
Debut
tab[0]← 1
tab[1]← 1
afficher tab[0]
afficher tab[1]
pour i ← 2 à 9 faire
{
tab[i]← tab[i-2]+tab[i-1]
afficher tab[i]
}
Fin

Exercice 5.4
Cet algorithme remplit un tableau de la manière suivante:
tab[0] [0] = 1
tab[0] [1] = 2
tab[0] [2] = 3
tab[1] [0] = 4
tab[1] [1] = 5
tab[1] [2] = 6
Il écrit ensuite ces valeurs à l’écran, dans cet ordre.
218

Exercice 5.5
Algorithme exercice55
Variables
tab : tableau[] d’entiers
taille, indice, x : entier
occur, positionCherchee : entier
Début
occur ← 0
lire taille
indice ← 0
tant_que (indice < taille) faire
{
lire tab[indice]
indice ← indice + 1
}
// La recherche
lire x
indice ← 0
tant_que (indice < taille) faire
{
si (tab[indice] = x) alors
{
occur ← occur + 1
}

indice ← indice + 1
}
afficher " Le nombre d’occurrences est : ", occur
Fin

Exercice 5.6
Algorithme exercice56
Variables
p, q, r : tableau[] d’entiers
i, n : entier
Début
lire n
i←0
tant_que (i < n) faire
{
lire p[i]
lire q[i]
r[i] ← p[i] + q[i]
afficher r[i]
indice ← indice + 1
}
Fin
219

Exercice 5.7
Algorithme exercice57
Variables
p, q: tableau[] d’entiers
i, n, sca : entier
Début
lire n
sca ← 0
i←0
tant_que (i < n) faire
{
lire p[i]
lire q[i]
sca ← sca +p[i] * q[i]
indice ← indice + 1
}
afficher "Le produit scalaire est: ", sca
Fin

Exercice 5.8
Algorithme exercice58
Variables
montant : tableau[12] d’entiers
montant, i, min, max, som : entier
moy : réel
Debut
min ←1000000
max ←0
som←0
pour i allant de 1 à 12 faire
{
affiher "Entrez le montant reçu du ", i, "ième mois"
lire montant[i]
som ← som + montant[i]
si (montant [i] < min) alors
{
min ← montant[i]
}
sinon si (montant [i] > max) alors
{
max ← montant[i]
}
}
moy ← som/12
afficher " La somme mensuelle moyenne reçue:", moy
afficher " Le montant minimal reçu sur l'année:", min
afficher " Le montant maximal reçu sur l'année: ", max
Fin
220

Exercice 5.9
Algorithme exercice59
Variables
compte : tableau[21] de réels
i: entier
Debut
compte[0] ←1000
pour i allant de 1 à 20 faire
{
compte[i] ← compte[i] * 1.0225
afficher compte[i]
}
Fin

Exercice 5.10
Algorithme exercice510
Variables
tab : tableau[] d’entiers
nbPos, nbNeg, i, taille : entier
Debut
nbPos ←0
nbNeg ←0
afficher "Entrez le nombre de valeurs :"
lire taille
pour i allant de 0 à taille-1 faire
{
affiher "Entrez le nombre no ", i
lire tab[i]
si (tab[i] < 0) alors
{
nbNeg ← nbNeg + 1
}
sinon
{
nbPos ← nbPos + 1
}
}
afficher " Le nombre de valeurs positives est:", nbPos
afficher " Le nombre de valeurs négatives est:", nbNeg
Fin

Exercice 5.11
Algorithme exercice511
Variables
tab : tableau[] d’entiers
i, som : entier
Debut
221

som ←0
afficher "Entrez le nombre de valeurs :"
lire taille
pour i allant de 0 à taille-1 faire
{
affiher "Entrez le nombre no ", i
lire tab[i]
som ← som + tab[i]
}
afficher " La somme des éléments du tableau est:", som
Fin

Exercice 5.12
Algorithme exercice512
Variables
note : tableau[] d’entiers
n, i, som, nbSup : entier
moy : réel
Debut
som ←0
afficher "Entrez le nombre de notes à saisir : "
lire n
pour i allant de 0 à n-1 faire
{
afficher "Entrez la note n° ", i
lire note[i]
som ← som + note[i]
}
moy ← som / n
nbSup ←0
pour i allant de 0 à n-1 faire
{
si ( note[i] >moy) alors
nbSup ← nbSup + 1
}
afficher nbSup, " étudiants dépassent la moyenne de la promotion"
Fin

Exercice 5.13
Algorithme exercice513
Variables
tab : tableau[] d’entiers
i, n, min, max : entier
Debut
min ← 10000
max ← -10000
afficher "Entrez le nombre de valeurs :"
lire n
pour i allant de 0 à n-1 faire
222

{
affiher "Entrez le nombre no ", i
lire tab[i]
si (tab[i] < min) alors
min ← tab[i]
sinon si (tab[i] > max) alors
{
max ← tab[i]
}

}
afficher " La différence est:", max - min
Fin

Exercice 5.14
Algorithme exercice514
Variables
tab : tableau[] d’entiers
i, n, temp: entier
Debut
afficher "Entrez le nombre de valeurs :"
lire n
pour i allant de 0 à n-1 faire
{
affiher "Entrez le nombre no ", i
lire tab[i]
}
pour i allant de 0 à (n-1)/2 faire
{
temp ← tab[i]
tab[i] ← tab[n-1-i]
tab[n-1-i] ← tab[i]
}
Fin

Exercice 5.15
Algorithme exercice515
Variables
tab : tableau[] d’entiers
i, n, r: entier
Debut
afficher "Entrez le nombre de valeurs :"
lire n
pour i allant de 0 à n-1 faire
{
affiher "Entrez le nombre no ", i
lire tab[i]
}
afficher "Rang de la valeur à supprimer ?"
lire r
223

pour i allant de s à n-2 faire


tab[i] ← tab[i+1]
Fin

Exercice 5.16
Algorithme exercice516
Variables
tab : tableau[][] d’entiers

i, j, trace : entier

Debut
trace ← 0
afficher "Entrez l’ordre de la matrice :"
lire n
pour i ← 0 à n-1 faire
{
pour j ← 0 à n-1 faire
{
lire tab[i][j]
}
trace ← trace + tab[i][i]
}
afficher "La trace de la matrice est: ", trace
Fin

Exercice 5.17
Algorithme exercice517
Variables
tab : tableau[10][6] d’entiers

i, j, iMax, jMax : entier

Debut
iMax ← 0
jMax ← 0
pour i ← 0 à 9 faire
{
pour j ← 0 à 5 faire
{
lire tab[i][j]
}
}
pour i ← 0 à 9 faire
{
pour j ← 0 à 5 faire
{
si (tab[i][j] > tab[iMax][jMax]) alors
{
iMax ← i
jMax ← j
}
}
}
224

afficher "Le plus grand élément est ", > tab[iMax][jMax]


afficher "Il se trouve aux indices ", iMax, "; ", jMax
Fin

Exercice 5.18
Algorithme exercice518
Variables
x, y : tableau[] d’entiers

a : tableau[][] d’entiers

i, j, m, n, k : entier

Debut
afficher "Entrez le nombre des lignes de la matrice :"
lire m
afficher "Entrez le nombre des colonnes de la matrice :"
lire n
afficher "Entrez la taille du vecteur :"
lire k
si (k <> n) alors
{
afficher "Produit impossible"
}
sinon
{
afficher "Lecture des éléments de la matrice, ligne par ligne"
pour i ← 0 à m-1 faire
{
pour j ← 0 à n-1 faire
{
lire a[i][j]
}
}
afficher "Lecture des éléments du vecteur"
pour j ← 0 à n-1 faire
{
lire x[j]
}
// Calcul
pour i ← 0 à m-1 faire
{
y[i] ← 0
pour j ← 0 à n-1 faire
{
y[i] ← y[i] + a[i][j] * x[j]
}
afficher y[i]
}
}
Fin
225

Exercice 5.19
Soient deux matrices 𝐴 = (𝑎𝑖𝑘 )𝑖=1,..,𝑛:𝑘=1,…,𝑞 et 𝐵 = (𝑏)𝑘=1,..,𝑘:𝑗=1,…,𝑝 . Les éléments de
la matrice produit C = A*B sont définis comme suit :
𝑐𝑖𝑗 = ∑𝑞𝑘=1 𝑎𝑖𝑘 𝑏𝑘𝑗 pour i=1, …, n et j=1, …,p

Algorithme exercice519
Variables
A : tableau[n][q] de réels

B : tableau[q][p] de réels

C : tableau[n][p] de réels

i, j, k, n, p, q: entier

Debut
afficher "Entrez le nombre des lignes de la matrice A :"
lire n
afficher "Entrez le nombre des colonnes de la matrice A:"
lire q
afficher "Entrez le nombre des colonnes de la matrice B:"
lire p
afficher "Lecture des éléments de la matrice A, ligne par ligne"
pour i ← 0 à n-1 faire
{
pour k ← 0 à q-1 faire
{
lire a[i][k]
}
}
afficher "Lecture des éléments de la matrice B, ligne par ligne"
pour k ← 0 à q-1 faire
{
pour j ← 0 à p-1 faire
{
lire b[k][j]
}
}
// Calcul des éléments de la matrice C
pour i ← 0 à n-1 faire
{
pour j ← 0 à p-1 faire
{
c[i][j]← 0
pour k ← 0 à q-1 faire
{
c[i][j] ← c[i][j] + a[i][k] * b[k][j]
}
}
}
Fin
226

Exercice 5.20
Pour résoudre ce problème, nous considérons deux tableaux de chaines et de réels
respectivement. Les structures des tableaux se présentent comme suit :

Nom étudiant Admissibilité Cours1 Cours2 Moyenne

Algorithme exercice520
Variables
etudiant : tableau[n][2] de chaines

note : tableau[n][m] de réels

i, j, k, m, n: entier

som, moy: réel

Debut
afficher "Entrez le nombre d’étudiants :"
lire n
afficher "Entrez le nombre des cours:"
lire k
m ← k+1
pour i ← 0 à n-1 faire
{
som ← 0
afficher "Introduire les informations de l’étudiant no ", i+1
afficher "Quel est le nom "
lire etudiant[i][0]
pour j ← 0 à k-1 faire
{
afficher "Note no ", j
lire note[i][k]
som ← som+ note[i][k]
}
note[i][m-1] ← som/k
}
// Calcul de l’admissibilité
pour i ← 0 à n-1 faire
{
si (note[i][m-1] >= 16) alors
etudiant[i][1] ← "Très bien"
sinon si (note[i][m-1] >= 14) alors
etudiant[i][1] ← "Bien"
sinon si (note[i][m-1] >= 12) alors
etudiant[i][1] ← "Assez bien"
sinon si (note[i][m-1] >= 10) alors
etudiant[i][1] ← " Passable"
227

sinon
etudiant[i][1] ← "Non admis"
}
//Affichage
pour i ← 0 à n-1 faire
{
afficher etudiant[i][0], etudiant[i][1]
}
Fin

Chapitre 6
Exercice 6.1

fonction somme(a: entier, b : entier) : entier


Debut
retourne a+b
Fin

Algorithme d’utilisation

Algorithme exercice61
Variables
x, y, som : entier
Debut
afficher ("Entrez deux entiers :")
lire(x)
lire(y)
som ← somme(x,y)
afficher (x, "+", y, "=", som)
Fin

Exercice 6.2

Il faudra faire attention au petit piège. Le fait que 1 mile = 1,609 km) implique qu’il
faut diviser le nombre de kilomètres par 1, 609 pour obtenir le nombre de miles.
fonction kilometreVersMile(km : réel) : réel
Debut
retourne km/1.6.9
Fin
228

Exercice 6.3

fonction FahrenheitVersCentigrade(f : réel) : réel


Debut
retourne 5/9*(f-32)
Fin

Exercice 6.4

4
Étant donné le rayon r, le volume d’une sphère est donné par 𝑣 = 3 𝜋𝑟 3 .

fonction volumeSphere(r : réel) : réel


Constantes
pi= 3.14159
Debut
retourne 4/3*pi*(r^3)
Fin

Exercice 6.5

Ici, éviter à tout prix d’écrire en dur 35 et 150 dans le code. Utiliser des constantes
pour pouvoir plus facilement modifier le programme (les lois et les taux peuvent changer).
fonction salaireHebdomadaire (nbHeure : entier, salaireHoraire : réel) : réel
Constantes
dureeLegale= 35
tauxHeureSup=150
Variables
res : réel
Debut
si (nbHeure < dureeLegale) alors
{
res ← nbHeure* salaireHoraire
} sinon
{
res ← (dureeLegale + (nbHeure – dureeLegale)*( tauxHeureSup/100))*
salaireHoraire
}
retourne res
Fin

Exercice 6.6

fonction nombreVoyelle() : vide


Variables
phrase: chaine
i, nb: entier
Debut
229

afficher("Entrez une phrase:")


lire(phrase)
nb ← 0
pour i ← 1 à longueur(phrase) faire
{
si (milieu(phrase,i,1)= ‘a’ ou milieu(phrase,i,1)= ‘e’ ou milieu(phrase,i,1)= ‘i’ ou
milieu(phrase,i,1)= ‘o’ ou milieu(phrase,i,1)= ‘u’ ou milieu(phrase,i,1)= ‘y’) alors
nb ← nb + 1
}
afficher("Cette phrase compte ", nb, " voyelles")
Fin

Exercice 6.7

fonction apparitionVoyelle() : vide


Variables
voyelle : tableau[1..6] ← {‘a’,’e’,’i’,’o’,’u’,’y’} de caractères
nbvoy : tableau ← {0,0,0,0,0,0} d’entiers
phrase: chaine
i, j: entier
Debut
afficher("Entrez une phrase:")
lire(phrase)
pour i ← 1 à longueur(phrase) faire
{
pour j ← 0 à 5 faire
{
si (milieu(phrase,i,1)= voyelle[j]) alors
{
nbvoy[j] ← nbvoy[j] + 1
}
}
}
pour j ← 0 à 5 faire
{
afficher(nbvoy[j], " la voyelle ", voyelle[j])
}
Fin

Exercice 6.8

Là, on est obligé de compter par une boucle le nombre d'espaces de la phrase, et on en
déduit le nombre de mots. La boucle examine les caractères de la phrase un par un, du premier
au dernier, et les compare à l'espace.

fonction nombreMots() : vide


Variables
phrase: chaine
i, nb: entier
230

Debut
afficher("Entrez une phrase:")
lire(phrase)
nb ← 0
pour i ← 1 à longueur(phrase) faire
{
si (milieu(phrase,i,1)= " ") alors
nb ← nb + 1
}
afficher("Cette phrase compte", nb+1, " mots")
Fin

Exercice 6.9

fonction supprimerCaratere() : vide


Variables
phrase: chaine
nb: entier
Debut
afficher("Entrez une phrase:")
lire(phrase)
afficher("Entrez le rang du caractère à supprimer:")
lire(nb)
phrase ← suppr(phrase , nb, 1)
afficher("La nouvelle phrase est ", phrase)
Fin

Exercice 6.10

fonction note(bonneRep : entier) : caractère


Variables
res : caractère
Debut
si (bonneRep <= 10) alors
{
res ← ‘E’
} sinon si (bonneRep <= 20) alors
{

res ← ‘D’
} sinon si (bonneRep <= 30) alors
{
res ← ‘C’
} sinon si (bonneRep <= 40) alors
{
res ← ‘B’
} sinon
{
res ← ‘A’
}
retourne res
231

Fin

Exercice 6.11

Une année est bissextile si


 elle est divisible par 4,
 elle est divisible par 400 et non par 100.

fonction bissextile (annee : entier) : booléen


Debut
retourne (annee MOD 4 = 0) et ((annee MOD 400 = 0) ou (annee MOD 100) > 0))
Fin

Exercice 6.12

fonction nbJoursMois (mois : entier, annee : entier) : entier


Variables
nbJour : entier
Debut
suivant_que mois faire
{
1 : 3 : 5 : 7 : 8 : 10 : 12 :
nbJour ←31
4 : 6 : 9 : 11 :
nbJour ←30
2:{
si (bissextile (annee) ) alors
nbJour ←29
sinon
nbJour ←28
}
}
retourne nbJour
Fin

Exercice 6.13

Pour cet exercice, il y a une règle générale : pour chaque lettre, on détecte sa position
dans l'alphabet, et on la remplace par la lettre occupant la position suivante. Seul cas
particulier, la vingt-sixième lettre (le Z) doit être codée par la première (le A), et non par la
vingt-septième, qui n'existe pas !

fonction cryptographie1() : vide


232

Variables
alpha, bla, cod: chaine
x : caractère
i, pos: entier
Debut
afficher("Entrez la phrase à coder en majuscule:")
lire(bla)
alpha ← "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
cod ← ""
pour i ← 0 à longueur(bla) faire
{
x ← milieu(bla,i,1)
si (x <> "Z") alors
{
pos← trouve(alpha, x)
cod ← cod&milieu(alpha,pos+1,1)
} sinon
cod ← cod&"A"
}
bla ← cod
afficher("La phrase codée est ", bla)
Fin

Exercice 6.14

Cette procédure est une généralisation du précédent. Mais là, comme on ne connaît pas
d'avance le décalage à appliquer, on ne sait pas a priori combien de "cas particuliers", à savoir
de dépassements au-delà du Z, il va y avoir.

Il faut donc trouver un moyen simple de dire que si on obtient 27, il faut en réalité
prendre la lettre numéro 1 de l'alphabet, que si on obtient 28, il faut en réalité prendre la
numéro 2, etc. Ce moyen simple existe : il faut considérer le reste de la division par 26,
autrement dit le modulo.

Il y a une petite ruse supplémentaire à appliquer, puisque 26 doit rester 26 et ne pas


devenir 0.

fonction cryptographie2() : vide


Variables
alpha, bla, cod: chaine
x : caractère
i, pos, nouvPos, decal: entier
Debut
afficher("Entrez le décalage à appliquer:")
lire(decal)
afficher("Entrez la phrase à coder en majuscule:")
lire(bla)
alpha ← "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
233

cod ← ""
pour i ← 0 à longueur(bla) faire
{
x ← milieu(bla,i,1)
pos ← trouve(alpha, x)
nouvPos ← (pos+decal) MOD 26

si (nouvPos = 0) alors
{
nouvPos ← 26
}
cod ← cod&milieu(alpha,nouvPos,1)
}
bla ← cod
afficher("La phrase codée est ", bla)
Fin

Exercice 6.15

fonction cryptographie3() : vide


Variables
alpha, bla, cod, cle: chaine
x : caractère
i, pos: entier
Debut
afficher("Entrez l’alphabet clé:")
lire(cle)
afficher("Entrez la phrase à coder en majuscule:")
lire(bla)
alpha ← "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
cod ← ""
pour i ← 0 à longueur(bla) faire
{
x ← milieu(bla,i,1)
pos ← trouve(alpha, x)
cod ← cod&milieu(cle,pos,1)
}
bla ← cod
afficher("La phrase codée est ", bla)
Fin

Exercice 6.16

Avant toute chose, définissons d’abord une fonction qui permet de retourner un verbe
régulier du premier groupe.
fonction lireVerbe() : chaine
Variables
verbe, termi : chaine
Début
234

afficher ("Entrez un verbe régulier du premier groupe ")


lire(verbe)
termi ← gauche(verbe, 2)
tant_que ( termi <>"er") faire
{
afficher ("*** il ne se termine pas par er - donnez-en un autre : ")
lire verbe
termi ← gauche(verbe, 2)
}
retourne verbe
Fin

La procédure de conjugaison proprement dite se définie comme suit :

fonction conjugaison() : vide


Variables
verbe: chaine
long: entier
Debut
verbe ← lireVerbe()
afficher("Conjugaison au présent du verbe ", verbe)
long ← longueur(verbe)
verbe ← milieu(verbe,1,long-2)
afficher("je " & verbe &"e")
afficher("tu " & verbe &"es")
afficher("il/elle " & verbe &"e")
afficher("nous " & verbe &"ons")
afficher("vous " & verbe &"ez")
afficher("ils/elles " & verbe &"ent")
Fin

Exercice 6.17

fonction pgcd(a : entier, b : entier) : entier


Variables
f : entier
Debut
si (b = 0) alors
{
retourne a
} sinon
retourne pgcd(b, a MOD b) // La fonction s’appelle elle-même
Fin

Exercice 6.18

fonction ppdp(n : entier) : entier


Variables
d : entier
Debut
235

si ((n MOD 2) = 0) alors


{
retourne 2
}
pour d← 3 à (d*d <= n) et (n MOD d <> 0) Pas 2 faire
{
/* on ne fait toujours rien */
}
si ((n MOD 2) = 0) alors
{
retourne d
} sinon
{
retourne d
}
Fin

Exercice 6.19

fonction suiteBizarre(n : entier) : réel


Variables
i : entier
u : réel
Debut
u ← 1/3
pour i ← 0 à n-1 faire
{
u ← (4*u/3) - 1
}
retourne u
Fin

Exercice 6.20

fonction fibonacci(n : entier, a : entier, b : entier) : entier


Debut
suivant_que n faire
{
0:
retourne a
1:
retourne b
defaut :
retourne fibonacci(n-1, a , b) +fibonacci(n-2, a, b)
Fin

Chapitre 7
Exercice 7.1
236

Cet algorithme écrit l'intégralité du fichier "exemple.txt" à l'écran.

Exercice 7.2
Algorithme exercice72
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
i : entier
Debut
nomF ← "exemple.txt"
ouvrir nomF dans fic pour lecture
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
pour i ← 1 à longueur(ligne) faire
{
si (milieu(ligne,i,1)= "/") alors
afficher("/")
sinon
afficher(milieu(ligne,i,1))
}
}
fermer fic
Fin

Exercice 7.3
Algorithme exercice73
Variables
fic : fichier séquentiel
nom: chaîne de 20 caractères
prenom: chaîne de 15 caractères
tel: chaîne de 10 caractères
email: chaîne de 20 caractères
nomF, ligne : chaîne
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour ajout
afficher("Entrez le nom :")
lire nom
afficher("Entrez le prénom :")
lire prenom
afficher("Entrez le numéro de téléphone :")
lire tel
afficher("Entrez l’adresse e-mail :")
lire email
ligne ← nom&prenom&tel&email
ecrireFichier(fic, ligne)
fermer fic
237

Fin

Exercice 7.4
Algorithme exercice74
Variables
fic : fichier séquentiel
nom: chaîne de 20 caractères
prenom: chaîne de 15 caractères
age: entier
tel: chaîne de 10 caractères
nomF, ligne, choix : chaîne
Debut
nomF ← "repertoire.txt"
ouvrir nomF dans fic pour ajout
choix ← "O"
faire
{
afficher("Entrez le nom :")
lire nom
afficher("Entrez le prénom :")
lire prenom
afficher("Entrez l’âge :")
lire age
afficher("Entrez le numéro de téléphone :")
lire tel
ligne ← nom&prenom& numch(age)& tel
ecrireFichier(fic, ligne)
lire choix
} tant_que (choix <> "N")
fermer fic
Fin

Exercice 7.5
Algorithme exercice75
Variables
fic : fichier séquentiel
nom, nomF, ligne: chaîne
Debut
nomF ← "repertoire.txt"
ouvrir nomF dans fic pour lecture
afficher("Quel est le nom de la personne recherchée ?")
lire nom
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
si (milieu(ligne,1,20)=nom) alors
{
afficher(ligne)
238

}
}
fermer fic
Fin

Exercice 7.6
Nous considérons les tailles suivantes :
 6 caractères pour le matricule
 20 caractères pour le nom et
 4 caractères pour le nbHP (nombre d’heures prestées)

Algorithme exercice76
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
matricule, nom : chaine
nbHP : entier
Debut
nomF ← "exemple.txt"
ouvrir nomF dans fic pour lecture
afficher("Matricule ", "Nom de l’employé ", "Nombre d’heures prestées")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
matricule ← milieu(ligne,1,6)
nom ← milieu(ligne,7,20)
nbHP ← chnum(milieu(ligne,27,4))
afficher(matricule, nom, nbHP)
}
fermer fic
Fin

Exercice 7.7
Soit nbTHP la variable entière qui indique le nombre total d’heures prestées. On peut
juste introduire l’instruction suivante dans la solution de l’exercice 7.6 et afficher nbTHP:
nbHPP ← nbHPP + nbHP

Exercice 7.8

Nous considérons les tailles suivantes :


 6 caractères pour le no client
 6 caractères pour le code article
 4 caractères pour la quantité et
 8 caractères pour le prix unitaire
239

Algorithme exercice78
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
noClient, codeArt: chaine
qte, nbCl : entier
prixU, prixA, montantT : réel
Debut
nomF ← "client.txt"
ouvrir nomF dans fic pour lecture
afficher("No client ", "Quantité ", "Prix unitaire ", "Prix toital")
nbCl ← 0
montantT ← 0.0
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
nbCl ← nbCl +1
noClient ← milieu(ligne,1,6)
codeArt ← milieu(ligne,7,6)
qte ← chnum(milieu(ligne,52,4))
prixU ← chnum(milieu(ligne,56,4))
prixT ← prixU*qte
montantT ← montantT + prixT
afficher(noClient, qte, prixU, prixT)
}
afficher("Le nombre total de clients est ", nbCl)
afficher("Le montant total de clients est ", montantT)
fermer fic
Fin

Exercice 7.9
a)

Algorithme exercice79a
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
matricule, nom: chaine
codeSexe : caractère
montant : entier
Debut
nomF ← "personnel.txt"
ouvrir nomF dans fic pour lecture
afficher("Nom ", "Montant")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
matricule ← milieu(ligne,1,6)
nom ← milieu(ligne,7,20)
codeSexe ← milieu(ligne,27,1)
240

montant ← chnum(milieu(ligne,28,4))
si (codeSexe = ‘F’) alors
afficher(nom, montant)
}
fermer fic
Fin

b) si (montant > = 1000) alors


afficher(nom)
c) si ((codeSexe = ‘M’) et (montant < 1500)) alors

afficher(matricule)
d) si (((codeSexe = ‘M’) et (montant >1000)) ou ((codeSexe = ‘F’) et (montant < 2500))) alors

afficher(matricule)

Exercice 7.10
a)

Algorithme exercice710a
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
matricule, nom: chaine
codeSexe : caractère
nbH, salaireBr : entier
Debut
nomF ← "agent.txt"
ouvrir nomF dans fic pour lecture
afficher("Matricule ", "Nom ", "Salaire brut")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
matricule ← milieu(ligne,1,6)
nom ← milieu(ligne,7,20)
codeSexe ← milieu(ligne,27,1)
nbH ← chnum(milieu(ligne,28,4))
si (codeSexe = ‘F’) alors
{
salaireBr ← 50*nbH
afficher(matricule, nom, salaireBr)
}
}
fermer fic
Fin

b) si( (codeSexe = ‘H’) et (nbH > 20)) alors


{
salaireBr ← 60*nbH
afficher(matricule, nom, salaireBr)
}
241

c) si( (codeSexe = ‘F’) alors


salaireBr ← 50*nbH
sinon
salaireBr ← 60*nbH

afficher(matricule, nom, salaireBr)

d) salaireH ← 40
si (codeSexe = ‘H’) alors
{
si (nbH > 20) alors
{

salaireH ← 60
tauxImpot ← 0.2
} sinon
{
si (nbH > 10) alors
{

salaireH ← 50

tauxImpot ← 0.1
}

salaireBr ← salaireH *nbH

brutImpot ← tauxImpot* salaireBr

salaireNet ← salaireBr - brutImpot

afficher(matricule, nom, nbH, salaireH , salaireBr, brutImpot, salaireNet)

Exercice 7.11
Algorithme exercice711
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
codeArt, libelleArt: chaine
stockD, stockF, achatJ, venteJ, stockS : entier
Debut
nomF ← "article.txt"
ouvrir nomF dans fic pour lecture
afficher("Code article ", "Stock fin de journée ", "Astérisque")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
codeArt ← milieu(ligne,1,6)
242

libelleArt ← milieu(ligne,7,20)
stockD ← chnum(milieu(ligne,27,4))
achatJ ← chnum(milieu(ligne,31,4))
venteJ ← chnum(milieu(ligne,35,4))
stockS ← chnum(milieu(ligne,39,4))
stockF ← stockD + achatJ - venteJ
si (stockF < stockS) alors
{
afficher(codeArt, stockF, "*")
} sinon
afficher(codeArt, stockF, " "))
}
fermer fic
Fin

Exercice 7.12
Algorithme exercice712
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
matricule, nom : chaine
nbEt, taille, poids: entier
sommeTaille, sommePoids: entier
Debut
nbEt ← 0
sommeTaille ← 0
sommePoids ← 0
nomF ← "etudiant.txt"
ouvrir nomF dans fic pour lecture
afficher("Matricule ", "Nom ", "Taille ", "Poids")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
matricule ← milieu(ligne,1,6)
nom ← milieu(ligne,7,20)
taille ← chnum(milieu(ligne,27,4))
poids ← chnum(milieu(ligne,31,4))
afficher(matricule, nom, taille, poids)
nbEt ← nbEt + 1
sommeTaille ← sommeTaille + taille
sommePoids ← sommePoids + poids
}
afficher("La taille moyenne est ", sommeTaille/nbEt )
afficher("Le poids moyen est ", sommePoids/nbEt )
fermer fic
Fin

Exercice 7.13
Algorithme exercice713
Constantes
243

tauxNor = 15
tauxSup = 5
tauxNut = 20
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
matricule, nom, typeH: chaine
nbEnrNor, nbEnrSup, nbEnrNut ← 0: entier
nbHNor, nbHSup, nbHNut ← 0: entier
montantNor, montantSup, montantNut ← 0: entier
nbH, montantTot : entier
Debut
nomF ← "paie.txt"
ouvrir nomF dans fic pour lecture
afficher("Type-hres ", " Nbre enregistrements ", " Nbre tot hres ", " Taux ", " Montant ")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
matricule ← milieu(ligne,1,6)
nom ← milieu(ligne,7,20)
typeH ← milieu(ligne,27,3)
nbH ← chnum(milieu(ligne,30,4))
si (typeH = "nor") alors
{
nbEnrNor ← nbEnrNor + 1
nbHNor ← nbHNor + nbH
} sinon si (typeH = "sup") alors
{
nbEnrSup ← nbEnrSup + 1
nbHSup ← nbHSup + nbH
} sinon
{
nbEnrNut ← nbEnrNut + 1
nbHNut ← nbHNut + nbH
}
}
montantNor ← nbHNor* tauxNor
afficher(nor, nbEnrNor, nbHNor, tauxNor, montantNor)
montantSup ← nbHSup* tauxSup
afficher(sup, nbEnrSup, nbHSup, tauxSup, montantSup)
montantNut ← nbHNut* tauxNut
afficher(nut, nbEnrNut, nbHNut, tauxNut, montantNut)
montantT ← montantSup + montantSup + montantNut
afficher("Le montant total est ", montantT)
fermer fic
Fin

Exercice 7.14
Algorithme exercice714
Variables
244

fic : fichier séquentiel


nomF, ligne : chaîne
matricule, nom, grade: chaine
nbAgent, salaireB, salaireBrut, prime: entier
tauxI, salaireNet, impot : réel
totalBase, totalPrime, totalBrut, totalNet ← 0.0: réel
Debut
nbAgent ← 0
nomF ← "agent.txt"
ouvrir nomF dans fic pour lecture
afficher("Matricule ", "Grade", "Salaire base", "Prime", "Salaire brut", "Impôt", "Salaire
net")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
matricule ← milieu(ligne,1,6)
nom ← milieu(ligne,7,20)
grade ← milieu(ligne,27,10)
salaireB ← chnum(milieu(ligne,37,4))
prime ← chnum(milieu(ligne,41,4))
nbAgent ← nbAgent + 1
totalBase ← totalBase + salaireB
totalPrime ← totalPrime + prime
salaireBrut ← salaireBrut + prime
totalBrut ← totalBrut + salaireBrut
si (salaireB < 1000) alors
tauxI ← 0.10
sinon si (salaireB < 2500) alors
tauxI ← 0.15
sinon si (salaireB < 5000) alors
tauxI ← 0.30
sinon
tauxI ← 0.50
impot ← salaireB * tauxI
totalImpot ← totalImpot + impot
salaireNet ← salaireBrut – impot
totalNet ← totalNet+ salaireNet
afficher(matricule, grade, salaireB, prime, salaireBrut, impot, salaireNet)
}
afficher("Nombre total d’agents : ", nbAgent)
afficher("Montant total de salaire de base : ", totalBase)
afficher("Primes", totalPrime)
afficher("Montant total de salaire brut", totalBrut)
afficher("Impôts : ", totalImpot)
afficher("Montant total de salaire net", totalNet)
fermer fic
Fin

Exercice 7.15
245

Là, comme indiqué dans le cours, nous passons par un tableau en mémoire vive, ce qui
est la technique la plus fréquemment employée. Le tri - qui est en fait un simple test - sera
effectué sur le premier champ (nom).

On recopie l'intégralité du fichier "adresse.txt" dans le tableau adresse. Et après tout,


c'est l'occasion : quand on tombe au bon endroit, on insère subtilement notre nouveau copain
dans le tableau.
Algorithme exercice715
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
adresse : tableau[1..100] [1..4] de chaînes
nom: chaîne de 20 caractères
prenom: chaîne de 15 caractères
tel: chaîne de 10 caractères
email: chaîne de 20 caractères
i, j : entier
insere: booléen
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour lecture
afficher("Entrez le nom :")
lire nom
afficher("Entrez le prénom :")
lire prenom
afficher("Entrez le numéro de téléphone :")
lire tel
afficher("Entrez l’adresse e-mail :")
lire email
i ← -1
insere ← faux
// Recopie du fichier dans un tableau et insertion
tant_que (non eof(fic)) faire
{
i ← i+1
lireFichier(fic, ligne)
adresse[i][0] ← milieu(ligne,1,20)
adresse[i][1] ← milieu(ligne,21,15)
adresse[i][2] ← milieu(ligne,36,10)
adresse[i][3] ← milieu(ligne,46,20)
si ((adresse[i][0] > nom) et (non insere)) alors
{
adresse[i+1][0] ← adresse[i][0]
adresse[i+1][1] ← adresse[i][1]
adresse[i+1][2] ← adresse[i][2]
adresse[i+1][3] ← adresse[i][3]
246

adresse[i][0] ← nom
adresse[i][1] ← prenom
adresse[i][2] ← tel
adresse[i][3] ← email
insere ← vrai
i ← i+1
}
}
fermer fic
// Recopie du tableau dans un fichier
ouvrir nomF dans fic pour écriture
pour j ← 0 à i faire
{
ligne ← adresse[j][0]& adresse[j][1]& adresse[j][2]& adresse[j][3]
ecrireFichier(fic, ligne)
}
fermer fic
Fin

Exercice 7.16
C'est un peu la même chose que ce que nous venions de faire, à quelques variantes
près. Il y a essentiellement une petite gestion de flag pour faire bonne mesure.

Algorithme exercice716
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
adresse : tableau[1..100] [1..4] de chaînes
nom, nouvauNom: chaîne de 20 caractères
prenom: chaîne de 15 caractères
tel: chaîne de 10 caractères
email: chaîne de 20 caractères
i, j : entier
trouve: booléen
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour lecture
afficher("Entrez le nom à modifier:")
lire nom
afficher("Entrez le nouveau nom :")
lire nouveauNom
i ← -1
trouve ← faux
// Recopie du fichier dans un tableau et modification possible
tant_que (non eof(fic)) faire
{
i ← i+1
lireFichier(fic, ligne)
adresse[i][0] ← milieu(ligne,1,20)
247

adresse[i][1] ← milieu(ligne,21,15)
adresse[i][2] ← milieu(ligne,36,10)
adresse[i][3] ← milieu(ligne,46,20)
si (adresse[i][0]=nom) alors
{
adresse[i][0] ← nouveauNom
trouve ← vrai
}
}
fermer fic
// Recopie du tableau dans un fichier
ouvrir nomF dans fic pour écriture
pour j ← 0 à i faire
{
ligne ← adresse[j][0]& adresse[j][1]& adresse[j][2]& adresse[j][3]
ecrireFichier(fic, ligne)
}
// Et un petit message pour finir !

si trouve alors
afficher( "Modification effectuée")
sinon
afficher("Nom inconnu. Aucune modification effectuée")
fermer fic
Fin

Exercice 7.17
Dans un premier, nous recopions l'intégralité du fichier "adresse.txt" dans le tableau. Le
tableau est trié sur la colonne nom en utilisation un tri par insertion (cfr 5.3.2). Le nouveau tableau trié
est ensuite recopié dans le fichier "adresse.txt".

Algorithme exercice717
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
adresse : tableau[1..100] [1..4] de chaînes
nom, tempN: chaîne de 20 caractères
prenom, tempP: chaîne de 15 caractères
tel, tempT: chaîne de 10 caractères
email, tempE: chaîne de 20 caractères
i, j, ins : entier
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour lecture
i ← -1
// Recopie du fichier dans un tableau
tant_que (non eof(fic)) faire
{
i ← i+1
lireFichier(fic, ligne)
248

adresse[i][0] ← milieu(ligne,1,20)
adresse[i][1] ← milieu(ligne,21,15)
adresse[i][2] ← milieu(ligne,36,10)
adresse[i][3] ← milieu(ligne,46,20)
}
// Tri par insertion
j←1
tant_que (j < i) faire
{
// décalage vers la gauche de adresse[j][0]: à sa place
tempN ← adresse[j][0]
tempP ← adresse[j][1]
tempT ← adresse[j][2]
tempE ← adresse[j][3]
ins ← j-1
// boucle de recherche du minimum
tant_que ((ins >= 0) et (tempN <= adresse[ins][0])) faire
{
adresse[ins+1][0] ← adresse[ins][0]
ins ← ins-1
}
adresse[ins+1][0] ← tempN
adresse[ins+1][1] ← tempP
adresse[ins+1][2] ← tempT
adresse[ins+1][3] ← tempE
j ← j+1
}
fermer fic
// Recopie du tableau dans un fichier
ouvrir nomF dans fic pour écriture
pour j ← 0 à i faire
{
ligne ← adresse[j][0]& adresse[j][1]& adresse[j][2]& adresse[j][3]
ecrireFichier(fic, ligne)
}
fermer fic
Fin

Exercice 7.18
Ici, nous n’avons pas besoin de passer par des tableaux.
Algorithme exercice718
Variables
Fic, ficF : fichier séquentiel
nomF, nomFF, ligne : chaîne
Debut
nomF ← "adresse3.txt"
ouvrir nomFF dans ficF pour ajout
nomF ← "adresse1.txt"
ouvrir nomF dans fic pour lecture
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
ecrireFichier(ficF, ligne)
}
249

fermer fic
nomF ← "adresse2.txt"
ouvrir nomF dans fic pour lecture
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
ecrireFichier(ficF, ligne)
}
fermer fic
fermer ficF
Fin

Exercice 7.19
Nous allons éliminer les mauvaises entrées dès la recopie : si l'enregistrement ne
présente pas un mail valide, on l'ignore, sinon on le copie dans le tableau.
Algorithme exercice719
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
adresse : tableau[1..100] [1..4] de chaînes
nom, nouvauNom: chaîne de 20 caractères
prenom: chaîne de 15 caractères
tel: chaîne de 10 caractères
email: chaîne de 20 caractères
i, j, nb : entier
Debut
nomF ← "adresse.txt"
ouvrir nomF dans fic pour lecture
i ← -1
// Recopie du fichier dans un tableau et suppression possible
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
nom ← milieu(ligne,1,20)
prenom ← milieu(ligne,21,15)
tel ← milieu(ligne,36,10)
email ← milieu(ligne,46,20)
pour j ← 1 à longueur(adresse[i][3]) faire
{
si (milieu(email, j, 1) = "@") alors
nb ← nb + 1
}
si (nb=1) alors
{
i←i+1
adresse[i][0] ← nom
adresse[i][1] ← prenom
adresse[i][2] ← tel
adresse[i][3] ← email
}
}
250

fermer fic
// Recopie du tableau dans un fichier
ouvrir nomF dans fic pour écriture
pour j ← 0 à i faire
{
ligne ← adresse[j][0]& adresse[j][1]& adresse[j][2]& adresse[j][3]
ecrireFichier(fic, ligne)
}
fermer fic
Fin

Exercice 7.20
Une fois de plus, le passage par un tableau de structures est une stratégie commode.
Attention toutefois, comme il s'agit d'un fichier texte, tout est stocké en caractère. Il faudra
donc convertir en numérique les caractères représentant les ventes, pour pouvoir effectuer les
calculs demandés. Pour le traitement, il y a deux possibilités. Soit on recopie le fichier à
l'identique dans un premier tableau, et on traite ensuite ce tableau pour faire la somme par
vendeur. Soit on fait le traitement directement, dès la lecture du fichier. C'est cette option qui
est choisie dans ce corrigé.

Nous balayons le fichier en faisant nos additions. Dès que le nom a changé (nous
sommes passés au vendeur suivant), nous rangeons le résultat et nous remettons tout à zéro.
Algorithme exercice720
Variables
fic : fichier séquentiel
nomF, ligne : chaîne
nom, nomPrec: chaine
montant, som, vente : entier
Debut
nomF ← "vente.txt"
ouvrir nomF dans fic pour lecture
som ← 0
lireFichier(fic, ligne)
nom ← milieu(ligne,1,20)
nomPrec ← nom
vente ← chnum(milieu(ligne,21,4))
som ← som + vente
afficher("Vendeur ", "Total de ventes")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
nom ← milieu(ligne,1,20)
vente ← chnum(milieu(ligne,21,4))
si (nom=nomPrec) alors
251

{
som ← som + vente
} sinom
{
afficher(nom, som)
nomPrec ← nom
som ← vente
}
}
afficher(nom, som) // Pour le dernier vendeur
fermer fic
Fin

Chapitre 8
Exercice 8.1
Classe Boulangerie{
public principal() : vide
{
h, j : entier
b : booléen
afficher("Saisissez l’heure (entre 0 et 23):")
lire h
afficher("Et le jour (entre 0 et 6):")
lire j
b ← ((h >= 7) et (h <= 13) et (j <> 1)) ou (h >= 16) et (h <= 20) et (j > 1))
si b alors
afficher("La boulangerie est ouverte")
sinon
afficher("La boulangerie est fermée")
}
}

Exercice 8.2
Classe Connexion{
public principal() : vide
{
debut , fin, nbHeures : entier
nbHeuresTarif1, nbHeuresTarif2 : entier
donneesOK : booléen
debut ← lireEntier("Début de la connexion : ")
fin ← lireEntier("Fin de la connexion : ")
donneesOK ← testerDonnees(debut, fin)
si donneesOK alors
{
nbHeures ← fin - debut
nbHeuresTarif1 ← calculerNbHeuresTarif1(debut, fin)
nbHeuresTarif2 ← nbHeures - nbHeuresTarif1
afficherPrix(nbHeuresTarif1, nbHeuresTarif2)
}
}
252

// Demande à l'utilisateur d'entrer un entier.


lireEntier(message : chaine) : entier
{
x : entier
afficher(message)
lire(x)
retourne x
}

// Vérifie si les données entrées sont cohérentes


testerDonnees(debut : entier, fin : entier) : booléen
{
si (debut = fin) alors
{
afficher("Bizarre, vous n'avez pas été connecté du tout ...")
retourne faux
} sinon si (debut > fin) alors
{
afficher("Bizarre, le début est après la fin ...")
retourne faux
} sinon
retourne vrai
}

// Calcule le nombre d'heures passées en tarif 1


calculerNbHeuresTarif1(debut : entier, fin : entier) : entier
{
nb ← 0 : entier
heure : entier
pour heure ← debut à fin-1 faire
{
si ((heure >= 7) et (heure < 17)) alors
{
nb ← nb+1
}
}
retourne nb
}
// Affiche le prix à payer par l'utilisateur
afficherPrix(nbHeuresTarif1 : entier, nbHeuresTarif2 : entier) : vide
{
prix : entier
prix ← nbHeuresTarif1 * 10+ nbHeuresTarif2 * 0.50;
afficher("Vous avez été connecté " , nbHeuresTarif1 + nbHeuresTarif2, " heures
pour " + prix + " dollars");
}
}

Exercice 8.3
253

Classe Factorielle {
public static principal(String)
{
n : entier
recommencer = 'o' : caractère
faire
{
n ← demanderNombre()
afficher("Méthode itérative :")
afficher(n & "! = " & factorielleIterative(n))
afficher("Méthode récursive :")
afficher(n & "! = " & factorielleRecursive(n))
afficher("Voulez-vous recommencer [o/n] ?")
lire(recommencer)
} tant_que (recommencer = 'o');
}
// Demande un entier à l'utilisateur
static demanderNombre() : entier
{
n : entier
faire
{
afficher("Donnez un nombre entier compris entre 0 et 12 (compris)")
lire(n)
} tant_que ((n > 12) ou (n < 0))
retourne n
}
// Calcul de la factorielle par la méthode itérative
static factorielleIterative(nombre : entier) : entier
{
i, fact ← 1: entier
pour i ← 2 à nombre
{
fact ← fact * i
}
retourne fact
}
// Calcul de la factorielle par la méthode récursive
static factorielleRecursive nombre : entier) : entier
{
si (nombre = 0) alors
{
retourne 1
} sinon
{
retourne (nombre * factorielleRecursive(nombre - 1))
}
}
}

Exercice 8.4
254

Voici ce que pourrait être la définition de notre classe Carac :


classe Carac{
car : caractère // pour conserver le caractère

Carac (c : caractère) // constructeur à un paramètre


{
car ← c
}
Carac() // constructeur sans paramètre
{
car ← ’ ’
}
estVoyelle () : booléen
{
ok : booléen
si (car = ’a’ ou car = ’e’ ou car = ’i’ ou car = ’o’ ou car = ’u’ ou car = ’y’) alors
ok ← vrai
sinon
ok ← faux
retourne ok
}
}

Voici un petit programme utilisant cette classe :


Classe Test{
public principal() : vide
{
x ← ’e’ : caractère
c1, c2 : Carac

c1 ← new Carac()
si (c1.estVoyelle()) alors
afficher("voyelle ")
c2 ← new Carac (x) // on fournit la valeur de x (ici ’e’ au constructeur)
si (c2.estVoyelle()) alors
afficher("voyelle ")
}
}

Notez bien que, telle qu’elle a été conçue, nous n’avons aucun moyen de connaître,
après construction, le caractère stocké dans un objet de type Carac. Notamment, ce besoin
pourrait se faire sentir dans les instructions d’écriture précédentes.

Exercice 8.5
Voici ce que pourrait être la définition de notre classe Rectangle :

classe Rectangle{
cote1, cote2 : réel
255

Rectangle()
{
cote1 ← 1.0
cote2 ← 1.0
}
Rectangle (ct : réel)
{
cote1 ← ct
cote2 ← ct
}
Rectangle (ct1 : réel, ct2 : réel)
{
cote1 ← ct1
cote2 ← ct2
}
perimètre() : réel
{
p : réel
p ← 2 * (cote1 + cote2)
retourne p
}
surface() : réel
{
s : réel
s ← cote1 * cote2
retourne s
}
agrandit (coef : réel) : vide
{
cote1 ← cote1 * coef
cote2 ← cote2 * coef
}
}

Voici un petit programme d’utilisation, accompagné des résultats qu’il fournit :

Classe Test{
public principal() : vide
{
r1, r2 : Rectangle

r1 ← new Rectangle()
afficher ("Le premier rectangle a pour surface ", r1.surface ()")
r1.agrandit (2.5)
afficher ("Le premier rectangle a maintenant pour surface ", r1.surface ()")
r2 ← new Rectangle(1.5, 5.0)
afficher ("Le second rectangle a pour surface ", r2.surface ()")
r2.agrandit (10.0)
afficher ("Le premier rectangle a maintenant pour surface ", r2.périmètre()")
}
}

L’exécution donne :
256

Le premier rectangle a pour surface 1.0


Le premier rectangle a maintenant pour surface 6.25
Le second rectangle a pour périmètre 13.0
Le second rectangle a maintenant pour périmètre 130.0

Exercice 8.6
La classe Etudiant est définie comme suit :
Classe Etudiant {
nom : Chaine
admissibilite : {Non admissible, Passable, Assez bien, Bien, Très bien}

Etudiant()
{
nom ← Chaine()
admissibilte ← Chaine()
}
getNom() : Chaine
{
netourne nom
}
admissibiliteExamen(moy: réel) : Chaine
{
adm : Chaine
adm ← new Chaine()
si (moy >= 16) alors
adm ← "Très bien"
sinon si (moy >= 14) alors
adm ← "Bien"
sinon si (moy >= 12) alors
adm ← "Assez bien"
sinon si (moy >= 10) alors
adm ← "Passable"
sinon
adm ← "Non admissible"
retourne adm
}
}

Le programme principal est :


Classe TestAdmissibilite{
// Attributs
fic : fichier séquentiel
nomF, ligne : chaîne
nom , adm: Chaine
note1, note2, note3 : entier
moy : réel
et : Etudiant

et ← new Etudiant()
257

nom ← new Chaine()


adm ← new Chaine()
nomF ← "etudiant.txt"
ouvrir nomF dans fic pour lecture
afficher("Nom de l’étudiant ", "Admissibilité")
tant_que (non eof(fic)) faire
{
lireFichier(fic, ligne)
et.nom ← milieu(ligne,1,20)
note1 ← chnum(milieu(ligne,21,4))
note2 ← chnum(milieu(ligne,25,4))
note3 ← chnum(milieu(ligne,29,4))
moy ← (note1 + note2 + note3)/3
adm ← et.admissibiliteExamen(moy)
afficher(nom, adm)
}
fermer fic
}

Chapitre 9
Exercice 9.1
La classe Abonne ne présente pas de difficultés particulières. Si, comme il est
conseillé, on y encapsule les champs de données, il faut simplement prévoir les méthodes
d’accès correspondantes :
classe Abonne{
privé nom, numero: Chaine
public Abonne (nom: Chaine, numero Chaine)
{
this.nom ← nom
this.numero ← numero
}
public getNom(): Chaine
{
retourne nom
}
public getNumero(): Chaine
{
retourne numero
}
}

En ce qui concerne la classe Repertoire, nous pouvons nous permettre, dans la


méthode getAbonne, de fournir en résultat une copie de la référence à l’abonné correspondant.

Dans la méthode getAbonnesTries, nous faisons porter le tri sur une copie du tableau
des références aux différents abonnés, afin de ne pas modifier l’ordre initial du répertoire.
Voici ce que pourrait être la définition de notre classe Repertoire :
258

classe Repertoire{

public Repertoire (nMax : entier)


{
this.nMax ← nMax
rep ← new Abonne[nMax]
nAbon ← 0
}
public addAbonne (a: Abonne): booléen
{
si (nAbon >= nMax) alors
retourne faux
rep[nAbon] ← a
nAbon ← nAbon + 1
retourne vrai
}
public getNAbonnes(): entire
{
retourne nAbon
}
public getAbonne (num: entier) : Abonne
{
si (num < nAbon) alors
retourne rep[num]
sinon
retourne null
}
public getNumero(nom: Chaine): Chaine
{
i: entier
pour i ← 0 à nAbon faire
{
si (nom.equals(rep[i].getNom())) alors
retourne rep[i].getNumero()
sinon
retourne null
}
public getAbonnesTries() : Abonne[]
{
i, j: entier
privé nMax, nAbon: entier
privé repTrie : tableau[] d’Abonnes
temp : Abonne

pour i ← 0 à nAbon-1 faire


{
repTrie[i] ← rep[i]
}
pour i ← 0 à nAbon-2 faire
{
pour j ← i+1 à nAbon-1 faire
{
si ((repTrie[j].getNom()) < (repTrie[i].getNom()) alors
{
259

temp ← repTrie[i]
repTrie[i] ← repTrie[j]
repTrie[j] ← temp
}
}
}
retourne repTrie
}
}

Voici un petit programme de test, accompagné de ses résultats :

public classe TestRep{


public static principal(): vide
{
i: entire
rep: Repertoire
a, b: Abonne
abonnes : tableau[] d’Abonnes
rep ← new Repertoire(10)
afficher("iI y a " & rep.getNAbonnes () & " abonnes")
a ← new Abonne("Donel", "0818899608")
b ← new Abonne("Amel", "0842578483")
rep.addAbonne (a)
rep.addAbonne (b)
rep.addAbonne(new Abonne("Grael", "0901485690"))
rep.addAbonne(new Abonne("Coel", "0818955623"))
rep.addAbonne(new Abonne("Anael", "0878955623"))
afficher("Il y a " & rep.getNAbonnes () & " abonnes")
afficher("qui sont : ")
pour i ← 0 à rep.getNAbonnes()-1 faire
{
afficher(rep.getAbonne(i).getNom() & " " & rep.getAbonne(i).getNumero())
}
afficher("ou encore, par ordre alphabétique")
abonnes ← rep.getAbonnesTries ()
pour i ← 0 à abonnes.longueur()-1 faire
{
afficher(abonnes[i].getNom() & " " & abonnes[i].getNumero())
}
}

Il y a 0 abonnes
Il y a 5 abonnes
qui sont :
Donel 0818899608
Amel 0842578483
Grael 0901485690
Coel 0818955623
260

Anael 0878955623
ou encore, par ordre alphabétique
Amel 0842578483
Anael 0878955623
Coel 0818955623
Donel 0818899608
Grael 0901485690

Exercice 9.2
Classe Personne {
privé nom : Chaine
privé age : entier

public Personne(a : entier, n : Chaine)


{
nom ← Chaine(n)
age ← a
}
public getChaine() : Chaine
{
tempNom, tempAge : Chaine
tempAge ← new Chaine(this.age)
tempNom ← new Chaine(this.nom)
tempNom.concantener(new Chaine("-"))
tempNom.concantener(tempAge)
netourne tempNom
}
}

Classe Couple {
privé p1, p2 : Personne
privé age : entier

public Couple()
{
this.p1 ← null
this.p2 ← null
}
public Couple(p1: Personne, p2: Personne)
{
this.p1 ← p1
this.p2 ← p2
}

public reunir(p1: Personne, p2: Personne) : vide


{
this.p1 ← p1
this.p2 ← p2
261

public separer() : vide


{
this.p1 ← null
this.p2 ← null
}

public getChaine() : Chaine


{
temp : Chaine
si ((p1 <> null) et (p1 <> null)) alors
{
temp ← p1.getChaine()
temp.concantener(new Chaine(" et "))
temp.concantener(p2.getChaine() )
} sinon
temp ← new Chaine(" pas un vrai couple! ")
retourne temp
}
}

Classe UtiliseCouplePersonne {
public main() : vide
{
c1, c2 : Couple
c1 ← new Couple(new Personne(30, "Kévin"), new Personne(25, "Carine"))
c2 ← new Couple()
afficher("c1: ", c1)
afficher("c2: ", c2)
c1.separer()
c2.reunir(new Personne(28, "Yan"), new Personne(24, "Tania"))
afficher("c1: ", c1)
afficher("c2: ", c2)
}
}

Exercice 9.3
Nous revenons sur la gestion de la Pharmacie (cfr : 9.4) en modifiant la classe
Pharmacie et en créant la classe GestionPharmacie comme suit :

a. Classe Pharmacie
public classe Pharmacie {
// Une pharmacie est une liste de clients et une liste de médicaments
privé clients : tableau[] de Clients
privé medicaments : tableau[] de Medicaments

public Pharmacie(cs: Client[],ms: Medicament[])


{
clients ← cs
262

medicaments ← ms
}

public getClients(): Client[]


{
retourne this.clients
}

public getMedicaments(): Medicament[]


{
retourne this.medicaments
}

static acheter(): vide


{
paiement : réel
quantite : entier
client : Client
medicament : Medicament
client ← this.lireClient()
medicament ← this.lireMedicament()
paiement ← lirePaiement()
quantite ← lireQuantite()
si (quantite <= medicament.getStock())
{
medicament.diminuerStock(quantite)
client.augmenterCredit((medicament.getPrix() * quantite) - paiement)
} sinon
afficher("Achat impossible. Quantité insuffisante")
}
static approvisionnemer(): vide
{
quantite : entier
medicament : Medicament

medicament ← lireMedicament(medicaments)
afficher("Donner la Quantité : ")
lire(quantite)
medicament.augmenterStock(quantite)
}
static afficherPh(): vide
{
i: entier
afficher("Affichage des stocks")
pour i ← 0 à medicaments.longueur()-1 faire
{
afficher ("Stock du médicament " + medicaments[i].getNom(), " est ",
medicaments[i].getStock())
}
afficher("Affichage des crédits")
pour i ← 0 à clients.longueur()-1 faire
{
afficher("Crédit du client ", clients[i].getNom(), " est " , clients[i].getCredit())
}
}
263

static lireClient() : Client


{
i: entier
nom: Chaine
trouve ← faux: booléen
c ← nulle : Client
afficher("Nom du client?")
faire{
lire(nom)
pour i ← 0 à (!trouve et i < clients.longueur()) faire
{
si ((clients[i].getNom()).egal(nom)) alors
{
trouve ← vrai
c ← clients[i]
}
}
si (!trouve) alors
afficher("Client inconnu. Veuillez recommencer")

} tant_que(!trouve)
retourne c
}
static lireMedicament(): Medicament
{
i: entier
nom: Chaine
trouve ← faux: booléen
m ← nulle : Medicament
afficher("Nom du médicament?:")
faire{
lire(nom)
pour i ← 0 à (!trouve et i < medicaments.longueur()) faire
{
si ((medicaments[i].getNom()).egal(nom)) alors
{
trouve ← vrai
m ← medicaments[i]
}
}
si (!trouve) alors
afficher("Medicament inconnu. Veuillez recommencer")

} tant_que(!trouve)
retourne m
}

static lirePaiement() : réel


{
paiement : réel
afficher("Quel est le montant du paiement?");
lire(paiement)
retourne GestionPharmacie.paiement
}
264

static lireQuantite() : entier


{
quantite : entier
afficher("Quelle est la quantité achetée?");
lire(quantite)
retourne GestionPharmacie.quantite
}
}

b. Classe GestionPharmacie
public classe GestionPharmacie {
public static principal(): void
{
clients: tableau[] de Clients
medicaments: tableau[] de Medicaments
p: Pharmacie

clients ← new Client[5]


clients[0] ← new Client("Donel", 0.0)
clients[1] ← new Client("Amel", 0.0)
clients[2] ← new Client("Grael", 0.0)
clients[3] ← new Client("Coel", 0.0)
clients[4] ← new Client("Anael", 0.0)

medicaments ← new Medicament[4]


medicaments[0] ← new Medicament("Aspirine", 20.40, 5)
medicaments[1] ← new Medicament("Maladox", 19.15, 5)
medicaments[2] ← new Medicament("Doliprane", 20.40, 5)
medicaments[3] ← new Medicament("Tranxene", 19.15, 5)

p = new Pharmacie(clients, medicaments)


choix : entier
faire {
choix ← menu()
suivant_que (choix) faire
{
1: p.achater()
2: p.approvisionnemer()
3: p.afficherPh()
4: quitter()
}
} tant_que(choix < 4)
}

static menu() : entier


{
choix ← 0 : entier
afficher()
afficher("1 : Achat de médicament")
afficher("2 : Approvisionnement en médicaments")
afficher("3 : Etats des stocks et des crédits")
afficher("4 : Quitter")
265

tant_que ((choix != 1) et (choix != 2) et (choix != 3) et (choix != 4))


{
afficher("Quel est votre choix ?")
lire(choix)
}
retourne choix
}

static quitter() : vide


{
afficher("Fin de traitement!")
}
}

Chapitre 10
Exercice 10.1
Partant de la solution de l’exercice 5.18, nous obtenons la partie principale suivante :
// Calcul
pour i ← 0 à n-1 faire
{
y[i] ← 0
pour j ← 0 à n-1 faire
{
y[i] ← y[i] + a[i][j] * x[j]
}
afficher y[i]
}

Etant donné l’existence de deux boucles imbriquées, la complexité T(n) = O(n2)


(complexité d’ordre n2).

Exercice 10.2
Partant de la solution de l’exercice 5.19, nous obtenons la partie principale suivante :
// Calcul des éléments de la matrice C
pour i ← 0 à n-1 faire
{
pour j ← 0 à n-1 faire
{
c[i][j]← 0
pour k ← 0 à n-1 faire
{
c[i][j] ← c[i][j] + a[i][k] * b[k][j]
}
}
}
266

Etant donné l’existence de trois boucles imbriquées, la complexité T(n) = O(n3)


(complexité d’ordre n3).
267

Bibliographie
[1] Bruno Baynat, Philippe Chrétienne et Claire Hanen, Exercices et problèmes
d'algorithmique, Dunod, 2010.
[2] Hugues Bersini, L’orienté objet, Eyrolles, 2007.
[3] Patrick Bosc, Marc Guyomard et Laurent Miclet, Conception d'algorithmes, Dunod, 2016.

[4] Olivier Carton, Langages formels – Calculabilité et complexité, Vuibert, 2014.


[5] Thomas H. Cormen, Charles Leiserson, Ronald L. Rivest et Clifford Stein, Algorithmique,
Dunod, 2010.
[6] Christophe Dabancourt, Apprendre à programmer, Eyrolles, 2008.
[7] Christophe Darmangeat, Algorithmique et programmation pour non-matheux, Tutoriel,
2010.
[8] Claude Delannoy, S'initier à la programmation et à l'orienté objet : Avec des exemples en
C, C++, C#, Java, Python et PHP, Eyrolles, 2014.
[9] Laurent Debrauwer, Algorithmique - Entraînez-vous et améliorez votre pratique de la
programmation (Exemples en Java), Eni, 2009.
[10] Michel Divay, Algorithmes et structures de données génériques - Cours et exercices
corrigés en langage C, Dunod, 2004
[11] Franck Ebel et Sébastien Rohaut, Algorithmique - Techniques fondamentales de
programmation (Exemples en Python), Eni.
[12] Robert Michel di Scala, Les bases de l’informatique et de la programmation, Berti, 2014
[13] Nicolas Flasque, Helen Kassel, Franck Lepoivre et Boris Velikson, Exercices et
problèmes d'algorithmique, Dunod, 2010.
[14] Christophe Haro, Algorithmique - Raisonner pour concevoir, Eni, 2009.
[15] Sébastien Putier et Sébastien Rohaut, Algorithmique - Techniques fondamentales de
programmation (Exemples en C#), Eni.
[16] Sébastien Putier et Sébastien Rohaut, Algorithmique et programmation : les bases
indispensables (Exemples en C#), Eni.
[17] Sébastien Rohaut, Algorithmique - Techniques fondamentales de programmation
(Exemples en Java), Eni.
[18] Sébastien Rohaut, Algorithmique - Techniques fondamentales de programmation
(Exemples en PHP), Eni

Vous aimerez peut-être aussi