[Go to site: main page, start]

0% ont trouvé ce document utile (0 vote)
41 vues254 pages

Programmation en Pascal avec Lazarus

Transféré par

A'abas Bauer
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
41 vues254 pages

Programmation en Pascal avec Lazarus

Transféré par

A'abas Bauer
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Programmation et langages

Lazarus (Free Pascal)

5e année Transition - Informatique

Pierrard - Virton Eric Henrotte


2
TABLE DES MATIÈRES

I Notions essentielles 11
1 Introduction 13
1.1 Définitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.1.1 Ordinateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.1.2 Traitement formel d’information . . . . . . . . . . . . . . . . . . 13
1.1.3 Opposition « utilisateur – programmeur » . . . . . . . . . . . . . 14
1.1.4 Algorithmes et programmation . . . . . . . . . . . . . . . . . . 14
1.2 Installation de Lazarus . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2 Concepts de base 19
2.1 Les identificateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2 Constantes et variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2.1 Définition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2.2 Déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.3 Commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.4 Affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.5 Instructions et blocs d’instructions . . . . . . . . . . . . . . . . . . . . . 22
2.6 Types et expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.6.1 Les types entiers . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.6.2 Les types réels . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.6.3 Conversion réels ⇐⇒ entiers . . . . . . . . . . . . . . . . . . . . 26
2.6.4 Type booléen (boolean) . . . . . . . . . . . . . . . . . . . . . . . 27
2.6.5 Type caractère (char) . . . . . . . . . . . . . . . . . . . . . . . . 30
2.6.6 Les chaînes de caractères (String) . . . . . . . . . . . . . . . . . 31
2.6.7 Autres types de données . . . . . . . . . . . . . . . . . . . . . . 36

3 Les instructions en Pascal 37


3.1 Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.2 L’affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.3 Lecture et écriture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.3.1 Lecture du contenu d’une variable au clavier . . . . . . . . . . . 37
3.3.2 Écriture du contenu d’une variable à l’écran . . . . . . . . . . . . 38

3
TABLE DES MATIÈRES TABLE DES MATIÈRES

3.3.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3.4 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.4 Les tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.4.1 La structure alternative . . . . . . . . . . . . . . . . . . . . . . . 40
3.4.2 Le choix multiple . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.4.3 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.5 Les structures répétitives ou boucles . . . . . . . . . . . . . . . . . . . . 47
3.5.1 La boucle while (Tant Que) . . . . . . . . . . . . . . . . . . . . 47
3.5.2 La boucle repeat (répéter . . . jusqu’à) . . . . . . . . . . . . . . . 50
3.5.3 La boucle for (pour) . . . . . . . . . . . . . . . . . . . . . . . . 53
3.6 Procédures Halt, Break, Continue, Exit . . . . . . . . . . . . . . . . . . . 56
3.6.1 Halt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.6.2 Break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.6.3 Continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.6.4 Exit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.6.5 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.7 Utilisation du générateur aléatoire . . . . . . . . . . . . . . . . . . . . . 60
3.7.1 Générer un nombre réel . . . . . . . . . . . . . . . . . . . . . . 60
3.7.2 Générer un nombre entier . . . . . . . . . . . . . . . . . . . . . 60
3.7.3 Randomize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

4 Les tableaux 63
4.1 Les tableaux à une dimension . . . . . . . . . . . . . . . . . . . . . . . . 63
4.1.1 Définition et utilité . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.1.2 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.2 Les tableaux à plusieurs dimensions . . . . . . . . . . . . . . . . . . . . 68
4.2.1 Les matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
4.2.2 Les tableaux d’une dimension supérieure à deux . . . . . . . . . 69
4.3 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.4 Le tri d’un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.4.1 Le tri par sélection . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.4.2 Le tri « bulles » . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.4.3 Le tri par insertion . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.4.4 Le tri à peigne . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.5 La recherche dans un tableau . . . . . . . . . . . . . . . . . . . . . . . . 76
4.5.1 La recherche séquentielle . . . . . . . . . . . . . . . . . . . . . . 76
4.5.2 La recherche dichotomique . . . . . . . . . . . . . . . . . . . . . 76
4.5.3 La fusion de deux tableaux triés . . . . . . . . . . . . . . . . . . 78

5 Types de données additionnels 79


5.1 Le type énumération . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5.2 Le type intervalle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.3 Le type enregistrement . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.3.1 Définition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.3.2 Accès aux champs . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.3.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.4 Le type ensemble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

4
TABLE DES MATIÈRES TABLE DES MATIÈRES

5.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.4.2 Manipulation des ensembles . . . . . . . . . . . . . . . . . . . . 85
5.4.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

6 Les sous-programmes 89
6.1 Décomposition d’un problème . . . . . . . . . . . . . . . . . . . . . . . 89
6.2 L’écriture de “gros” programmes . . . . . . . . . . . . . . . . . . . . . . 91
6.3 Les procédures et fonctions . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.3.1 Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.3.2 Les procédures . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.3.3 Le passage des paramètres . . . . . . . . . . . . . . . . . . . . . 102
6.3.4 Variables locales, globales – Effet de bord . . . . . . . . . . . . . 104
6.3.5 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

7 Les fichiers 111


7.1 Différents types de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . 111
7.1.1 Fichiers texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
7.1.2 Fichiers à accès direct . . . . . . . . . . . . . . . . . . . . . . . 111
7.1.3 Fichiers binaires ou non typés . . . . . . . . . . . . . . . . . . . 112
7.2 Manipulation des fichiers texte . . . . . . . . . . . . . . . . . . . . . . . 112
7.2.1 Ouverture et fermeture d’un fichier texte . . . . . . . . . . . . . . 112
7.2.2 Lecture depuis un fichier texte . . . . . . . . . . . . . . . . . . . 114
7.2.3 Écriture dans un fichier texte . . . . . . . . . . . . . . . . . . . . 115
7.2.4 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
7.2.5 Effacement d’un fichier . . . . . . . . . . . . . . . . . . . . . . . 117
7.2.6 Renommage d’un fichier . . . . . . . . . . . . . . . . . . . . . . 117
7.2.7 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
7.3 Manipulation des fichiers à accès direct . . . . . . . . . . . . . . . . . . 119
7.3.1 Déclaration du type de fichier à accès direct . . . . . . . . . . . 120
7.3.2 Assignation de fichier . . . . . . . . . . . . . . . . . . . . . . . 120
7.3.3 Ouverture de fichier . . . . . . . . . . . . . . . . . . . . . . . . 120
7.3.4 Positionnement à l’intérieur d’un fichier . . . . . . . . . . . . . 120
7.3.5 Instructions de lecture et d’écriture . . . . . . . . . . . . . . . . 121
7.3.6 Enregistrement courant et taille d’un fichier . . . . . . . . . . . . 121
7.3.7 Fin de fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
7.3.8 Fermeture de fichier . . . . . . . . . . . . . . . . . . . . . . . . 121
7.3.9 Effacement et renommage d’un fichier . . . . . . . . . . . . . . . 121
7.3.10 Troncature d’un fichier . . . . . . . . . . . . . . . . . . . . . . . 122
7.3.11 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
7.3.12 Exercice : gestion simplifiée d’un fichier d’élèves . . . . . . . . . 127
7.4 Fichiers non typés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

8 Compléments 129
8.1 L’unité CRT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
8.1.1 Quelques constantes . . . . . . . . . . . . . . . . . . . . . . . . 129
8.1.2 Quelques fonctions ou procédures . . . . . . . . . . . . . . . . . 129
8.2 L’unité GRAPH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

5
TABLE DES MATIÈRES TABLE DES MATIÈRES

8.3 L’unité WINCRT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135


8.3.1 Fonctions et procédures . . . . . . . . . . . . . . . . . . . . . . 135

II Exercices supplémentaires 137


1 Les boucles 139

2 Les tableaux 149

III Correction de quelques exercices 153


1 Les structure de contrôle 155
1.1 Exercices élémentaires : séquence . . . . . . . . . . . . . . . . . . . . . 155
1.2 Les tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
1.3 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

2 Tableaux | Sous-programmes | Fichiers 203


2.1 Les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
2.2 Les sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
2.3 Graphisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
2.4 Les fichiers texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
2.5 Les fichiers d’enregistrements . . . . . . . . . . . . . . . . . . . . . . . 248

6
TABLE DES FIGURES

1.1 La programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.2 Pseudo code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.3 Organigramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.4 Homepage Lazarus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5 Projet Lazarus : programme simple . . . . . . . . . . . . . . . . . . . . . 17
1.6 Fenêtre du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.1 Les types entiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24


2.2 Les types réels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.3 Opérateurs relationnels . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.4 Opérateurs logiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.5 Précédence des opérateurs . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.6 Quelques codes ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.7 Quelques codes ASCII : les caractères accentués . . . . . . . . . . . . . . 35

3.1 L’alternative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.2 Le choix multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.3 La boucle While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.4 La boucle Repeat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.5 La boucle For (to) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.6 La boucle For (downto) . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

4.1 Représentation d’un tableau . . . . . . . . . . . . . . . . . . . . . . . . . 63


4.2 Tableau à deux dimensions . . . . . . . . . . . . . . . . . . . . . . . . . 68

6.1 Décomposition d’un problème (1) . . . . . . . . . . . . . . . . . . . . . 89


6.2 Décomposition d’un problème (2) . . . . . . . . . . . . . . . . . . . . . 90
6.3 Écriture d’entêtes de fonctions . . . . . . . . . . . . . . . . . . . . . . . 95
6.4 Le passage par valeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
6.5 Le passage par adresse . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

7
INDEX

•, 82 conversion de types, 26, 33


+=, 48 Copy, 32
:=, 22, 37 crt, 129
#, 30
$, 25 décomposition d’un problème, 89–91
delete, voir effacement
affectation, 22, 37 div, 24
algorithme, 15, 37, 38
alternative, voir structures de contrôle écriture
AnsiString, 31 à l’écran, 38
Append, 112 dans un fichier d’enregistrements, 121
ascii, 30, 34, 35 dans un fichier texte, 115
Assign, 112, 120 effacement
assignation, voir affectation chaîne, 33
fichier, 117
bit, 23 effet de bord, 105
bloc d’instructions, 22 enregistrement, voir type
BlockRead, 128 ensemble, voir type
BlockWrite, 128 Eof, 114, 121
booléen, 27 Erase, voir effacement
boucles, voir structures de contrôle Exit, 57
Break, 56 expression, 23
byte, voir octet
fichiers
caractère, 30 à accès direct, 119–128
cardinalité, 79 non typés, 128
carré magique, 70 texte, 111–119
chaîne, voir type (String) FileExists, 113
champ, 81 FilePos, 121
choix multiple, voir structures de contrôle FileSize, 121
Chr, 30, 33 fonctions, 94–99
Close, 113, 121 appel, 97
commentaires, 21, 37, 92, 93 corps, 99
constante, 19, 35 déclaration, 96, 98
Continue, 57 définition, 94

8
INDEX INDEX

Frac, 27 programmation, 14
pseudo code, 15
goto, 92
graph, 135 Random, 60
Randomize, 60
Halt, 56 Readln, 38, 114
Real, 26
identificateur, 19 recherche
In, 86 dichotomique, 76–78
Infinity, 27 séquentielle, 76
Insert, 33 Rename, 117
instruction, 22 renommage d’un fichier, 117
Int, 27 Reset, 112, 120
Integer, 24 Rewrite, 112, 120
Round, 26
lazarus, 17
lecture Seek, 120
au clavier, 37 sous-programmes, 94–106
dans un fichier d’enregistrements, 121 Sqr, 40
dans un fichier texte, 114 Sqrt, 40
Length, 31 Str, 33
LowerCase, 32 string, voir type (String)
StringOfChar, 33
MaxInt, 25 structures de contrôle, 92
mod, 25 alternative, 40
modularisation, 91, 94 boucles
For ... Downto, 54
octet, 23 For ... To, 53
opérateurs booléens Repeat, 50
opérateurs logiques, 28 While, 47
opérateurs relationnels, 28 choix multiple, 42
ordinateur, 13 séquence, 23
organigramme, 16, 38, 40, 43
tableau
paramètre formel, 98–103 à deux dimensions, 68
paramètre réel, 101–103 à plus de deux dimensions, 69
passage des paramètres, 102–104 à une dimension, 63
avantages et inconvénients, 103 Text, 112
par adresse, 103 traitement formel, 13
par valeur, 102 tri
Pos, 33 à peigne, 75
précédence des opérateurs, 29 bulles, 72
procédures, 99–101 par insertion, 74
corps, 101 par sélection, 72
déclaration, 99, 101 Troncature, 122
définition, 99 Trunc, 26

9
INDEX INDEX

type, 23–36
énumération, 79
booléen, 27
caractère, 30
enregistrement, 81, 119, 120
ensemble, 83
entier, 24
intervalle, 80
réel, 26
string, 31–36

UpCase, 32

Val, 33
variable, 20
variable globale, 104
variable locale, 104

WideString, 31
wincrt, 135
With, 127
Write, 38
Writeln, 38, 115

10
Première partie

Notions essentielles

11
CHAPITRE 1
INTRODUCTION

1.1 Définitions
1.1.1 Ordinateur
Dans le cadre de l’utilisation que l’on va en faire, un ordinateur, c’est une machine
à traiter des informations, de manière formelle, pour autant qu’on lui ait indiqué, dans le
détail, comment mener à bien ce traitement.

1.1.2 Traitement formel d’information


L’ordinateur va donc s’atteler au traitement d’informations par exemple :
- additionner deux nombres ;
- calculer une moyenne ;
- chercher le plus grand d’une série de nombres ;
- trier un paquet de cartes numérotées qui se présentent dans le désordre ;
- transcrire en toutes lettres un nombre écrit en chiffres ;
- chercher le numéro de téléphone d’un abonné ;
- insérer un nouvel élève ;
- conjuguer un verbe régulier du premier groupe à tous les temps de l’indicatif ;
- lire un texte et fournir la fréquence des divers mots le composant ;
- centrer un titre lors de la dactylographie d’un document ;
- ...
Le premier ensemble de tâches concerne des traitements de nombres et les manipu-
lations de données numériques sont, par essence, formelles. Le processus d’addition de
deux nombres n’a que faire du “sens” qui serait attaché aux quantités à additionner, qu’il
s’agisse de poids, de sommes d’argent ou d’âges.
Le deuxième exemple de tâches correspond lui aussi, même si les informations ne sont
plus numériques, à des traitements formels : trier, chercher un numéro de téléphone, clas-
ser, ... sont des actions qui ne font appel qu’à la forme des données manipulées. ANTOINE

13
Définitions Introduction

précèdera toujours BENOIT dans un classement alphabétique et c’est l’apparence externe


de ces prénoms qui permettra de dire que « AAFFRR » n’est pas un prénom. L’ordinateur,
ne travaillant qu’avec la forme des données qui lui sont transmises, classera « AAFFRR »
avant ANTOINE sans se soucier du sens du mot « AAFFRR » dans la liste de prénoms.
Le troisième exemple de tâches concerne la manipulation formelle de texte. Le texte est
considérer comme une chaîne (ou succession) de caractères et non de mots. En aucun cas
l’ordinateur ne se souciera du sens d’un texte. Pour s’en rendre compte, il suffit de vérifier
les propositions qu’un correcteur orthographique peut proposer pour un mot erroné. Par
exemple, si j’écris « je fais une phôte d’orthographe », le mot « phôte » est repéré dans le
texte comme étant incorrect, et les propositions de corrections sont « hôte » ou « hôtes » !
Par contre, rien dans la phrase « il faut pou voir se rencontrer » n’éveille une réaction de
l’ordinateur ; les mots « pou » et « voir » se trouvant dans la liste des mots acceptables.

1.1.3 Opposition « utilisateur – programmeur »


Schématiquement, on peut représenter les choses de la manière suivantes :

Figure 1.1 – La programmation

L’utilisateur voit dans l’ordinateur, équipé des programmes convenables qui le feront
agir, un outil pour l’aider à accomplir sa tâche (présenter un document, calculer des tra-
jectoires balistiques, gérer les opérations bancaires, dessiner, . . . ). Ce qui l’intéresse, c’est
essentiellement : « quelles données dois-je fournir ? » et « quels résultats suis-je en droit
d’attendre après le traitement qui y sera appliqué ? ». Pour le reste, l’ordinateur équipé du
programme (logiciel) qui le gouverne pendant l’utilisation, c’est une boîte magique.
Le programmeur (ou plutôt l’analyste-programmeur) s’intéresse d’abord au traite-
ment proprement dit. Pour lui, l’ordinateur est d’abord un exécutant à qui il va falloir
fournir une marche à suivre (programme) expliquant le traitement à effectuer.

1.1.4 Algorithmes et programmation


Démarche type de résolution d’un problème en informatique
La programmation implique une démarche de résolution de problème qui permet
d’appréhender la complexité. Cette démarche, qui doit être mise en œuvre pour tous les
problèmes de programmation et qui doit être accompagnée d’un rapport final sur le travail
effectué, peut être décomposée de la manière suivante :

14
Définitions Introduction

- discussion, élaboration et rédaction du cahier de charge ;


- analyse du problème ;
- rédaction de l’algorithme (langage de description des algorithmes) ;
- transcription de l’algorithme dans un langage (lisibilité : commentaires, indenta-
tion) ;
- tests et simulations ;
- corrections, validation, débogages.

Programmer c’est faire faire...


Il s’agira à chaque fois pour le programmeur, non d’exécuter des tâches lui-même, mais
de les faire exécuter. C’est cela programmer !

Il s’agit, non seulement d’être capable de mener à bien soi-même une


tâche donnée, mais d’expliquer à un autre (l’ordinateur) comment il doit
s’y prendre pour exécuter cette tâche à sa place.

Le problème principal du programmeur est de parvenir à décrire correctement et le


plus simplement possible la suite des actions élémentaires permettant d’obtenir, à partir
des données fournies, les résultats escomptés. Un algorithme est une suite d’opérations
permettant de résoudre un problème spécifique.

Deux représentations des algorithmes


1. Pseudo code

Lire N
S←0
I←1
tant que I ≤ N faire
S ←S+I
I ←I +1
fin
Afficher S
Figure 1.2 – Pseudo code

15
Définitions Introduction

2. Organigramme

Figure 1.3 – Organigramme

16
Installation de Lazarus Introduction

1.2 Installation de Lazarus


Il suffit de se rendre sur le site http ://[Link]/, de télécharger puis d’exé-
cuter.

Figure 1.4 – Homepage Lazarus

Lazarus sera utilisé pour écrire des programmes en mode console (aucun "widget"
comme des boutons, cases à cocher, ...).

Figure 1.5 – Projet Lazarus : programme simple

17
Installation de Lazarus Introduction

On obtient la fenêtre suivante où il est possible d’écrire du code

Figure 1.6 – Fenêtre du code

qu’on exécutera avec

18
CHAPITRE 2

CONCEPTS DE BASE

2.1 Les identificateurs


Chaque fois que l’on fait référence à un objet du programme (une variable, une constante,
le nom d’une procédure...), c’est par l’intermédiaire d’un nom, appelé identificateur. Un
identificateur est une suite de caractères de longueur non limitée dont le premier doit obli-
gatoirement être une lettre (non accentuée) ou le caractère de soulignement (_). Après cette
première lettre peuvent figurer exclusivement des chiffres, des lettres (non accentuées) ou
des caractères de soulignement (dans un ordre quelconque). Le caractère de soulignement
est souvent utilisé dans le but d’améliorer la lisibilité. Voici quelques exemples d’identifi-
cateurs :
A Epsilon45 revenu_brut

Le choix des identificateurs peut également favoriser la lecture et la compréhension


d’un programme. II est déconseillé d’utiliser des identificateurs trop courts, ne suggérant
aucune signification (par exemple A, X2, z), ainsi que des identificateurs trop longs, né-
cessitant plus de travail lors de l’écriture, et surtout n’offrant pas forcément une meilleure
lisibilité.
Le langage Pascal ne distingue pas les minuscules des majuscules qui forment un iden-
tificateur. Ainsi les trois noms qui suivent désignent le même objet :
Rendement rendement RENDEMENT

2.2 Constantes et variables


Le langage Pascal fait une distinction entre constantes et variables. On utilise une
constante chaque fois qu’un objet garde la même valeur tout au long d’un programme.
Une constante reçoit une valeur au moment de la compilation du programme et cette va-
leur ne peut pas être modifiée. Une variable sera au contraire utilisée comme un objet dont
la valeur peut être modifiée durant l’exécution du programme.

19
Constantes et variables Concepts de base

2.2.1 Définition
Une variable est une association entre une place de la mémoire et un nom. Une va-
riable sert à stocker des données, des résultats, des informations que le programme pourra
réutiliser ensuite. Une variable sert à stocker une valeur. Cette valeur peut être (type) :
- un nombre : 12 ou 75.5
- une chaine de caractères : ’Arts & Métiers – PIERRARD’
- ...
Remarques :
- la mémoire (mémoire centrale ou RAM) utilisée durant l’exécution d’un programme
peut être comparée à un bureau avec de nombreux tiroirs, espaces de travail, . . .
- chaque case de la mémoire est repérée par un numéro distinct : son adresse ;
- cette mémoire est différente du disque dur qui permet de retrouver ses fichiers après
avoir éteint et rallumé l’ordinateur 1 .
Une variable s’utilise souvent en 3 étapes :
- déclaration : définir le type de la variable.
- initiation : donner une valeur à la variable.
- utilisation (de la valeur de la variable) : par exemple pour l’afficher, pour calculer,
...

2.2.2 Déclaration
Comme tous les objets définis par le programmeur, les constantes et les variables
doivent être déclarées avant leur utilisation. La déclaration d’une variable comporte deux
parties : le nom de la variable 2 et son type. Voici un exemple de déclaration de constantes
et de variables :
procedure premier ;
const nul = 0 ;
code = ' secret ' ;
zede = 'z ' ;
var age : integer ;
salaire : real ;
sexe : char ;
begin
// on utilise les variables et constantes ici
end .

Dans le cas des constantes, l’identificateur est suivi du signe "=" et de la valeur que
l’on associe à la constante. Pour les variables, l’identificateur est suivi du signe " :" et
du type de la variable. Chaque déclaration de constante ou de variable se termine par un
point virgule. Si plusieurs variables sont du même type, il est possible de les déclarer sous
forme de liste d’identificateurs (séparés par une virgule) suivie du signe " :" et du type des
variables :
var age , enfants , voitures : integer ;
salaire , taille : real ;

1. La mémoire centrale (RAM) est dite volatile tandis que le disque dur est une mémoire permanente
2. Rappel : le nom d’une variable doit commencer par une lettre ou _

20
Commentaires Concepts de base

Les déclarations précédentes peuvent également s’écrire :


var age : integer ; { du p è r e }
enfants : integer ; { à charge }
voitures : integer ; { disponibles }
salaire : real ; { maximum }
taille : real ; { du capitaine }

2.3 Commentaires
Dans le but d’améliorer la lisibilité et la compréhension des programmes, il est forte-
ment conseillé d’introduire des commentaires. Un commentaire est un texte explicatif plus
ou moins long, placé dans le programme, et ignoré par le compilateur. Les commentaires
sont donc totalement invisibles et inutiles dans la phase de compilation et d’exécution d’un
programme, mais d’une importance primordiale dans les phases de conception, de mise
au point et de maintenance.
Ces explications, visibles uniquement dans les fichiers source (contenant le texte du
programme), sont essentiellement destinées aux personnes susceptibles d’analyser un pro-
gramme ou de lui apporter des modifications. Dans la plupart des cas, les commentaires
sont destinés à l’auteur du programme. Mais dans tous les cas où un programme est réalisé
en équipe, ou repris par d’autres personnes que l’auteur, les commentaires doivent être une
aide à la compréhension, surtout dans certains passages peu évidents.
II n’est pas rare de rencontrer des programmes où les commentaires occupent plus de
place que les instructions elles-mêmes. II ne faut cependant pas oublier de mettre à jour les
commentaires lors de la modification de tout ou partie du programme. Un commentaire
devenu caduque ou qui n’a pas été mis à jour perd son utilité et peut même devenir un
obstacle à la compréhension d’un programme.
En Pascal, les commentaires sont reconnus comme tels par le compilateur grâce à des
marques de début et de fin qui sont soit des accolades { }, soit les symboles (* et *). II est
possible d’imbriquer un type de commentaire dans l’autre type de commentaire. En voici
quelques exemples :
(*
Bonjour .
Ce programme affiche un m e s s a g e de bienvenue .
*)
(* Programme é c r i t par : Durant Eva le 25/09/2012 *)
{ imbrication de commentaires (* t r ès drô l e s *) }

Il existe un troisième type de commentaire issu du langage C : chaque ligne commen-


çant par // est considérée comme un commentaire. Dans ce cas, le commentaire ne peut
s’étendre que sur une ligne et ne possède qu’une marque de début :
Writeln ( ' Bonjour ' ) ; // Ache "Bonjour" à l'écran

21
Affectation Concepts de base

2.4 Affectation
L’affectation (ou assignation) est l’une des instructions les plus importantes en Pascal.
Elle permet de placer une valeur, qui est le résultat de l’évaluation d’une expression, dans
une position mémoire référencée par une variable :
variable := expression ;

où variable est l’identificateur d’une variable qui a été déclarée auparavant.


L’expression peut être une simple variable ou constante, ou bien une combinaison de
constantes, variables et opérateurs arithmétiques. Le symbole
:=

indique l’affectation et pourrait être traduit par "prend la valeur de". Les deux signes qui
le composent doivent être accolés.
En Pascal, on a voulu éviter toute confusion entre le symbole de l’affectation (" :=")
et celui de l’égalité (représenté par le signe "="). Lors d’une affectation, l’expression qui
se trouve à droite du symbole := est évaluée, ensuite seulement le résultat de l’évaluation
est affecté à la variable située à gauche du symbole :=. De plus, il est impératif que le type
de l’expression soit le même que le type de la variable à laquelle on affecte le résultat de
l’expression 3 .

2.5 Instructions et blocs d’instructions


Les instructions en Pascal sont séparées par des points virgules. Lorsque plusieurs ins-
tructions forment logiquement un tout, on est souvent amené à les grouper. On obtient alors
un bloc d’instructions. Le début d’un tel bloc est indiqué par le mot réservé begin, alors
que sa fin est indiquée par le mot réservé end. On parle parfois d"’instruction composée" au
lieu de "bloc d’instructions". Ceci exprime bien le fait qu’un groupement de plusieurs ins-
tructions peut être vu comme une seule instruction (indivisible). Le corps d’un programme
Pascal est lui-même un bloc d’instructions. Voici un exemple de bloc d’instructions :
begin
age := 55;
no := age * 10;
end ;

Lorsque l’on écrit ses premiers programmes, les points virgules posent parfois des
problèmes. La règle concernant les points virgules est la suivante :

Chaque instruction doit se terminer par un point-virgule.


Toutefois, le point-virgule peut être omis s’il est suivi des mots réservés end ou until.
Il doit être omis s’il est suivi du mot réservé else (sauf s’il s’agit d’une structure sélective
case...of ).

3. Il y a parfois des conversions implicites de types, par exemple, un entier en réel.

22
Types et expressions Concepts de base

En suivant cette règle, l’exemple précédent aurait pu s’écrire de la manière suivante


begin
age := 55;
no := age * 10
end ;

Bien que cette forme d’écriture soit tout à fait correcte, il est conseillé de l’éviter au
profit de la première citée. L’économie de points virgules peut parfois conduire à des er-
reurs de syntaxe lors de la modification d’un programme. Ajoutons, par exemple, une ligne
à la fin du bloc d’instructions (avant le end). Le risque d’oublier de placer un point virgule
à la fin de la ligne qui précède donne le résultat suivant :
begin
age := 55;
no := age * 10 // il manque un ; ici
no := no − age // ligne ajoutée
end ;

Ce fragment de programme n’est pas correct, car il manque le séparateur entre les deux
dernières instructions.

Séquence : l’ordre dans lequel les différentes opérations seront écrites indique l’ordre
dans lequel elles seront exécutées : de haut en bas et de gauche à droite. Il s’agit
d’une exécution séquentielle (séquence).

2.6 Types et expressions


Parmi les avantages qu’offre le langage Pascal, on trouve une grande richesse de types
de données. Nous avons vu précédemment qu’à chaque variable correspond un type. La
notion de type est très importante puisqu’elle détermine la nature et l’ensemble des va-
leurs que peut prendre une variable. Dans cette section nous nous intéressons aux types
scalaires. Parmi les types scalaires on trouve les types entiers, réels, booléen et caractère,
ainsi que les types énumérés ou définis par l’utilisateur. Nous étudierons également les
expressions qu’il est possible de construire sur la base de chacun de ces types.
Une expression est une combinaison d’objets qui sont des opérateurs, des opérandes
et des parenthèses. Nous serons amenés à évoquer la représentation interne des nombres,
ou du moins la place mémoire occupée par une variable d’un type donné. En informa-
tique, l’unité de mesure de la capacité mémoire est l’octet (byte) ; un octet étant lui-même
composé de 8 chiffres binaires (bits) pouvant prendre chacun la valeur 0 ou 1.

23
Types et expressions Concepts de base

2.6.1 Les types entiers


II existe plusieurs type permettant de stocker des valeurs entière. Voici leurs caracté-
ristiques :

Type Intervalle Format/taille


Byte 0 .. 255 1 octet
Shortint −128 .. 127 1 octet
Smallint −32768 .. 32767 2 octets
Word 0 .. 65535 2 octets
Longint −2147483648 .. 2147483647 4 octets
Cardinal Longword 4 octets
Longword 0 .. 4294967295 4 octets
63 63
Int64 −2 .. 2 − 1 8 octets
−9223372036854775808 .. 9223372036854775807
QWord 0 .. 264 − 1 8 octets
0..18446744073709551615
Integer Longint (−2147483648 .. 2147483647) 4 octets

Figure 2.1 – Les types entiers

Malgré leurs particularités, les différents types entiers se comportent de la même ma-
nière. Pour garder une cohérence dans les types de données, une opération entre deux
nombres entiers doit fournir un résultat de type entier. Ceci est effectivement le cas pour :
- l’addition 3 + 5 donne 8
- la soustraction 3 – 5 donne -2
- la multiplication 3 * 5 donne 15
Mais la division (/) pose un problème :
- le quotient de 6 par 4 donne 1.5 qui n’est pas un nombre entier.
- le quotient de 6 par 3 donne 2.0 qui n’est pas un nombre entier.

/ donne toujours un résultat réel (jamais entier)

II a donc fallu implémenter une division, spécifique aux nombres entiers, qui conserve
le type des opérandes

La division entière s’écrit div

6 div 4 donne 1
10 div 3 donne 3

24
Types et expressions Concepts de base

Le résultat de cette division correspond à la troncature de la partie décimale. Parallè-


lement à cette division entière, il est souvent utile de connaître le reste de la division entre
deux nombres entiers.

On obtient le reste d’une division entière avec mod

10 mod 3 donne 1
23 mod 4 donne 3

Lorsque des opérateurs et des opérandes sont combinés de manière à former une ex-
pression, il est nécessaire d’avoir une convention permettant de l’évaluer. Ainsi l’expres-
sion 4 ∗ 2 + 3 donnera-t-elle le résultat 11 ou bien 20 ? Tout dépend de l’ordre dans lequel
sont effectuées les opérations. Les conventions d’évaluation en vigueur en Pascal corres-
pondent à des règles de priorité (cf. Figure 2.5, page 29), semblables à celles qui existent
en mathématique :
- les opérateurs div, mod, et * sont prioritaires par rapport aux opérateurs + et - ;
- dans chacune de ces deux catégories les opérateurs ont la même priorité ;
- en cas d’égalité de priorité, les opérations concernées sont effectuées de gauche à
droite.

Ainsi :
4 * 2 + 3 donne 11
8 + 4 * 3 div 2 donne 14
6 mod 4 * 2 div 3 donne 1

Pour modifier ces règles de priorité, il est toujours possible d’utiliser les parenthèses :
4 * (2 + 3) donne 20
7 div ((5 mod 3) mod 4) donne 3

II est également possible de faire précéder un nombre par l’opérateur unaire "-" :
−4 * 1 2 donne −48
4 * ( − 5) donne −20

Base 16 on peut écrire un entier en hexadécimal en utilisant le symbole $. Par exemple


$FF (255).
Infini on obtient le plus grand entier (integer) en écrivant MaxInt

25
Types et expressions Concepts de base

2.6.2 Les types réels


Les différents types réels se différencient par leur domaine de définition, le nombre de
chiffres significatifs (précision) et la place mémoire occupée. Le tableau suivant résume
ces différentes caractéristiques :

Type Intervalle Chiffres Taille en octets


Single 1.5 × 10−45 .. 3.4 × 1038 7-8 4
Real 5.0 × 10 −324
.. 1.7 × 10 308
15-16 8
Double 5.0 × 10−324 .. 1.7 × 10308 15-16 8
Extended 1.9 × 10−4932 .. 1.1 × 104932 19-20 10
−922337203685477.5808 ..
Currency 19-20 8
922337203685477.5807

Figure 2.2 – Les types réels

2.6.3 Conversion réels ⇐⇒ entiers


1. II existe deux manières de convertir une valeur réelle en valeur entière : l’arrondi
et la troncature. Le Pascal dispose de deux fonctions standard qui effectuent ces
opérations sur les nombres réels.

La troncature

La fonction Trunc agit de manière à tronquer la partie décimale d’un nombre réel.
Son utilisation est illustrée par les exemples qui suivent :
trunc (4.2) donne 4
trunc (4.99) donne 4
trunc ( −12.6) donne −12
trunc (3.01) donne 3

r := 5.67; { r est de type ré e l }


i := trunc (r ); { i est de type entier et contient 5}

L’arrondi

La fonction Round permet d’arrondir un nombre réel à l’entier le plus proche :


round (2.99) donne 3
round (2.5) donne 2
round (2.50000001) donne 3
round (2.499) donne 2
round ( −7.8) donne −8

r := 4.77; { r est de type ré e l }


i := round (r ); { i est de type entier et contient 5}

26
Types et expressions Concepts de base

Remarques : partie décimale et fractionnaire

- La fonction Frac renvoie la partie décimale d’une expression de type réel. Le


résultat est un réel.
Frac ( pi ) donne 0.14159265358979324

- La fonction Int renvoie la partie entière d’une expression de type réel. Le ré-
sultat est un réel.
Int ( pi ) donne 3.0

2. La conversion d’une valeur entière en une valeur réelle s’effectue sans passer par
des fonctions spécifiques. Lors de l’affectation d’une expression de type entier à
une variable de type réel, la conversion de type est implicite. Dans les instructions
qui suivent, a et b sont des variables de type entier et c de type réel :
a := 6;
b := 2;
c := 2 * a + b; { c contiendra la valeur 14.0 }

Très souvent le programmeur est confronté à des expressions mixtes, contenant aussi
bien des valeurs entières que réelles. Dans ce cas, le résultat sera de type réel.
c := 15 div a; // c contiendra 2.0
c := 15 / a; // c contiendra 2.5
c := 1.5 * (a + b) ; // c contiendra 12.0

Infini on obtient le plus grand réel (real) en écrivant Infinity qui est défini dans l’unité
math (”uses math” nécessaire au début du programme).

2.6.4 Type booléen (boolean)


L’ensemble des valeurs constituant le type booléen (boolean) est réduit à deux identifi-
cateurs de constantes prédéfinies : true (vrai) et false (faux). On parle souvent de variables
ou d’expressions logiques, car le langage Pascal est fortement inspiré de la logique ma-
thématique en ce qui concerne les opérations associées au type booléen. Les constantes et
variables de ce type se déclarent de la manière suivante :
const demo = true ;
var majuscules , termine : boolean ;

La constante demo a la valeur true ; les variables majuscules et termine peuvent recevoir
les valeurs true ou false, selon leur utilisation dans le programme.

27
Types et expressions Concepts de base

Parmi les opérateurs booléens on trouve, dans une première catégorie, les opérateurs
relationnels et dans une seconde catégorie, les opérateurs logiques.
- La première catégorie d’opérateurs booléens est constituée des opérateurs relation-
nels :

< plus petit


> plus grand
= égal
<> différent
<= inférieur ou égal
>= supérieur ou égal

Figure 2.3 – Opérateurs relationnels

Ces opérateurs se rencontrent dans les expressions booléennes correspondant à des


conditions. Comme nous le verrons plus loin, les conditions interviennent notam-
ment dans les instructions sélectives et répétitives.
- La seconde catégorie d’opérateurs booléens est constituée par des opérateurs pu-
rement logiques. Ils sont au nombre de quatre, et sont illustrés ci-dessous par des
exemples :

not (non) négation logique si x > 12 est vrai, alors not (x > 12) est faux
(x > 2) and (x < 10) est vrai, si (x > 2) est vrai et
and (et) conjonction logique
(x < 10) est vrai
(x < 2) or (x > 10) est vrai, si (x < 2) est vrai ou
or (ou) disjonction logique
(x > 10) est vrai
a xor b est vrai si a et b n’ont pas la même valeur
xor (ou exclusif) exclusion logique
logique

Figure 2.4 – Opérateurs logiques

Comme il est possible, et même très courant, de construire des expressions logiques
contenant aussi bien des opérateurs arithmétiques que logiques, il convient d’étendre les
conventions de priorité établies précédemment.

28
Types et expressions Concepts de base

Nous avons quatre classes d’opérateurs indiquées dans la liste qui suit, en partant de la
plus prioritaire :

1. ()
2. not
3. * / div mod and
4. + - or xor
5. = <> < > <= >=
Figure 2.5 – Précédence des opérateurs

Dans chacune des classes, les opérateurs ont la même priorité. En cas d’égalité de
priorité, les opérations correspondantes sont effectuées de gauche à droite. Les paren-
thèses peuvent servir à forcer la priorité. Voici, à titre d’exemple, comment s’exprimerait
en Pascal l’expression "somme est comprise entre 10 et 35" :
( somme >= 1 0 ) and ( somme <= 3 5 )

Examinons deux autres exemples d’expressions booléennes :


age < date + 100

il s’agit ici de comparer le contenu de la variable age avec le résultat de date + 100. L’opé-
rateur + a une plus grande priorité que l’opérateur <. De ce fait, cette expression booléenne
est équivalente à
age < ( date + 100)

Mais
a g e < 40 and revenu > 6000

cette expression provoquera un message d’erreur de la part du compilateur, car elle pré-
sente un conflit de types. En effet, la priorité de l’opérateur and étant plus élevée que celle
des opérateurs relationnels < et >, elle sera interprétée comme
age < (40 and revenu ) > 6000

qui n’est pas une expression correcte. Il faudra écrire


( age < 40) and ( revenu > 6000)

29
Types et expressions Concepts de base

2.6.5 Type caractère (char)


Ce type dénote un ensemble de caractères, fini et ordonné. Chacun de ces caractères
peut être exprimé grâce à son code ASCII. Une variable de type caractère (char) peut conte-
nir un seul caractère, généralement spécifié entre apostrophes. Comme nous le verrons plus
loin, il est possible de constituer des suites de caractères appelées chaînes de caractères.
Voici un petit programme qui met en évidence l’emploi des variables et constantes de type
caractère :
const effe = 'F ' ;
var lettre : char ;
bip : char ;
begin
bip := Chr (7);
lettre := 'h ' ;
end ;

Dans cet exemple, la constante effe contient une lettre majuscule indiquée entre apos-
trophes et la variable bip contient le caractère dont le code ASCII est 7. Ce code correspond
à l’émission d’un bref signal sonore par le haut-parleur de l’ordinateur. La fonction prédé-
finie Chr permet de référencer tous les caractères, y compris certains caractères du code
ASCII qui ne sont pas affichables. L’argument de cette fonction est précisément le code
ASCII du caractère désiré. Pour connaître le code des caractères disponibles, il convient
de se reporter au manuel de référence de l’ordinateur utilisé.
On peut aussi écrire un caractère en faisant précéder son code par le symbole #. Cette
notation est équivalente à la fonction Chr et permet, par exemple, d’incorporer des carac-
tères particuliers dans une chaîne de caractères.
#27 'G '

cette suite de caractères comprend le caractère correspondant à la touche <Esc>, suivi du


caractère G. ;
if c = #13 then ...

Cette instruction permet de déterminer si la variable c (de type caractère) contient le ca-
ractère correspondant à la touche <Return>. On aurait également pu écrire :
if c = chr (13) then ...

30
Types et expressions Concepts de base

2.6.6 Les chaînes de caractères (String)


[Link] Définitions
- Une chaîne de caractères est un ensemble de caractères délimité par des apostrophes (’).
Elles se définissent par String, AnsiString ou WideString.
- Le type String peut faire référence à ShortString ou AnsiString, selon la bascule
{$H}. Si la bascule est off ({$H-}) alors toute déclaration String va définir un ShortS-
tring. Sa taille sera de 255 caractères, si elle n’est pas spécifiée autrement. Si la bas-
cule est on ({$H+}), String sans spécifier la taille va définir un AnsiString, sinon un
ShortString avec une taille spécifiée.
Par défaut, un String est un AnsiString.
- Une variable de type WideString ou AnsiString n’a pas de limite quant au nombre
de caractères.
- On peut limiter la taille d’une chaîne en écrivant String[n] où n ≤ 255.

[Link] Le traitement des chaînes de caractères


Remarque Seules, quelques fonctions ou procédures qui manipulent les chaînes seront
traitées ici.

Concaténation (regroupement) de chaînes On regroupe deux ou plusieurs chaînes en


utilisant l’opérateur + 4 .
Exemple
ch1 := ' Bonjour ' ;
ch2 := ' tout le monde ! ' ;
ch3 := ch1 + ch2 ; // ch3 vaut 'Bonjour tout le monde !'

Longueur d’une chaîne La longueur d’une chaîne correspond à son nombre de carac-
tères. On l’obtient grâce à Length.
Exemple
s := ' Bonjour tout le monde ! ' ;
nbCar := Length (s ); // nbCar vaut 22

Extraction de caractères
- Pour extraire un seul caractère d’une chaîne, on utilise [position] où position est
l’indice du caractère souhaité. position commence à un : le premier caractère de la
chaîne s s’obtient en écrivant s[1], le second s[2], · · · .
Exemple
s := ' Bonjour tout le monde ! ' ;
car := s [6]; // car vaut 'u'

4. Concat permet aussi d’ajouter une chaîne à une autre

31
Types et expressions Concepts de base

- Pour extraire plusieurs caractères d’une chaîne, c’est-à-dire extraire une sous-chaîne,
on utilise copy(chaine, debut, combien).
Exemples
s := ' Bonjour tout le monde ! ' ;
ch := copy (s ,6 ,5); // ch vaut 'ur to'

Comparaison de chaînes Pour déterminer l’égalité de deux chaînes en tenant compte


de la casse des caractères, on utilise l’opérateur =.
Exemples
s1 := ' Bonjour ' ;
s2 := ' Bonjour ' ;
//s1 = s2 est vrai (true)
s1 := ' Bonjour ' ;
s2 := ' bonjour ' ;
// s1 = s2 est faux (false)

Changement de la casse des caractères


- UpCase convertit tous les caractères d’une chaîne en majuscules.
Exemple
s1 := ' Bonjour ' ;
s2 := UpCase ( s1 ) ; // s2 vaut BONJOUR

UpCase permet aussi de mettre un caractère en majuscule ; elle retourne alors un


caractère.
- LowerCase convertit tous les caractères d’une chaîne en minuscules. Les caractères
non alphabétiques ne sont pas affectés par l’opération.
Exemple
s1 := ' Bonjour ' ;
s2 := LowerCase ( s1 ) ; // s2 vaut bonjour

LowerCase permet aussi de mettre un caractère en minuscule ; elle retourne alors


un caractère.

32
Types et expressions Concepts de base

Recherche dans des chaînes Pos recherche la première occurrence d’un caractère ou
d’une chaîne dans une chaîne. Si le caractère ou la chaîne n’est pas inclus dans la chaîne,
le résultat de Pos est 0 sinon le résultat est le premier endroit où se trouve le caractère ou
la chaîne (commence à un).
Exemples
s1 := ' Bonjour ' ;
car := 'o ' ;
endroit := Pos ( car , s1 ) ; // endroit vaut 2

s1 := ' Bonjour ' ;


s2 := ' njo ' ;
endroit := Pos ( s2 , s 1 ) ; // endroit vaut 3

s1 := ' Bonjour ' ;


s2 := ' xy ' ;
endroit := Pos ( s2 , s 1 ) ; // endroit vaut 0 car xy n'est pas dans Bonjour

Effacement de caractères dans une chaîne Pour effacer des caractères d’une chaîne,
on utilise la procédure Delete(chaine, debut, combien).
Exemple
s := ' Bonjour tout le monde ! ' ;
Delete (s ,5 ,3); // s vaut 'Bonj tout le monde !'

Insertion d’une chaîne dans une autre Pour insérer une chaîne dans une autre, on
utilise la procédure Insert(chaineAInserer, cible, position).
Exemple
Cible := ' 12345678 ' ;
Insert ( '+++ ' , Cible , 3); // Cible vaut '12+++345678'

Créer une chaîne formée du même caractère Pour créer une chaîne formée de plu-
sieurs fois le même caractère, on utilise la fonction StringOfChar(car, nombre).
Exemple
etoile := StringOfChar ( '* ' , 10); // **********

Transformation en numérique et inversement


- La procédure Str transforme une valeur numérique en chaîne. Par exemple,
Str (25 , ch1 ) met ' 25 ' ( une c h a î ne ) dans ch1
Str ( pi , ch2 ) met la valeur de pi dans une chaîne

- La procédure Val transforme une chaîne en valeur numérique, si possible. Par exemple,
Val ( ' 25 ' , i , c o d e ) met 25 (entier) dans i et code sera égal à 0
Val ( ' bonjour ' , i , code ) n'est pas possible, code n'est pas nul et i est indéni
Val ( ' 3 . 1 4 ' , x , code ) met une approximation de π dans la variable x (supposée réelle)

- La fonction Chr convertit un code ASCII en caractère. Par exemple,


write chr ( (170)); // Caractère

33
Types et expressions Concepts de base

Figure 2.6 – Quelques codes ASCII

Voici le code (assez pénible) pour afficher le cadre suivant

program Cadre ;
var ligneHaut : string ;
ligneBlancs string
: ;
ligneMilieu string
: ;
ligneBas : string ;
begin
ligneHaut chr
:= StringOfChar chr
(218) + ( chr (196) ,20) + (194) +
StringOfChar chr ( chr
(196) ,20) + (191);
ligneBlancs chr
:= StringOfChar
(179) + chr
( ' ' ,20) + (179) +
StringOfChar chr
( ' ' ,20) + (179);
ligneMilieu chr
:= StringOfChar chr
(195) + ( chr (196) ,20) + (197) +
StringOfChar chr ( chr
(196) ,20) + (180);
ligneBas chr
:= StringOfChar chr
(192) + ( chr (196) ,20) + (193) +
StringOfChar chr ( chr
(196) ,20) + (217);

writeln ( ligneHaut ) ;
writeln ( ligneBlancs );
writeln ( ligneBlancs );
writeln ( ligneBlancs );
writeln ( ligneMilieu );
writeln ( ligneBlancs );
writeln ( ligneBlancs );
writeln ( ligneBlancs );
writeln ( ligneBas ) ;

readln ;
end .

34
Types et expressions Concepts de base

Pour faciliter le travail, l’utilisation de constantes pourrait être utile. Par exemple,
const CGH = chr (218); // Coin Gauche Haut
CDH = chr (191); // Coin Droit Haut
CBG = chr (192); // Coin Bas Gauche
CBD = chr (217); // Coin Bas Droit
VERT = chr (179); // Verticale
VD = chr (195; // Vertical Droite
CG = chr (180); // Vertical Gauche
HORIZ = chr (196); // Horizontale
HB = chr (194); // Horizontal Bas
HH = chr (193; // Horizontal Haut
CROIX = chr (197); // Croix

Le code s’écrira :
ligneHaut := CGH + StringOfChar (HORIZ,20) + HB + StringOfChar (HORIZ,20) + CDH ;
ligneBlancs := VERT + StringOfChar (' ',20) + VERT + StringOfChar (' ',20) + VERT ;
.
.
.

Quelques caractères accentués

chr(133) à chr(131) â chr(132) ä


chr(130) é chr(138) è chr(136) ê chr(137) ë
chr(140) î chr(139) ï
chr(147) ô
chr(150) û chr(151) ù chr(154) ü
chr(135) ç

Figure 2.7 – Quelques codes ASCII : les caractères accentués

[Link] Autres fonctions ou procédures qui manipulent les chaînes


Toutes les fonctions ou procédures traitées dans ce point font partie de l’unité System
(elles s’utilisent sans uses explicite). Il en existe encore une multitude d’autres, définies
dans les unités SysUtils et StrUtils (uses est alors nécessaire).
On peut citer dans StrUtils :

- RightStr qui extrait des caractères à partir de la fin


writeln ( RightStr ( ' abcdefghijklmnopqrstuvwxyz ' , 10)); // qrstuvwxyz

- NPos qui calcule la position de la ne occurrence d’une sous-chaîne dans une chaîne.
writeln ( NPos ( ' ab ' , ' a b c d e a b c e a b x y z ' , 3)); // 10

- PadLeft qui ajoute des espaces au début d’une chaîne jusqu’à ce qu’une certaine
longueur soit atteinte.
writeln ( PadLeft ( ' 1234 ' , 6)); // deux espaces suivis de 1234

35
Types et expressions Concepts de base

- PadRight qui ajoute des espaces à la fin d’une chaîne jusqu’à ce qu’une certaine
longueur soit atteinte.
writeln ( PadRight ( ' 1234 ' , 6)); // 1234 suivi de deux espaces

- PosEx qui recherche la position d’une sous-chaîne dans une chaîne en commençant
à un position spécifiée.
writeln ( PosEx ( ' ab ' , ' a b c d e a b c e a b x y z ' , 8)); // 10

- ReverseString qui inverse une chaîne de caractères.


writeln ( R e v e r s e S t r i n g ( ' abcde ' ) ) ; // 'edcba'

- WordCount qui compte le nombre de mots d’une chaine.


writeln ( WordCount ( ' C e c i est une c h a i n e ' , StdWordDelims ) ) ; // 4

Remarque StdWordDelims = [#0..' ', ',', '.', ';', '/', '\', ':', , '"', '`'] + Brackets

- RPos qui recherche la dernière position d’une sous-chaîne dans une chaîne.
writeln ( RPos ( ' ab ' , ' a b c d e a b c e a b x y z ' ) ) ; // 10

- RPos qui recherche la dernière position d’une sous-chaîne dans une chaîne.
writeln ( RPos ( ' ab ' , ' a b c d e a b c e a b x y z ' ) ) ; // 10

.
- ..

On peut citer dans SysUtils :

- StringReplace qui remplace les occurrences d’une sous-chaîne par une autre dans
une chaîne.
writeln ( S t r i n g R e p l a c e ( ' a b c d e a b c e a b x y z ' , ' ab ' , ' mno ' , [ r f R e p l a c e A l l ] ) ) ;
// 'mnocdemnocemnoxyz'

- TrimLeft qui supprime les espaces au début d’une chaîne.


writeln ( TrimLeft ( ' Des espaces ' )); =⇒ ' Des espaces '

- TrimRight qui supprime les espaces à la fin d’une chaîne.


writeln ( TrimRight ( ' Des espaces ' )); =⇒ ' Des espaces '

.
- ..

2.6.7 Autres types de données


D’autres types de données existent en Pascal. Il s’agit, entre autres, du type énuméré,
du type intervalle, du type ensemble, du type pointeur, du type tableau, du type fichier.
Ces types seront étudiés plus tard.

36
CHAPITRE 3
LES INSTRUCTIONS EN PASCAL

3.1 Les commentaires


Les commentaires ont été étudiées à la page 21.
Résumé on écrit des commentaires dans un programme en les entourant de (* *) ou { }.
Pour les commentaires d’une seule ligne, on peut utiliser //.
Les commentaires sont ignorés par le compilateur.

3.2 L’affectation
Cf. page 22.
Résumé il est possible d’affecter une valeur à une variable grâce à :=
Par exemple,
i := 10;
ch := ' Quel est votre nom ? ' ;
x := cos pi ( * sqrt (2)) / arctan (10);

3.3 Lecture et écriture


3.3.1 Lecture du contenu d’une variable au clavier
Le but est de mettre une valeur dans une variable grâce au clavier. Autrement dit, ce
que l’utilisateur va taper sur son clavier « va aller » dans la variable.
L’opération qui consiste à remplir le contenu d’une variable à partir du clavier s’appelle
une lecture.
- Dans un algorithme, on écrira
lire v où v est une variable quelconque

37
Lecture et écriture Les instructions en Pascal

- dans un organigramme, on représente la lecture par

- en Pascal, la lecture est accomplie avec l’instruction readln


readln (v );

3.3.2 Écriture du contenu d’une variable à l’écran


L’opération qui consiste à afficher la valeur d’une variable à l’écran s’appelle une écri-
ture.
- Dans un algorithme, on écrira
écrire v où v est une variable quelconque

ou
ache v

- dans un organigramme, on représente l’écriture par

- en Pascal, pour afficher la valeur d’une variable sur une console DOS, il faut écrire
write ( expr1 [ , expr2 . . . , ] ) ;

ou
writeln ( expr1 [ , expr2 . . . , ] ) ;

où expr est une expression contenant une chaîne de caractères, une variable ou une
constante. Dans la première expression, le curseur reste à la fin du texte affiché, dans
la seconde, le curseur se place au début de la ligne suivante.

3.3.3 Exemple
program demo ;
var i : integer ; // Déclaration de la variable
begin
write ( ' Entrez un nombre entier : ' ); // Ache ce message
readln ( i );

// Achage d'un message suivi du contenu de la variable i


writeln ( ' Le nombre que vous avez introduit vaut ' , i );

// Pour "ger" l'achage


readln ;
end .

38
Lecture et écriture Les instructions en Pascal

Voici le résultat :

3.3.4 Exercices
1. Afficher bonjour à l’écran.
2. Afficher une carte de visite à l’écran.
3. Calculer la somme et le produit de deux nombres réels.
4. Calculer l’aire et le périmètre d’un rectangle connaissant sa largeur et sa hauteur.
5. Calculer le volume de la sphère.
4
V olume = πRayon3
3
On obtient la valeur de π en écrivant pi.
6. Échanger le contenu de deux variables.
7. Lire deux entiers, afficher le quotient et le reste de la division.
8. Lire une température donnée en degrés Celsius et l’afficher en degrés Fahrenheit.
9 5
F ahrenheit = Celsius + 32 ⇐⇒ Celcius = (F ahrenheit − 32)
5 9
9. Lire une température donnée en degrés Fahrenheit et la transformer en degrés Cel-
cius.
10. Lire un nombre de secondes et le traduire sous la forme d’heures, minutes et se-
condes.
(4354 secondes = 1 heure 12 minutes 34 secondes).
11. Transformer un angle donné en radians en degrés.
180 π
degre = radian ⇐⇒ radian = degre
π 180
12. Transformer un angle donné en degrés en radians.
13. Lire un nombre de degrés, minutes, secondes et le transformer en radian.
(Il faut d’abord réaliser le passage Degrés Minutes Secondes en degrés)
14. Lire un angle en radian et le transformer en degrés, minutes, secondes et millièmes
de seconde.
15. Lire un nombre de jours et le transformer sous la forme d’années, mois et jours en
supposant qu’un mois contiendra toujours trente jours.
16. Calculer la résistance (électrique) R de trois résistances en parallèle R1 , R2 , R3 ,.
1 1 1 1
= + +
R R1 R2 R3

39
Les tests Les instructions en Pascal

17. Calculer le périmètre et l’aire d’un triangle dont on connaît la longueur des 3 côtés.
r
p p p p
Aire = ( − cote1 )( − cote2 )( − cote3 )
2 2 2 2
où p est le périmètre du triangle (p
√ = cote1 + cote2 + cote3 ).
On obtient la racine carrée de x ( x) en écrivant sqrt(x) 1 .
18. Lire trois chaînes de caractères et les afficher en une seule chaîne.
19. Calculer le temps écoulé entre deux événements.

3.4 Les tests


3.4.1 La structure alternative
En français, une alternative est un choix entre deux possibilités. La structure alterna-
tive peut s’écrire :

si condition alors
action1(s)
sinon
action2(s)
fin

Signification : si la condition est vérifiée, les actions action1(s) seront exécutées ; dans le
cas contraire, les actions action2(s) seront exécutées.
Dans les organigrammes, le losange représente une alternative

Figure 3.1 – L’alternative

En Pascal, on écrira :
if condition then
begin
instruction ( s ) séparé e s par des ;
end
else
begin
instruction ( s ) séparé e s par des ;
end ;

1. Le carré de x peut s’obtenir en écrivant sqr(x)

40
Les tests Les instructions en Pascal

Remarques : Il est interdit de mettre un point-virgule avant ELSE.


Les mots BEGIN et END ne sont nécessaires que s’il y a plusieurs instructions.
La partie ELSE est facultative.

Exemple : lire un nombre entier et dire s’il est strictement positif.

lire I
si I > 0 alors
écrire ’Le nombre est strictement positif’
sinon
écrire ’Le nombre est négatif ou nul’
fin

program test ;
var i : // Déclaration de la variable
integer ;
begin
write ( ' Entrez un nombre entier : ' );
readln // Lecture au clavier
( i );

if then
i > 0
writeln ( ' Le nombre est strictement positif ')
else
writeln ( ' Le nombre est negatif ou nul ' ) ;

readln ;
end .

41
Les tests Les instructions en Pascal

3.4.2 Le choix multiple


Supposons qu’on veuille afficher le jour de la semaine connaissant son numéro (1=di-
manche, · · · , 7=samedi).

On peut écrire en utilisant la structure al- ou encore


ternative :
if numJour = 1 then if numJour = 1 then
write ( ' Dimanche ' ) write ( ' Dimanche ' ) ;
else i f numJour = 2 then if numJour = 2 then
write ( ' Lundi ' ) write ( ' Lundi ' ) ;
else i f numJour = 3 then if numJour = 3 then
write ( ' Mardi ' ) write ( ' Mardi ' ) ;
else i f numJour = 4 then if numJour = 4 then
write ( ' Mercredi ' ) write ( ' Mercredi ' ) ;
else i f numJour = 5 then if numJour = 5 then
write ( ' Jeudi ' ) write ( ' Jeudi ' ) ;
else i f numJour = 6 then if numJour = 6 then
write ( ' Vendredi ' ) write ( ' Vendredi ' ) ;
else i f numJour = 7 then if numJour = 7 then
write ( ' Samedi ' ) ; write ( ' Samedi ' ) ;

Le mieux est certainement d’utiliser le choix multiple :

suivant numJour faire


cas où 1 faire Afficher ’Dimanche’;
cas où 2 faire Afficher ’Lundi’;
cas où 3 faire Afficher ’Mardi’;
cas où 4 faire Afficher ’Mercredi’;
cas où 5 faire Afficher ’Jeudi’;
cas où 6 faire Afficher ’Vendredi’;
cas où 7 faire Afficher ’Samedi’;
fin

42
Les tests Les instructions en Pascal

Dans les organigrammes, on peut représenter un choix multiple de la manière suivante :

Figure 3.2 – Le choix multiple

En Pascal,
case numJour of
1 : write ( ' Dimanche ' ) ;
2 : write ( ' Lundi ' ) ;
3 : write ( ' Mardi ' ) ;
4 : write ( ' Mercredi ' ) ;
5 : write ( ' Jeudi ' ) ;
6 : write ( ' Vendredi ' ) ;
7 : write ( ' Samedi ' ) ;
end ;

Cette nouvelle structure agit en fait à la manière d’un test à multiples branches. Pour
chaque branche l’égalité entre la valeur de numJour et la constante correspondante est
vérifiée. Si effectivement la valeur de numJour équivaut à une des constantes, l’instruction
ou le bloc d’instructions (pour rappel, un bloc d’instructions est un ensemble d’instructions
séparés par les mots Begin et End) correspondant sont exécutés. Si la valeur du sélecteur
ne correspond à aucune des constantes indiquées l’exécution du programme se poursuit
après la structure sélective.

43
Les tests Les instructions en Pascal

Une branche supplémentaire indiquée par un else permet l’exécution d’une instruction
ou d’un bloc d’instructions au cas où la valeur du sélecteur ne correspond à aucune des
constantes spécifiées. L’exemple qui suit illustre cette possibilité :
case numJour of
1 write
: ( ' Dimanche ' ) ;
2 write
: ( ' Lundi ' ) ;
3 write
: ( ' Mardi ' ) ;
4 write
: ( ' Mercredi ' ) ;
5 write
: ( ' Jeudi ' ) ;
6 write
: ( ' Vendredi ' ) ;
7 write
: ( ' Samedi ' ) ;
else
write ( ' Erreur ' ) ;
end ;

Remarquons qu’avant le mot réservé else d’une structure case peut se trouver un point
virgule.
Dans chaque branche d’une instruction case, on peut indiquer plus d’une valeur (2,4,7),
et même un intervalle de valeurs (2..7). Par exemple,
case resultat of
1..5: Valeur := ' Low ' ;
6..9: Valeur := ' High ' ;
0, 10..99: Valeur := ' Hors limite ' ;
else
Valeur := ' ' ;
end ;

S’il y a plusieurs instructions dans une branche du case, il faut les entourer de begin
et end.
case resultat of
1 : begin
resultat := 1;
writeln ( ' Resultat = ' , resultat );
end ;
.
.
.

Comme d’habitude, le langage (Pascal) autorise l’utilisation de begin et end même s’il n’y
a qu’une seule instruction.

Voir la solution de l’exercice en page 174 pour un exemple plus détaillé d’un choix
multiple.

44
Les tests Les instructions en Pascal

3.4.3 Exercices
1. Afficher le plus grand et le plus petit de deux nombres réels.
2. Calculer la racine carrée si cette opération est possible.
3. Résoudre l’équation du second degré.

Lire a,b,c
δ = b2 − 4ac
si δ > 0 alors √
racine1 = −b+ 2a√
δ

racine2 = −b− 2a
δ

sinon si δ = 0 alors
−b
racine1 = racine2 = 2a
sinon
Pas de racine
fin

4. Lire trois nombres, en écrire le plus petit, le plus grand.


5. Résoudre le même problème que précédemment mais avec six nombres.
6. Déterminer si une année A est bissextile. Une année A est bissextile si A est multiple
de 4, toutefois, les années séculaires ne sont bissextiles que si A est multiple de 400.
7. On appelle nombre d’Armstrong un nombre de trois chiffres tel que sa valeur égale
la somme des cubes de ses chiffres. Par exemple,

153 = 13 + 53 + 33

Lire un nombre et afficher si c’est un nombre d’Armstrong (les nombres d’Armstrong


sont 153, 370, 371 et 407) ;
8. Déterminer si un triangle est rectangle, connaissant la longueur des trois côtés. Un
triangle est rectangle si C 2 = A2 + B 2 .
A, B, C sont les trois côtés du triangle, C étant l’hypoténuse.
9. Calculer le prix à payer si une réduction de 5% est accordée sur la partie qui dépasse
100 €.
10. Afficher la position de la droite ax + by + c = 0 par rapport aux axes (parallèle à
l’axe X, parallèle à l’axe Y, oblique).
11. Lire un caractère, le programme teste s’il s’agit d’une lettre majuscule, si oui, il
renvoie cette lettre en minuscule, sinon il renvoie un message d’erreur.
12. Lire deux chaînes de caractères et afficher à partir de quel endroit on retrouve la
première dans la seconde ; si elle ne s’y trouve pas, afficher "La première chaîne
n’est pas dans la seconde".
13. Lire un caractère, déterminer si ce caractère est une lettre, un chiffre ou un autre
caractère.
14. Lire une chaîne de caractères, écrire si elle commence ou se termine par une consonne
ou une voyelle.

45
Les tests Les instructions en Pascal

15. Lire deux réels et un symbole au clavier.


- si le symbole vaut ’+’, on additionne les deux réels,
- si le symbole vaut ’-’, on soustrait le second réel du premier,
- si le symbole vaut ’*’ ou ’.’, on multiplie les deux réels,
- si le symbole vaut ’/’ ou ’ :’, on divise le premier réel par le second,
- si le symbole ne vaut aucune de ces valeurs, le programme indique qu’il y a eu
une erreur
16. Lire deux chaînes de caractères et supprimer, si elle s’y trouve, la seconde de la
première.
17. Lire le nom d’un fichier (une chaîne). Le programme vérifie que celui-ci possède
l’extension « PAS ».
Indication Une extension n’a pas toujours trois caractères mais est toujours précé-
dées de “.”.
18. Lire une expression sous forme de chaîne et l’évaluer.
Exemples :
- 8+9
- 187 / 54
- 24 div 7
- 24 mod 7
Simplification On suppose qu’on évalue une expression simple, c’est-à-dire deux
opérandes entières et un opérateur.
19. Déterminer le jour de la semaine correspondant à une date donnée. Les jours de la
semaine sont codifiés de la manière suivante :
0 −→ dimanche, 1 −→ lundi, 2 −→ mardi, · · · , 6 −→ samedi.
Le numéro de jour de la semaine est fourni par la valeur de
(N + AN + J + 5 × S) mod 7 où
- S indique les deux premiers chiffres du millésime,
- AN les deux derniers chiffres du millésime pour tous les mois sauf
janvier et février, auquel cas, il faut diminuer ce nombre d’une unité,
- J représente le numéro du jour dans le mois,
- N est fourni par la relation
−1
N = b 13×M
5
c + b S4 c + b AN
4
c
Pour janvier et février, M vaut respectivement 11 et 12 et pour les
autres mois, M est le numéro du mois diminué de 2 unités.

46
Les structures répétitives ou boucles Les instructions en Pascal

3.5 Les structures répétitives ou boucles


Il est souvent nécessaire d’indiquer qu’un ensemble d’instructions doit être exécuté
plusieurs fois. Le langage Pascal contient trois méthodes pour répéter des instructions. Il
est possible d’exécuter des instructions
1. un certain nombre de fois (For),
2. tant qu’une condition est vérifiée (While) ou
3. jusqu’à ce qu’une condition soit vérifiée (Repeat).

3.5.1 La boucle while (Tant Que)


La boucle While dit à l’ordinateur de répéter des actions tant qu’une certaine condition
est vérifiée. La structure est la suivante :

tant que condition faire


action(s)
fin

Figure 3.3 – La boucle While

la traduction en Pascal est :


while condition do
begin
instruction ( s )
end;

Remarques :
- L’ordinateur exécute les instructions indiquées entre BEGIN et END tant que la
condition est vraie.
- BEGIN et END sont facultatifs s’il n’y a qu’une seule instruction à exécuter.

47
Les structures répétitives ou boucles Les instructions en Pascal

Exemple 1 Lire un nombre n au clavier. Afficher une ligne de n « * »


Ainsi,
- si le nombre entré au clavier est 2, le programme doit afficher **
- si le nombre entré au clavier est 5, le programme doit afficher *****
- si le nombre entré au clavier est 10, le programme doit afficher **********

Lire N
Etoile ← 0 // Etoile est le nombre d’étoiles déjà affiché
N étoiles ont-elles déjà été affichées ?
tant que Etoile ≤ N faire
Afficher *
Etoile ← Etoile + 1 // Une étoile vient d’être affichée
fin

1 program Etoiles ;
2 ( * ******************************************************
3 * L i r e ( s a i s i r ) un nombre n au c l a v i e r *
4 * A f f i c h e r une l i g n e d e n e t o i l e s *
5 ****************************************************** * )
6 var n : // Le nombre d'étoiles à acher
integer ;
7 etoile : // Le nombre d'étoiles déjà achées
integer ;
8 begin
9 //Saisie du nombre d'étoiles à acher
10 Write −
( ' Combien d ' ' e t o i l e s voulez vous afficher ? ' );
11 Readln (n ) ;
12
13 // Achage des étoiles
14 etoile := 0;
15 while e t o i l e <= n do
16 begin
17 Write ( '* ' ); // Pas Writeln pour éviter le retour à la ligne
18 e t o i l e += 1 ; // ou etoile := etoile + 1
19 end ;
20
21 Readln ;
22 end .

48
Les structures répétitives ou boucles Les instructions en Pascal

Exemple 2 Lire (saisir) un nombre n au clavier. Afficher les nombres de n jusqu’à 1 en


diminuant de 1 à chaque fois
Ainsi,
- si le nombre entré au clavier est 5, le programme doit afficher 5 4 3 2 1
- si le nombre entré au clavier est 8, le programme doit afficher 8 7 6 5 4 3 2 1

Lire N
I←N // Au départ, le premier nombre à afficher vaut N
Est-on arrivé à 1 ?
tant que I ≥ 1 faire
Afficher I
I ← I − 1 // On diminue I de 1
fin

1 program CompteARebours ;
2 ( * ***********************************************************
3 Lire ( saisir ) un nombre n au clavier . Afficher les
4 nombres de n j u s q u 'à 1 en diminuant de 1 à chaque fois .
5 *********************************************************** * )
6 var n : // Le nombre à partir duquel le compte à rebours commence
integer ;
7 i : // Variable de travail
integer ;
8 begin
9 // Saisie du nombre
10 Write ( ' Nombre de depart ? ' );
11 Readln (n ) ;
12
13 i := n;
14 // Achage du compte à rebours
15 while i >= 1 do
16 begin
17 Write (i , ' ' ); //Pas writeln pour éviter le retour à la ligne
18 − i = 1; // ou i := i-1
19 end ;
20
21 Readln ;
22 end .

Questions à se poser Pour écrire une boucle, il faut se poser les questions suivantes.
1. Que doit-on écrire avant que la boucle ne commence ? Cette étape est
l’initialisation.
2. Que doit faire la boucle à chaque étape ? Cette étape est le traitement.
3. Quand la boucle s’arrête-t-elle ou quelle est la condition d’arrêt ?

49
Les structures répétitives ou boucles Les instructions en Pascal

3.5.2 La boucle repeat (répéter . . . jusqu’à)


La boucle Repeat dit à l’ordinateur de répéter des actions jusqu’à ce qu’une certaine
condition soit vérifiée. La structure est la suivante :

répéter
instruction(s)
jusqu’à condition d’arret;

Figure 3.4 – La boucle Repeat

la traduction en Pascal est :


repeat
instructions
until condition ;

Remarques :
- L’ordinateur exécute les instructions indiquées entre REPEAT et UNTIL jusqu’à ce
que la condition soit vraie. Autrement dit, si la condition devient vraie, la boucle
s’arrête, ce qui est exactement l’opposé de la boucle WHILE.
- Du fait que le test d’arrêt est évalué en fin de boucle, la boucle REPEAT est toujours
exécutée au moins une fois ; ce qui n’est pas nécessairement le cas de la boucle
WHILE.
- BEGIN et END sont inutiles puisque le début de la boucle est indiqué par REPEAT
et la fin par UNTIL.

50
Les structures répétitives ou boucles Les instructions en Pascal

Exemple 1 Lire un nombre n au clavier. Afficher une ligne de n « * »

Lire N
Etoile ← 0 // Etoile est le nombre d’étoiles déjà affiché
N étoiles ont-elles déjà été affichées ?
répéter
Afficher *
Etoile ← Etoile + 1 // Une étoile vient d’être affichée
jusqu’à Etoile > N

1 program Etoiles ;
2 ( * ******************************************************
3 * L i r e ( s a i s i r ) un nombre n au c l a v i e r *
4 * A f f i c h e r une l i g n e d e n e t o i l e s *
5 ****************************************************** * )
6 var n : // Le nombre d'étoiles à acher
integer ;
7 etoile : // Le nombre d'étoiles déjà achées
integer ;
8 begin
9 //Saisie du nombre d'étoiles à acher
10 Write −
( ' Combien d ' ' e t o i l e s voulez vous afficher ? ' );
11 Readln (n ) ;
12
13 // Achage des étoiles
14 etoile := 0;
15 repeat
16 Write ( '* ' ); // Pas Writeln pour éviter le retour à la ligne
17 e t o i l e += 1 ; // ou etoile := etoile + 1
18 until etoile > n;
19
20 Readln ;
21 end .

51
Les structures répétitives ou boucles Les instructions en Pascal

Exemple 2 Lire (saisir) un nombre n au clavier. Afficher les nombres de n jusqu’à 1 en


diminuant de 1 à chaque fois.

Lire N
I←N // Au départ, le premier nombre à afficher vaut N
répéter
Afficher I
I ← I − 1 // On diminue I de 1
// Est-ce fini ?
jusqu’à I < 1

1 program CompteARebours ;
2 ( * ***********************************************************
3 Lire ( saisir ) un nombre n au clavier . Afficher les
4 nombres de n j u s q u 'à 1 en diminuant de 1 à chaque fois .
5 *********************************************************** * )
6 var n : integer ; // Le nombre à partir duquel le compte à rebours commence
7 i : integer ; // Variable de travail
8 begin
9 // Saisie du nombre
10 write ( ' Nombre de depart ? ' );
11 readln (n ) ;
12
13 i := n;
14 // Achage du compte à rebours
15 repeat
16 write (i , ' ' ); //Pas writeln pour éviter le retour à la ligne
17 −
i = 1; // ou i := i-1
18 until i < 1;
19
20 readln ;
21 end .

52
Les structures répétitives ou boucles Les instructions en Pascal

3.5.3 La boucle for (pour)


La boucle for dit à l’ordinateur de répéter des actions un certain nombre de fois. La
structure est la suivante :

pour i ← debut à f in faire


action(s)
fin

Figure 3.5 – La boucle For (to)

la traduction en Pascal est :


for I := debut to fin do
begin
instruction ( s )
end;

Remarques :
- Au départ, I est initialisé automatiquement à DEBUT. Puis, à chaque passage dans
la boucle, I est augmenté automatiquement de un. La boucle s’arrête quand I dé-
passe FIN. La boucle est donc exécutée FIN-DEBUT+1 fois.

53
Les structures répétitives ou boucles Les instructions en Pascal

La boucle FOR est équivalente à une boucle WHILE avec deux choses qui se font
automatiquement, à savoir l’initialisation de I à debut et l’augmentation de I de 1.
- BEGIN et END sont facultatifs s’il n’y a qu’une seule instruction à exécuter.
- La boucle FOR ne s’exécute pas si FIN < DEBUT.
- Il existe une variante de la boucle FOR qui permet de décrémenter la variable de
contrôle (I) de un au lieu de l’augmenter (Downto) :
for I := debut downto fin do
begin
instruction ( s )
end ;

Figure 3.6 – La boucle For (downto)

Dans ce cours, la boucle FOR est la boucle la plus utile mais on ne peut l’utiliser
que si le nombre de répétitions est connu !

54
Les structures répétitives ou boucles Les instructions en Pascal

Exemple 1 Lire un nombre n au clavier. Afficher une ligne de n « * »

Lire N
N étoiles ont-elles déjà été affichées ?
pour etoile ← 1 à N faire
Afficher *
fin

1 program Etoiles ;
2 ( * A f f i c h e r une l i g n e d e n e t o i l e s * )
3 var n : // Le nombre d'étoiles à acher
integer ;
4 etoile : // Le nombre d'étoiles déjà achées
integer ;
5 begin
6 //Saisie du nombre d'étoiles à acher
7 write ( ' Combien d ' ' e t o i l e s − voulez vous afficher ? ' );
8 readln (n ) ;
9
10 // On ache une étoile N fois
11 for etoile := 1 to n do
12 write ( '* ' );
13
14 readln ;
15 end .

Exemple 2 Afficher les nombres de n jusqu’à 1 en diminuant de 1 à chaque fois.

Lire N
pour I ← N à 1 faire
Afficher I
fin

1 program CompteARebours ;
2 ( * A f f i c h e r l e s nombres d e n j u s q u 1 *) 'à
3 var n : // Le nombre à partir duquel le compte à rebours commence
integer ;
4 i : // Variable de travail
integer ;
5 begin
6 // Saisie du nombre
7 write ( ' Nombre de depart ? ' );
8 readln (n ) ;
9
10 for i downto do
:= n 1
11 write (i , ' ' );
12
13 readln ;
14 end .

55
Procédures Halt, Break, Continue, Exit Les instructions en Pascal

3.6 Procédures Halt, Break, Continue, Exit


3.6.1 Halt
La procédure Halt provoque une fin anormale d’un programme et passe le contrôle au
système d’exploitation.

3.6.2 Break
La procédure Break provoque l’interruption d’une boucle FOR, WHILE ou REPEAT.
L’exemple qui suit montre une procédure qui teste si un nombre nb est premier. Elle
comporte une boucle for dans laquelle on détermine si le nombre nb est divisible par les
nombres compris entre 2 et nb − 1. Dès que l’un de ces nombres divise nb, cela signifie
que nb n’est pas premier. II est donc inutile de poursuivre l’exécution de la boucle, d’où
l’utilisation de la procédure BREAK.
1 program premier ;
2 var nb : integer ; // nombre à tester
3 i : integer ; // indice de boucle
4 premier : boolean ; // le nombre est-il premier ?
5 begin
6 write ( ' Veuillez entrer un nombre entier : ' );
7 readln ( nb ) ;
8
9 premier true // On suppose que le nombre est premier
:= ;
10 for ito − do
:= 2 nb 1
11 begin
12 if mod nb then i = 0
13 begin
14 f a l s e // nb n'est pas premier
premier := ;
15 break ;
16 end ;
17 end ;
18 if true then
premier =
19 write ( nb , ' est un nombre premier ' )
20 else
21 write ( nb , ' n ' ' est pas un nombre premier ' ) ;
22
23 readln ;
24 end .

Remarque : la ligne 10 fait croire que la boucle va s’exécuter (nb − 2) fois mais la ligne
15 stoppe la boucle. La condition d’arrêt de cette boucle est
- soit i > nb − 1 ;
- soit un diviseur a été trouvé.

56
Procédures Halt, Break, Continue, Exit Les instructions en Pascal

Pour la lisibilité du programme, il aurait sans doute mieux valu utiliser une boucle WHILE
program premier ;
var nb : integer ; // nombre à tester
i : integer ; // indice de boucle
premier : boolean ; // le nombre est-il premier ?
begin
write ( ' Veuillez entrer un nombre entier : ' );
readln ( nb ) ;

premier := true ;
i := 2;
while ( i <= nb − 1) and ( premier = true do )
begin
if nb mod i = 0 then
premier := false ; // nb n'est pas premier
i := i + 1;
end ;

if premier then // ⇐⇒ premier = true


write ( nb , ' est un nombre premier ' )
else
write ( nb , ' n ' ' est pas un nombre premier ' ) ;

readln ;
end .

La condition d’arrêt est ici plus évidente.

3.6.3 Continue
L’appel à la procédure Continue provoque le passage du contrôle de l’exécution à l’ité-
ration suivante dans une instruction FOR, WHILE ou REPEAT.

3.6.4 Exit
La procédure Exit permet de quitter l’exécution de la procédure en cours. Si la pro-
cédure en cours correspond au programme principal, Exit termine l’exécution du pro-
gramme.

57
Procédures Halt, Break, Continue, Exit Les instructions en Pascal

3.6.5 Exercices
1. Calculer
(a) 1 + 2 + 3 + · · · + n
(b) 1 × 2 × 3 × · · · × n (n!)
où n est un entier positif.
2. Écrire un programme qui lit 10 nombres saisis au clavier et affiche le nombre de
valeurs négatives lues.
3. Calculer le produit de nombres réels lus au clavier. On arrête dès qu’on a lu le réel 0.
4. Calculer la somme des
(a) N premiers nombres pairs
(b) N premiers nombres impairs
où N est un entier positif lu au clavier.
5. Afficher tous les diviseurs d’un nombre entier donné.
6. Compter le nombre de diviseurs d’un nombre entier donné.
7. Écrire un programme qui affiche le nombre des entiers qui sont des multiples de 3
et inférieurs à un nombre n donné par l’utilisateur.
8. Calculer le plus grand et le plus petit parmi n nombres réels lus au clavier (n est
aussi lu au clavier).
9. Même exercice que le précédent mais on arrête si le nombre réel à lire est 0.
10. Afficher le nombre de diviseurs de tous les entiers compris entre10 et 100.
11. Afficher le nombre de diviseurs de tous les entiers compris entre10 et 100. Le pro-
gramme affichera encore celui qui a le plus de diviseurs.
12. Déterminer si un nombre entier est premier. Un nombre est premier s’il n’admet que
deux diviseurs : 1 et lui-même. Par exemple, 23 est premier.
13. Déterminer si un nombre est parfait. Un entier est parfait s’il est égal à la somme de
ses diviseurs, lui-même excepté (28 est un nombre parfait).
14. Calculer an si n est un entier positif.
15. Calculer an si n est un entier quelconque.
16. Afficher tous les nombres d’Armstrong (cf. exercice 7 page 45).
17. Afficher tous les nombres premiers compris entre 1 et 1000.
18. Afficher tous les nombres parfaits (cf. exercice 13) compris entre 1 et 10000 (il y en
a quatre : 6, 28, 496, 8128).
19. Imprimer tous les couples (x,y) de nombres entiers compris entre -100 et 100 véri-
fiant la relation 9x − 4y = 35
20. Imprimer tous les triplets (x,y,z) de nombres entiers compris entre 1 et 100 vérifiant
la relation de Pythagore. La relation de Pythagore est x2 + y 2 = z 2

58
Procédures Halt, Break, Continue, Exit Les instructions en Pascal

21. Pour un capital C placé au taux t, calculer le total du capital et des intérêts obtenus
au bout de n années (n est donné)
(a) si le placement se fait à intérêt simple : Cf inal = Cdepart (1 + nt)
(b) si le placement se fait à intérêt composé : Cf inal = Cdepart (1 + t)n
22. Ecrire un programme qui gère le jeu de la "fourchette".
23. Calculer le nombre de ’e’ d’une chaîne. (Il faut tenir compte des majuscules et des
minuscules).
24. Calculer le nombre de voyelles, de consonnes et des autres caractères d’une chaîne.
25. Renverser une chaîne.
26. Tester si une chaîne est un palindrome. Un palindrome est une chaîne qui se lit de la
même façon à l’endroit qu’à l’envers.
27. Compter le nombre de mots d’une chaîne. On suppose que les mots sont séparés par
des espaces et des caractères de ponctuation.
28. Programmer le jeu du "pendu".
29. Programmer le jeu des "cinq lettres".

59
Utilisation du générateur aléatoire Les instructions en Pascal

3.7 Utilisation du générateur aléatoire


3.7.1 Générer un nombre réel
Random écrit seul génère un nombre aléatoire réel compris dans l’étendue 0 <= X < 1 ([0, 1[)
function Random : Extended ; // Il n'y a aucun paramètre

L’instruction
r := Random * ( B−A) + A ;

génère donc un nombre réel compris entre A et B (B étant exclus). Par exemples,

- random * 20 génère un réel compris entre 0.0 et 20.0 ([0, 20[) ;


- random * 100 - 15 génère un réel compris entre −15 et 85 ([−15, 85[) ;
- random * 6 + 1 génère un réel compris entre 1 et 7 ([1, 7[) ;

3.7.2 Générer un nombre entier


function Random const ( ARange : Integer ): Integer ; // Il y a un paramètre

Quand un nombre entier est indiqué comme paramètre (ARange), la fonction Random
renvoie un nombre aléatoire entier compris dans l’étendue 0 <= X < ARange-1.

Par exemples,
- random(20) génère un entier compris entre 0 et 19 ;
- random(100) + 15 génère un entier compris entre 15 et 114 ;
- random(6) + 1 génère un entier compris entre 1 et 6 ;

Pour générer un entier i compris entre A et B, il suffit d’écrire


i := Random ( B−A+1) + A ;

3.7.3 Randomize
Randomize initialise le générateur interne de nombre aléatoire avec une valeur aléa-
toire (obtenue à partir de l’horloge du système).
procedure Randomize ;

60
Utilisation du générateur aléatoire Les instructions en Pascal

Exemple : Calculer la probabilité d’obtenir un 1 avec un dé

procedure TFiche . B o u t o n C l i c k ( S e n d e r : TObject ) ;


var nombreTirer : integer ;
combienDeFois : integer ;
combienDeUn : integer ;
probabilite : extended ;
i : integer ;
begin
// Initialisations
Randomize ;
combienDeFois := 1000000; // On tente l'expérience 1 000 000 de fois
combienDeUn := 0;

// Calcul
for toi :=1 combienDeFois do
begin
nombreTirer := Random (6) + 1; // Simulation d'un jet de dé (entre 1 et 6)
if nombreTirer = 1 then // Tester si 1
combienDeUn := combienDeUn + 1 ; //Ajout d'une unité au compteur de 1
end ;
probabilite := combienDeUn / combienDeFois ;
writeln ( probabilite :0:3);
end ;

61
Utilisation du générateur aléatoire Les instructions en Pascal

62
CHAPITRE 4
LES TABLEAUX

4.1 Les tableaux à une dimension


4.1.1 Définition et utilité
Si on veut utiliser huit variables entières dans un programme, une solution serait d’écrire
var i1 , i2 , i3 , i4 , i5 , i6 , i7 , i 8 : integer ;

une autre est d’utiliser les tableaux.


Un tableau est une structure constituée d’un nombre déterminé de composants, tous du
même type (les composants sont parfois appelés éléments). Les composants sont repérés
à l’intérieur du tableau par un indice. On peut représenter schématiquement un tableau
(appelé T) de 8 entiers de la manière suivante :

Figure 4.1 – Représentation d’un tableau

On déclare le tableau T en écrivant :


var T : array [1..8] of integer ;

On accède à un élément particulier en écrivant le nom du tableau suivi du numéro de


l’élément. Par exemple,
T[ 1 ] ou T [ 5 ] ou T [ i ] , ···

63
Les tableaux à une dimension Les tableaux

D’une manière plus générale, on déclare un tableau de la manière suivante :


var nom_de_variable : array [ i n d i c e _ d ébut . . i n d i c e _ f i n ] of type_é l éments ;

Voici quelques exemples,


var T1 : array [1..30] of integer ;
T2 : array [5..20] of real ;
T3 : array [ −50..10] of char ;
T4 : array [ 'A ' . . ' Z ' ] of byte ;
T5 : array [1..100] of string ;
...

- T1 est un tableau qui pourra contenir 30 entiers (T1[1], T1[2], ..., T1[30]) ;
- T2 est un tableau qui pourra contenir 16 réels (T2[5], T2[6], ..., T2[20]) ;
- T3 est un tableau qui pourra contenir 61 caractères (T3[-50], T3[-49], ..., T3[10]) ;
- T4 est un tableau qui pourra contenir 26 entiers (T4[’A’], T4[’B’], ..., T4[’Z’]) ;
- T5 est un tableau qui pourra contenir 100 chaînes (T5[1], T5[2], ..., T5[100]).

C’est au moment de la déclaration que la place d’un tableau est allouée en mémoire.

4.1.2 Exemples
1. Créer le tableau de la page précédente.
program ex_tableau_1 ;
var array
T : [1..8] of integer ;
begin
T[ 1 ] := 8;
T[ 2 ] := 14;
T[ 3 ] := − 2;
T[ 4 ] := 7;
T[ 5 ] := 0;
T[ 6 ] := − 54;
T[ 7 ] := 8;
T[ 8 ] := 1;
end .

2. Créer un tableau de 12 entiers contenant 1 dans son premier élément, 2 dans le


second, ..., 12 dans le dernier.

1 2 3 4 5 6 7 8 9 10 11 12
1 2 3 4 5 6 7 8 9 10 11 12

Dans cet exemple, l’indice est égal au contenu.

64
Les tableaux à une dimension Les tableaux

(*
Cré e r un tableau de 12 entiers contenant 1 dans son p r e m i e r é l é ment ,
2 dans le second , ... , 12 dans le dernier .
*)
program tableau ;
var i : // indice du tableau
integer ;
tab array : of // tableau de 12 entiers
[1..12] integer ;
begin
// Remplissage du tableau
for i to := do 1 12
begin
tab [ i ] // L'indice est égal au contenu
:= i ;
end ;

// Achage du tableau
for i to := 1 12 do
begin
writeln ( ' t a b [ ' , i , ' ]= ' , t a b [ i ] ) ;
end ;

readln ;
end .

On obtient :

65
Les tableaux à une dimension Les tableaux

3. Lire un tableau de N réels au clavier. Afficher ensuite ce tableau.


On suppose que N ne dépassera jamais 100.
Remarques : on ne peut pas écrire “var t : array[1..N ] of ...” car la valeur de N est
inconnue au moment de la compilation. On écrira donc “var t :array[1..100] of ...”
en sachant que l’utilisateur ne pourra entrer une valeur pour N qui soit supé-
rieure à 100.
Il existe aussi des tableaux dynamiques 1 dont le nombre d’éléments est fixé
à l’exécution.
1 program tableau ;
2 var i : integer ; //indice du tableau
3 tab : array [1..100] of real ; // Le tableau contient 100 éléments
4 taille : i n t e g e r ; //mais seuls les taille premiers éléments vont servir
5 begin
6 // Lecture du nombre d'éléments
7 write ( ' Combien d ' ' e l e m e n t s ? ' );
8 readln ( taille );
9 // Remplissage du tableau
10 for i to
:= 1 do taille
11 begin
12 write ( ' Que vaut tab [ ' , i , ' ] ? ' );
13 readln ( tab [ i ] ) ;
14 end ;
15 // Achage du tableau
16 for i to
:= 1 do taille
17 begin
18 writeln ( ' t a b [ ' , i , ' ]= ' , t a b [ i ] : 0 : 5 ) ;
19 end ;
20 readln ;
21 end .

Amélioration : Rien n’empêche l’utilisateur d’entrer une taille supérieure à 100.


Le programme devrait donc interdire l’entrée d’un nombre supérieur à 100. Il
suffit de remplacer les lignes 7 et 8 par
repeat
write ( ' Combien d ' ' e l e m e n t s ? ' );
readln ( taille );
until t a i l l e <= 1 0 0 ;

1. Les tableaux dynamiques seront étudiés en sixième

66
Les tableaux à une dimension Les tableaux

4. Lire un tableau de réels au clavier. La lecture s’arrête dès que l’utilisateur entre le
nombre décimal -99.0. Afficher ensuite ce tableau.
Cet exemple est identique au précédent sauf que la condition d’arrêt n’est plus “on
a lu N éléments”. Comme on ne sait pas d’avance combien d’éléments seront né-
cessaires,
(a) on alloue un nombre d’éléments raisonnable, c’est-à-dire suffisamment grand
mais pas inutilement grand ;
(b) on n’utilise plus une boucle FOR mais une boucle REPEAT

program tableau ;
(*
Lire un tableau de ré e l s au clavier .
La lecture s ' arrête dè s que l ' utilisateur entre
le nombre d é c i m a l −99.0.
Afficher ensuite ce tableau .
*)

var i : integer ; //indice du tableau


tab : array [1..100] of real ; // Taille raisonnable (100)
taille_du_tableau : integer ; // nombre d'éléments du tableau
begin
// Remplissage du tableau
i := 1;
repeat
write ( ' Que vaut tab [ ' , i , ' ] ? ' );
readln ( tab [ i ] ) ;
inc ( i ); // ou i+=1 ou i :=i+1
until tab [ i −1]= − 99; // i-1 car on a incrémenté i

taille_du_tableau := i − 2;
// i-2 car on a incrémenté i et on ne prend pas le -99

// Achage du tableau
for i to := 1 taille_du_tableau do
begin
writeln ( ' t a b [ ' , i , ' ]= ' , t a b [ i ] : 0 : 5 ) ;
end ;

readln ;
end .

67
Les tableaux à plusieurs dimensions Les tableaux

4.2 Les tableaux à plusieurs dimensions


Les tableaux étudiés à la section précédente sont des tableaux à une seule dimension
car un seul indice suffit pour les utiliser.
Les tableaux à deux dimensions auront besoin de deux indices, ceux de N dimensions
auront besoin de N indices.

4.2.1 Les matrices


Une matrice est un tableau à deux dimensions, c’est-à-dire un tableau constitué de
lignes et de colonnes (une grille).
 
m11 m12 m13 m14
 
m21 m22 m23 m24 
 
m31 m32 m33 m34 
 
 
m m m m 
 41 42 43 44 

m51 m52 m53 m54

Figure 4.2 – Tableau à deux dimensions

On les déclare
var matrice : array [ 1 . . m, 1 . . n ] of integer ;

où m est le nombre de lignes et n, le nombre de colonnes.


Accès aux éléments matrice[3, 4] représente l’élément qui se trouve en troisième ligne
et en quatrième colonne.

Exemple
Générer aléatoirement et afficher tous les éléments entiers d’un tableau de 4 lignes et
6 colonnes. Les éléments sont compris entre –100 et 100.
(*******************************************************
* Générer aléatoirement et afficher tous les éléments *
* entiers d'un tableau de 4 lignes et 6 colonnes. *
* Les éléments sont compris entre -100 et 100. *
*******************************************************)

program tableau ;
var lig , col : // indices du tableau (ligne et colonne)
integer ;
tab array
: of
[1..4 ,1..6] //tableau de 4*6 entiers
integer ;
begin
// Remplissage du tableau
randomize ;
for lig to do
:= 1 4
for col to do
:= 1 6

tab [ l i g , c o l ] random
:= 100 + (201);

68
Les tableaux à plusieurs dimensions Les tableaux

// Achage du tableau
for lig := 1 to 4 do
for col := 1 to 6 do
writeln ( ' t a b [ ' , l i g , ' , ' , c o l , ' ]= ' , t a b [ l i g , c o l ] ) ;

readln ;
end .

4.2.2 Les tableaux d’une dimension supérieure à deux


On les déclare
var t : array [ 1 . . n1 , 1 . . n2 , 1 . . n3 , . . . ] of ... ;

et on accède aux éléments en écrivant :


t [ i1 , i2 , i3 , . . . ]

69
Exercices Les tableaux

4.3 Exercices
1. Multiplier tous les éléments d’un tableau par 4.
2. Calculer la somme de deux tableaux à une dimension (utiliser trois tableaux).
3. Calculer la somme et le produit des éléments d’un tableau.
4. Calculer le plus grand et le plus petit élément d’un tableau.
5. Inverser le premier et le dernier élément d’un tableau.
Solution : on utilise une variable intermédiaire.
Intermediaire := T [ 1 ] ;
T[ 1 ] := T [ n ] ;
T[ n ] := Intermediaire ;

6. Inverser tous les éléments d’un tableau en utilisant la technique suivante : le premier
avec le deuxième, le deuxième avec le troisième, ... (permutation circulaire vers la
gauche).
7. Inverser tous les éléments d’un tableau en utilisant la technique suivante : le der-
nier avec l’avant-dernier, l’avant-dernier avec l’avant-avant-dernier, ... (permutation
circulaire vers la droite).
8. Permuter circulairement un tableau de k positions vers la droite ou vers la gauche.
Indication : utiliser deux tableaux.
9. Étant donné un tableau de nombres tous différents, chercher si un nombre donné
figure parmi les composants. Si oui, indiquer la valeur de l’indice correspondant
(recherche séquentielle).
10. Même question, mais les composants du tableau peuvent être égales. Si le nombre à
rechercher figure plusieurs fois parmi les éléments du tableau, on déterminera tous
les indices correspondants. Ce n’est qu’après avoir déterminé tous les indices qu’on
les écrira.
11. Jeu du « bonhomme pendu ». Le programme lit un mot proposé par un premier
joueur. Il affiche ensuite le mot où toutes les lettres sauf la première et la dernière sont
remplacées par un tiret. Un deuxième joueur propose des lettres. Chaque fois que la
lettre se trouve dans le mot, le programme remplace autant de tirets que nécessaire
par cette lettre et réaffiche le mot. Le second joueur a droit à un maximum de six
essais infructueux.
12. Calculer le nombre moyen de jets de dés qu’il faut pour obtenir une première fois 6.
Utiliser un tableau dont chaque élément sera, pour un essai donné, le nombre de jets
qu’il a fallu exécuter pour avoir 6. Il restera à calculer la moyenne des données du
tableau.
13. Calculer le nombre moyen de jets de dés qu’il faut pour obtenir une première fois
421 en lançant les trois dés en même temps. (Cf. exercice précédent).
14. Construire des carrés magiques d’ordre impair. Un carré magique d’ordre N est un
tableau carré (N × N ) dont les composants sont les N 2 premiers nombres entiers
disposés de telle façon que les sommes des termes de chaque colonne, de chaque

70
Exercices Les tableaux

ligne, ou de chaque diagonale principale soient égales.


8 1 6
Exemple : Carré magique d’ordre 3 3 5 7
4 9 2
Somme des termes d ' une ligne = somme des termes d ' une colonne
= somme des termes d ' une d i a g o n a l e = 15

Lorsque N est impair, il existe un algorithme ; l’exposé sera fait sur un carré d’ordre
5, mais le raisonnement s’appliquerait à un carré d’ordre N .
(a) Phase initiale
Pour commencer, on place le chiffre 1 dans la case située au-dessus de celle du
milieu du carré. On continue ensuite en plaçant les nombres 2, 3, 4, . . . selon
la diagonale ascendante de direction NORD-EST. Si I est l’indice de ligne et J
l’indice de colonne, cette diagonale s’obtient en faisant I = I −1 et J = J +1 :

23 6 19 2 15
10 18 1 14 22
17 5 13 21 9
4 12 25 8 16
11 24 7 20 3

(b) Règles à observer lors de la progression dans le carré


La loi de progression mentionnée ci-dessus entraînera tôt ou tard une sortie
hors des limites du carré défini. La notation A(I,J) repérant l’élément courant
du tableau A, on devra appliquer les règles suivantes :
- Si I < 1, on repart de la ligne du bas (I = N ), tout en conservant le même
indice J de colonne.
- Si J > N , on repart de la première colonne à gauche (J = 1), tout en
conservant la valeur de l’indice I obtenu.
- Si J < 1, on repart de la dernière colonne (J = N ), en conservant tou-
jours l’indice ligne I.
Vérification de la case atteinte
- Il peut arriver que l’on atteigne une case contenant déjà un nombre rangé
précédemment. On doit donc prévoir un moyen permettant de faire cette
vérification : par exemple, lors de l’initialisation, on placera des zéros dans
tous les éléments du carré, ce qui permettra ultérieurement de déduire si
la case est libre ou non.
- Si le test fait apparaître une occupation de la case A(I,J), on choisit la
direction NORD-OUEST à partir de la case courante occupée ; on repren-
dra la direction normale NORD-EST dès que le nombre courant est placé
dans cette case "libre". La direction NORD-OUEST s’obtient en faisant
I = I − 1 et J = J − 1, étant entendu que l’on devra vérifier que l’on ne
sort pas du tableau (comme avant).
15. Calculer le produit de deux matrices.

71
Le tri d’un tableau Les tableaux

4.4 Le tri d’un tableau


4.4.1 Le tri par sélection
Il existe le tri par sélection du minimum et le tri par sélection du maximum. Le tri qui
suit est le tri par sélection du minimum.
On voudrait trier le tableau suivant : 5 -2 30 10 0
1. Étape 1
- on recherche le minimum des éléments du tableau, c’est -2

- on échange le minimum avec le premier élément du tableau, on obtient : -2 5 30 10 0


2. Étape 2
- on recherche le minimum des éléments du tableau en commençant au 2e élé-
ment, c’est 0

- on échange le minimum avec le 2e élément du tableau, on obtient : -2 0 30 10 5


3. Étape 3
- on recherche le minimum des éléments du tableau en commençant au 3e élé-
ment, c’est 5

- on échange le minimum avec le 3e élément du tableau, on obtient : -2 0 5 10 30


4. Étape 4
- on recherche le minimum des éléments du tableau en commençant au 4e élé-
ment, c’est 10

- on échange le minimum avec le 4e élément du tableau, on obtient : -2 0 5 10 30

- il n’y a plus qu’un seul élément 30 , le tableau est donc trié.

Remarque : Il y une étape en moins que le nombre d’éléments du tableau.

4.4.2 Le tri « bulles »


On voudrait trier le tableau suivant : 5 -2 30 10 0
1. Étape 1
- on compare les deux premiers éléments du tableau, on les échange s’ils ne sont
pas dans l’ordre ; on obtient : -2 5 30 10 0
- on compare le 2e et le 3e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 5 30 10 0

72
Le tri d’un tableau Les tableaux

- on compare le 3e et le 4e élément du tableau, on les échange s’ils ne sont pas


dans l’ordre ; on obtient : -2 5 10 30 0
- on compare le 4e et le 5e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 5 10 0 30
2. Étape 2
- on compare les deux premiers éléments du tableau, on les échange s’ils ne sont
pas dans l’ordre ; on obtient : -2 5 10 0 30
- on compare le 2e et le 3e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 5 10 0 30
- on compare le 3e et le 4e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 5 0 10 30
- on compare le 4e et le 5e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 5 0 10 30
3. Étape 3
- on compare les deux premiers éléments du tableau, on les échange s’ils ne sont
pas dans l’ordre ; on obtient : -2 5 0 10 30
- on compare le 2e et le 3e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 0 5 10 30
- on compare le 3e et le 4e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 0 5 10 30
- on compare le 4e et le 5e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 0 5 10 30
4. Étape 4
- on compare les deux premiers éléments du tableau, on les échange s’ils ne sont
pas dans l’ordre ; on obtient : -2 0 5 10 30
- on compare le 2e et le 3e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 0 5 10 30
- on compare le 3e et le 4e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 0 5 10 30
- on compare le 4e et le 5e élément du tableau, on les échange s’ils ne sont pas
dans l’ordre ; on obtient : -2 0 5 10 30

Remarque : pour cette étape, aucun échange n’a eu lieu : arrêt, le tableau est trié !

73
Le tri d’un tableau Les tableaux

4.4.3 Le tri par insertion


On voudrait trier le tableau suivant : 5 -2 30 10 0

Étape 1 - on commence à partir du 2e élément du tableau -2

- on insère cet élément à sa place dans la partie gauche du tableau en dé-


calant les éléments nécessaires vers la droite -2 5 30 10 0

Étape 2 - on considère l’élément suivant dans le tableau, c’est le 3e et il vaut 30

- on insère cet élément à sa place dans la partie gauche du tableau en dé-


calant les éléments nécessaires vers la droite (ici, 30 est déjà à sa place)
-2 5 30 10 0

Étape 3 - on considère l’élément suivant dans le tableau, c’est le 4e et il vaut 10

- on insère cet élément à sa place dans la partie gauche du tableau en dé-


calant les éléments nécessaires vers la droite -2 5 10 30 0

Étape 4 - on considère l’élément suivant dans le tableau, c’est le 5e et il vaut 0

- on insère cet élément à sa place dans la partie gauche du tableau en dé-


calant les éléments nécessaires vers la droite -2 0 5 10 30

Remarque Il y une étape en moins que le nombre d’éléments du tableau.


Indication Voici comment placer le ie élément dans la partie gauche
insere := T [ i ] ;
// Trouver la place d'insertion (ce sera j)
j := 1;
while T[ i ] > T[ j ] do
j := j +1;
// Décalage jusqu'à la position j
for k := i −1 downto j do
T [ k +1] := T [ k ] ;
// Placer le ie élément dans le "trou"
T[ j ] := insere ;

ou
// Mettre le ie élément au bon endroit dans la partie gauche du tableau
insere := T [ i ] ;
j := i − 1;
while ( j >= 1 ) and (T [ j ] > insere ) do
begin
T [ j +1] := T [ j ] ;
j := j − 1;
end ;
T [ j +1] := insere ;

74
Le tri d’un tableau Les tableaux

4.4.4 Le tri à peigne


Le comb sort ou tri à peigne ou tri de Dobosiewicz est un algorithme de tri assez simple
initialement inventé par Wodzimierz Dobosiewicz en 1980. Dans le tri à bulles ascendant
classique, chacun des éléments de la liste à trier est comparé avec son voisin immédiat, et
interverti s’il est plus grand que l’élément suivant.
L’idée de base du comb sort est de comparer un élément avec un autre élément plus
lointain, espacé de celui-ci d’un certain intervalle. Au départ, cet intervalle est relativement
grand, puis on le réduit progressivement à chaque passe de l’algorithme jusqu’à ce qui ne
soit plus que de 1 en fin de traitement. Le tri à bulles peut être considéré comme une
variante du comb sort dans lequel l’intervalle est toujours de 1.
La valeur d’origine de l’intervalle est généralement la taille de la liste à trier divisée
par le facteur de réduction. Des essais empiriques ont montré que la valeur idéale de ce
facteur de réduction est voisine de 1, 3.
Une démonstration animée du fonctionnement de ce tri se trouve à l’adresse
http ://[Link]/pages/algo/tri/tri_peigne.html

Autres tris D’autres tris seront étudiés en sixième.

75
La recherche dans un tableau Les tableaux

4.5 La recherche dans un tableau


4.5.1 La recherche séquentielle
On appelle clé l’élément à rechercher. Le principe de la recherche séquentielle est de
rechercher la clé en partant du premier élément du tableau jusqu’au dernier.
La recherche s’arrête dès que la clé est trouvée ou si le dernier élément du tableau est
dépassé (dans ce dernier cas, la clé n’est pas dans le tableau).
Si la clé se trouve plusieurs fois dans le tableau, on peut demander à la recherche de
- s’arrêter à la première occurrence de la clé ;
- rechercher la dernière occurrence de la clé ;
- afficher tous les endroits où la clé se trouve.

4.5.2 La recherche dichotomique


La recherche dichotomique doit s’exécuter sur un tableau trié. Deux exemples illus-
treront son principe de fonctionnement.

Exemple 1 :
Considérons
- le tableau d’entiers suivant et ses indices :

1 3 4 6 9 11 12 14 17 20 24 40
1 2 3 4 5 6 7 8 9 10 11 12

- la clé 9

1. On prend l’élément au milieu du tableau, ici 11 .


On compare 11 à l’élément à rechercher (la clé 9) : comme 9 < 11, on peut limiter
la recherche à la partie gauche du tableau :

1 3 4 6 9
1 2 3 4 5

2. On prend l’élément au milieu (ici 4 ) de ce tableau (qui est le tableau de départ où


on ne s’intéresse plus qu’à certains indices).
On compare 4 à la clé : comme 9 > 4, on peut limiter la recherche à la partie droite
du tableau :

6 9
4 5

76
La recherche dans un tableau Les tableaux

3. On prend l’élément au milieu (ici 6 ) de ce tableau.


On compare 6 à la clé : comme 9 > 6, on peut limiter la recherche à la partie droite
du tableau :

9
5

4. On prend l’élément au milieu (ici 9 ) de ce tableau.


On compare 9 à la clé : comme 9 = 9, on a trouvé la clé à la place 5.

Exemple 2 :
Considérons
- le tableau d’entiers suivant et ses indices (le même tableau que précédemment) :

1 3 4 6 9 11 12 14 17 20 24 40
1 2 3 4 5 6 7 8 9 10 11 12

- la clé 22

1. On prend l’élément au milieu du tableau, ici 11 .


On compare 11 à l’élément à rechercher (la clé 22) : comme 22 > 11, on peut limiter
la recherche à la partie droite du tableau :

12 14 17 20 24 40
7 8 9 10 11 12

2. On prend l’élément au milieu de ce tableau (ici 17 ).


On compare 17 à la clé : comme 22 > 17, on peut limiter la recherche à la partie
droite du tableau :

20 24 40
10 11 12

3. On prend l’élément au milieu (ici 24 ) de ce tableau.


On compare 24 à la clé : comme 22 < 24, on peut limiter la recherche à la partie
gauche du tableau :

20
10

4. On prend l’élément au milieu (ici 20 ) de ce tableau.


On compare 20 à la clé : comme 22 > 20, on peut limiter la recherche à la partie
droite du tableau qui n’existe plus ; on arrête en indiquant que la clé ne se trouve
pas dans le tableau.

77
La recherche dans un tableau Les tableaux

Exercice 1 combien d’étapes cette recherche comporte-t-elle au maximum si le ta-


bleau contient n éléments (essayer avec 100, 1000, 10000, puis n) ?
Exercice 2 programmer cette recherche.
Quelques indications
- utiliser trois indices qu’on va appeler gauche, droite et milieu où
- gauche représentera l’indice gauche du tableau qui reste à trai-
ter ;
- droite représentera l’indice droite du tableau qui reste à trai-
ter ;
- milieu représentera l’indice du milieu du tableau qui reste à
traiter ;
au départ, gauche vaut 1, droite vaut n (n est le nombre d’éléments
du tableau) ;
- le calcul de milieu est simplement gauche+droite
2
(division entière) ;
- on se déplace à droite en écrivant gauche ← milieu + 1 ;
- on se déplace à gauche en écrivant droite ← milieu − 1 ;
- la recherche s’arrête si la clé est trouvée ou si gauche > droite

4.5.3 La fusion de deux tableaux triés

78
CHAPITRE 5

TYPES DE DONNÉES ADDITIONNELS

Quatre nouveaux types de données vont être étudiés dans cette partie : le type énumé-
ration, le type intervalle, le type enregistrement 1 et le type ensemble (le type fichier sera
étudié dans un chapitre à part).

5.1 Le type énumération


Les types de base en Pascal sont les types scalaires. Les types scalaires sont composés
d’éléments appelés constantes pour lesquelles il existe une relation d’ordre (une constante
est plus petite, égale ou plus grande qu’une autre). Le nombre total de constantes dans le
type scalaire est appelé la cardinalité de ce type. Le langage Pascal fournit quatre types
scalaires : Integer, Real, Boolean et Char. On peut définir soi-même des types scalaires
(une énumération). Voici un exemple :
type j o u r S e m a i n e = ( l u n , mar , mer , j e u , ven , sam , dim ) ;
direction = ( n ord , e s t , sud , o u e s t ) ;
c o u l e u r = ( pique , coeur , carreau , t r e f l e ) ; // Couleurs des cartes
etatCivil = ( marie , veuf , c e l i b a t a i r e ) ;
var jour : jourSemaine ;
versOu : direction ;
carte : couleur ;
etat : etatCivil ;

“jour” ne peut prendre que sept valeurs possibles (lun, mar, . . ., dim), “versOu” et “carte”
ne peuvent en prendre que quatre.
Écriture simplifiée l’extrait de programme ci-dessus peut également s’écrire sans définir
explicitement des nouveaux types de données :
var jour : ( l u n , mar , mer , j e u , ven , sam , dim ) ;
versOu : ( nord , e s t , sud , o u e s t ) ;
carte : ( pique , coeur , carreau , t r e f l e ) ;
etat : ( marie , veuf , c e l i b a t a i r e ) ;

1. Des quatre types, le type enregistrement est le plus important !

79
Le type intervalle Types de données additionnels

On peut utiliser nos nouveaux types et variables de la manière suivante :


jour := mar ;
if ( e t a t = marie ) or ( etat = veuf ) then
··· ;
for jour := lun to do · · ·
ven ;
for carte := trefle downto pique do ··· ;
if v e r s O u <= s u d then · · · ;
.
.
.

Remarque l’utilisation de constantes permet également de faciliter la lecture d’un pro-


gramme :
const LUN = 1 ;
MAR = 2 ;
MER = 3 ;
.
.
.

Cette méthode est peut-être moins commode que l’utilisation d’un type énumération.

5.2 Le type intervalle


Il arrive fréquemment que quand on utilise un type scalaire, on ai besoin que d’une
partie des valeurs possibles de ce type. Un type intervalle est un type composé d’une partie
des valeurs possibles d’un type (sauf réel). On utilise un type intervalle en écrivant
type nom_type = limiteInferieure .. limiteSuperieure ;

Quelques exemples :
1 type resultat = 0 .. 100;
2 alphabet = 'A ' .. 'Z ' ;
3 chiffre = '0 ' .. '9 ' ; // Des caractères
4 jourOuvrable = lun .. ven ; // du lundi au vendredi
5 var note : resultat ;
6 lettre : alphabet ;
7 jour : jourOuvrable ;

La ligne 4 ne provoque pas d’erreur si “lun” et “ven” ont été définis avant. Par exemple,
type j o u r S e m a i n e = ( l u n , mar , mer , j e u , ven , sam , dim ) ;
jourOuvrable = lun .. ven ; // Aucun problème

Écriture simplifiée on peut aussi écrire :


1 var note : 0 .. 100;
2 lettre : 'A ' .. 'Z ' ;
3 jour : lun .. ven ;

Avantages du type intervalle


- la ligne 1 est plus parlante (précise) que
var note : integer ;

80
Le type enregistrement Types de données additionnels

- une instruction du style


note := 101;

provoquera immédiatement un avertissement à la compilation


Warning : range check error while evaluating constants
tandis que
note := N ;

provoquera une erreur à l’exécution (le programme s’arrête) si N n’est pas dans
l’intervalle attendu ([0, 100]) et que la directive {$RANGECHECKS ON} est utilisée.

5.3 Le type enregistrement


5.3.1 Définition
Contrairement aux tableaux qui ne permettent pas de travailler avec des éléments de
types différents, les enregistrements permettent au programme de définir des structures
de variables regroupant des éléments de types différents.
Les composants d’un enregistrement sont appelés les champs de l’enregistrement. La
définition d’un type enregistrement consiste à spécifier les différents champs, chacun d’eux
étant identifié par son type et par un identificateur.
La déclaration d’un type enregistrement est la suivant :
type nom_de_type = record
champ_1 : type de donnée ;
champ_2 : type de donnée ;
...
champ_n : type de donnée ;
end ;

Par exemple :
type TEleve = record
nom : String [20];
prenom : String [20];
classe : String [4];
sexe : char ;
dateNaissance : TDate ; // ou TDateTime
note : integer ;
end ;

Une fois que la structure de l’enregistrement a été définie, on peut déclarer des variables
du type voulu. Si on écrit :
var eleve1 , eleve2 : TEleve ; // Deux variables simples
tableauEleves : array [1..1000] of TEleve ; // Tableau d'élèves
fichierEleves : f i l e of TEleve ; // Fichiers d'élèves

on définit quatre variables eleve1, eleve2, tableauEleves et fichierEleves.

81
Le type enregistrement Types de données additionnels

5.3.2 Accès aux champs


On accède aux différents champs d’un variable de type enregistrement en utilisant un
point entre le nom de la variable et le nom du champ :
nom_de_variable.champ
Par exemple,
e l e v e 1 . nom := 'DURANT ' ;
write ( ' Donner un prenom : ' );
readln ( e l e v e 1 . prenom ) ;
e l e v e 2 . note := e l e v e 2 . note + 10;

for i :=1 to 10 do
tableauEleves [ i ] . sexe := 'F ' ;

5.3.3 Exemple
Un point peut se représenter par un enregistrement formé de deux champs qui sont ses
coordonnées. Écrire un programme qui calcule la distance entre deux points.
program PPoints ;
type TPoints = record
abscisse : real ;
ordonnee : real ;
end ;
var pt1 , pt2 : TPoints ;
distance : real ;
begin
// pt1 = ( 12 , 3.0)
pt1 . a b s c i s s e := 1/2;
pt1 . ordonnee := 3.0;
3
// pt2 = (4.0, 4 )
p t 2 . a b s c i s s e := 4.0;
pt2 . ordonnee := 3/4;

p
// la distance entre (x1, y1) et (x2, y2) vaut (x2 − x1)2 + (y2 − y1)2
distance := sqrt (
( p t 2 . a b s c i s s e −p t 1 . a b s c i s s e ) * ( p t 2 . a b s c i s s e −p t 1 . a b s c i s s e ) +
( p t 2 . o r d o n n e e −p t 1 . o r d o n n e e ) * ( p t 2 . o r d o n n e e −p t 1 . o r d o n n e e ) ) ;

writeln ( ' Distance = ' , distance : 0 : 4 ) ;

readln ;
end .

Remarque on reviendra sur le type enregistrement lors de l’étude des fichiers.

82
Le type ensemble Types de données additionnels

5.4 Le type ensemble


5.4.1 Introduction
En programmation, les ensembles sont mis en œuvre avec la même signification qu’ils
possèdent en mathématique. On y retrouve d’ailleurs les mêmes opérations. Pour mieux
comprendre l’utilité du type ensemble, considérons le problème suivant.
Comment savoir si un caractère (Key) est une voyelle majuscule ?
Une structure sélective permet de résoudre facilement ce problème :
if ( Key= 'A ' ) or ( Key= ' E ' ) or ( Key= ' I ' ) or ( Key= ' 0 ' ) or
( Key= 'U ' ) or ( Key= 'Y ' ) then
write ( 'C ' ' e s t une voyelle ' );

Ce genre de problème, consistant à déterminer si le contenu d’une variable appartient à


un ensemble de valeurs données, se rencontre souvent en programmation. Voici comment
il est possible de résoudre ce problème à l’aide d’un ensemble :
if Key in [ 'A ' , ' E ' , ' I ' , ' 0 ' , 'U ' , 'Y ' ] then
write ( 'C ' ' e s t une voyelle ' );

Ici, l’ensemble des voyelles est spécifié de manière explicite par une liste de constantes
placée entre crochets, appelée constructeur d’ensemble. Cette forme d’écriture abrégée
est bien plus élégante, plus claire et plus concise qu’une expression booléenne complexe.
L’ensemble des voyelles peut, dans cet exemple, être considéré comme une constante de
type ensemble. Un ensemble contient toujours des éléments du même type de base, sca-
laire (prédéfini ou énuméré) ou intervalle, à l’exception du type réel. Le type ensemble se
déclare de la manière suivante :
type type_ensemble = set of type_de_base ;

Une variable de type type_ensemble peut contenir des éléments de type type_de_base,
qui doit être un type scalaire ou intervalle, à l’exception du type réel. Le nombre maxi-
mum d’éléments d’un ensemble est limité à 256. De plus, deux ensembles sont égaux s’ils
contiennent les mêmes éléments, indépendamment de leur l’ordre. La définition d’une va-
riable de type ensemble comporte la spécification du type de base des éléments de cet
ensemble. Seule une affectation permet de placer des valeurs dans une variable de ce type.
L’erreur consistant à croire que la déclaration d’une telle variable suffit à lui attribuer des
éléments se rencontre fréquemment 2 .
L’affectation d’éléments à un ensemble s’effectue à l’aide d’un constructeur d’en-
semble qui n’est autre qu’une liste d’éléments du type de base, délimitée par des crochets.
La notation d’intervalle est possible lorsque plusieurs éléments sont consécutifs. Le frag-
ment de programme qui suit montre quelques exemples de déclaration et d’utilisation de
variables de type ensemble :

2. Cf. page suivante

83
Le type ensemble Types de données additionnels

1 type alphabet = set of 'A ' . . ' Z ' ;


2 c o u l e u r s = ( rouge , vert , bleu , jaune , blanc ) ;
3 teinte = set of couleurs ;
4 bizarre = set of 0..255;
5
6 var lettre , voyelle : alphabet ;
7 c : char ;
8 lumiere : teinte ;
9 clair : set of jaune . . blanc ;
10 magique : bizarre ;
11
12 begin
13 lettre := [ 'A ' . . ' Z ' ] ;
14 voyelle := [ 'A ' , ' E ' , ' I ' , ' 0 ' , 'U ' , 'Y ' ] ;
15 lumiere := [ blanc ] ;
16 clair := [ jaune , blanc ] ;
17 magique := [0..8 ,12 ,19 ,22..38 ,99];
18 if c in voyelle then
19 write ( ' Voyelle ' ) ;
20 end ;

- les lignes 1 −→ 4 définissent quatre nouveaux types de données ;


- les lignes 6 −→ 10 déclarent des variables dont le contenu est, à ce moment, indé-
terminé ;
- les lignes 13 −→ 17 donnent des valeurs aux variables.

Le langage Pascal dispose d’opérateurs agissant sur les ensembles, de manière ana-
logue aux opérateurs de la théorie des ensembles en mathématique. On trouve, d’un côté,
les opérateurs ensemblistes proprement dits (union, intersection et différence) et, de l’autre,
des opérateurs relationnels (appartenance, égalité, altérité, inclusion). Comme pour les
nombres, ces opérateurs ont un degré de priorité et, en cas de même degré de priorité,
l’évaluation des expressions se fait de gauche à droite.
Voyons comment s’expriment ces opérateurs en Pascal. Les variables utilisées sont
déclarées comme suit :
var nombres , r e s u l t a t , a , b : set of 0..10;

84
Le type ensemble Types de données additionnels

5.4.2 Manipulation des ensembles


Supposons que
nombres := [1..10];
a := [1 ,2 ,4];
b := [3 ,5] ;

Intersection

A ∩ B = {x | x ∈ A et x ∈ B}
En Pascal, l’intersection est utilisée grâce à “*”
resultat := nombres *[2 ,4..6]; // resultat aura la valeur [2,4,5,6]
if a * b = [] then // [] représente l'ensemble vide.
write ( 'a et b sont disjoints ' );

Union

A ∪ B = {x | x ∈ A ou x ∈ B}
En Pascal, l’union est utilisée grâce à “+”
r e s u l t a t := a+b + [ 6 , 7 , 8 , 9 ] ; // resultat aura la valeur [1,2,3,4,5,6,7,8,9]

Différence

A \ B = {x | x ∈ A et x ∈
/ B}
En Pascal, la différence est utilisée grâce à “-”
resultat := nombres −[1 ,3..7]; // resultat aura la valeur [2,8,9]

Égalité

A = B si A et B contiennent les mêmes éléments


En Pascal, l’égalité est utilisée grâce à “=”
if nombres = [1..10] then
write ( ' Ensembles égaux ' ) ;

Altérité

A 6= B si A et B ne contiennent pas les mêmes éléments


En Pascal, l’altérité est utilisée grâce à “<>”
if ( nombres <> [1..10] ) then
write ( ' Ensembles non égaux ' ) ;

85
Le type ensemble Types de données additionnels

Inclusion

A ⊂ B si tous les éléments de A sont dans B


En Pascal, l’inclusion est utilisée grâce à “<=”
if nombres <= [ 0 , 2 , 4 , 6 , 8 ] then
chaine := ' pair ' ;
if ( a <= b ) and ( a <> b ) then
chaine := 'a inclus mais non é g a l a b' ;

Appartenance

a ∈ A si a est un élément de A
En Pascal, l’appartenance est utilisée grâce à “in”
if caractere in [ 'A ' , ' E ' , ' I ' , 'O ' , 'U ' , 'Y ' ] then
write ( ' Voyelle ' ) ;

Remarque
Il est important de ne pas confondre la notion d’ensemble avec la notion d’intervalle
ou de type énuméré. Si, par exemple, on désire écrire :
caractere := [ 'A ' . . ' L ' ] ;

caractere peut, par exemple, être déclaré comme :


var caractere : set of 'A ' . . ' L ' ;

et non comme :
var caractere : 'A ' . . ' L ' ; // ici caractere n'est pas un ensemble

Test
Supposons que
A = [1 ,3 ,5 ,7 ,9]
B = [2 ,4 ,6 ,8 ,10]
C = [1 ,2 ,3 ,4 ,5]
D = [5]
E = [ ]

1. (A+B)-C
2. (A*C)=D
Quelle est la valeur de chacune des opérations suivantes ? 3. (A+E)*(B+D)
4. 7 IN (((A-B)-C)-D)
5. C <= (A+B)

86
Le type ensemble Types de données additionnels

5.4.3 Exemple
Calculer le nombre de voyelles, de consonnes et des autres caractères d’une chaîne
(exercice 24 page 59).
program lettres ;
var voyelles , consonnes : set of char ;
chaine : String ;
nbVoyelles , n b Co n so n ne s , nbAutres : integer ;
i : integer ;
begin
voyelles := [ 'A ' , ' E ' , ' I ' , 'O ' , 'U ' , 'Y ' ] ;
consonnes := [ 'B ' , 'C ' , 'D ' , ' F ' , 'G ' , 'H ' , ' J ' , 'K ' , ' L ' , 'M' , 'N ' ,
' P ' , 'Q ' , 'R ' , ' S ' , 'T ' , 'V ' , 'W' , 'X ' , ' Z ' ] ;
// Lire la chaine au clavier et la mettre en majuscules
readln ( chaine ) ;
chaine := upCase ( chaine ) ;

// Calculs
nbVoyelles := 0; nbConsonnes := 0; nbAutres := 0;
for to Length
i :=1 ( chaine ) do
begin
if IN
chaine [ i ] voyelles then
nbVoyelles := nbVoyelles + 1
else
if IN chaine [ i ] consonnes then
nbConsonnes := nbConsonnes + 1
else
nbAutres := nbAutres + 1 ;
end ;

// Acher les résultats


writeln ( nbVoyelles , ' voyelle ( s ) ' );
writeln ( n b Co n so n ne s , ' consonne ( s ) ' ) ;
writeln ( nbAutres , ' autre ( s ) ' ) ;

readln ;
end .

87
Le type ensemble Types de données additionnels

88
CHAPITRE 6
LES SOUS-PROGRAMMES

6.1 Décomposition d’un problème


En général, tout problème peut se décomposer en sous-problèmes plus simples à ré-
soudre ; ces sous-problèmes pouvant être eux-mêmes décomposés, ... Cette décomposition
s’arrête quand les sous-problèmes deviennent élémentaires à résoudre.
Nous allons illustrer cette décomposition grâce à deux exemples tirés de la vie cou-
rante.

Exemple 1
Décomposition de la tâche qui consiste à téléphoner à partir d’une cabine publique.
Cette tâche sera décomposée en quatre sous-actions :
- obtenir le numéro désiré ;
- établir la communication avec son interlocuteur ;
- échanger un dialogue avec son interlocuteur ;
- raccrocher.
Ces tâches se décomposent elles-aussi. En effet, chacune d’elles soulève un obstacle.
On obtient le numéro de la personne qu’on appelle en recherchant son nom dans son agenda
ou dans l’annuaire ou en demandant l’information au centre de renseignements. Ensuite, il
s’agira de mener à bien la deuxième tâche : établir la connexion avec son interlocuteur, ...
Cette décomposition peut se schématiser de la manière suivante :

Figure 6.1 – Décomposition d’un problème (1)

89
Décomposition d’un problème Les sous-programmes

Exemple 2
Décomposition de la tâche qui consiste à gérer un carnet d’adresses. On suppose que
notre gestion se limite à trois opérations :
- ajouter un nom ;
- rechercher l’adresse ;
- éditer (modifier).
Bien entendu, un tel niveau de décomposition ne suffit pas pour pouvoir être exécuté
sur une machine. En effet, un ordinateur ne peut effectuer directement l’action “ajouter
une personne” ou “éditer un répertoire”.
Il va donc falloir expliciter un peu le déroulement des opérations.
Ajouter une personne, c’est :
- acquérir les coordonnées ;
- chercher une place libre ;
- écrire dans le carnet.
Retrouver une personne, c’est :
- lire une identité ;
- rechercher dans le répertoire.
La structure du programme pourrait être la suivante :

Figure 6.2 – Décomposition d’un problème (2)

La démarche employée dans ces deux exemples est une décomposition descendante
aussi appelée par raffinements successifs 1 car elle consiste, une fois le but d’une tâche
défini, à examiner les moyens nécessaires pour y parvenir et ainsi à décrire des opérations
plus élémentaires.
1. En anglais : top-down program design

90
L’écriture de “gros” programmes Les sous-programmes

La notion de sous-programme est un outil informatique qui rend les programmes plus
modulaires, c’est-à-dire les subdivise en entités plus simples, bien individualisées, et dont
la fonction peut se comprendre et se déterminer aisément.

6.2 L’écriture de “gros” programmes


La partie la plus couteuse quant à l’utilisation des ordinateurs n’est pas le matériel
lui-même mais le développement et la maintenance des programmes. Il faut donc des pro-
grammes clairs et facilement compréhensibles.

Conditions nécessaires pour obtenir des programmes lisibles


1. Modularisation Ne sont lisibles et clairs que les petits programmes. Pour illustrer
cette affirmation, considérons le rôle que joue une variable à l’intérieur d’un pro-
gramme : supposons que K soit une variable entière et qu’en lisant le programme,
on rencontre une instruction qui commence par
if K < 0 then ...

Si le programme est suffisamment petit, le lecteur n’a probablement pas oublié la va-
leur de la variable K. Au pire, même s’il a perdu de vue cette valeur, les instructions
qui ont assigné une valeur à K restent à la vue du lecteur qui peut les retrouver d’un
seul coup d’œil. De plus, toutes les variables du programme (qui sont en nombre
relativement réduit puisque le programme est petit) peuvent être “suivies” par le
lecteur. En résumé, on dira qu’un programme est trop gros si les instructions qui in-
téressent le lecteur ne sont pas visibles d’un coup d’œil ou si elles ne sont pas faciles
à trouver.
Cet exemple montre la nécessité d’écrire de petits programmes (une page de lis-
ting devait être suffisante), c’est pourquoi il est obligatoire que le programmeur
découpe son programme en sous-programmes. Cette technique est appelée la dé-
coupe en modules (ou modularisation).

La découpe modulaire doit être réfléchie : le programmeur doit analyser


(penser) d’abord et coder ensuite.

91
L’écriture de “gros” programmes Les sous-programmes

2. Documentation Ce n’est jamais une perte de temps que de documenter ses pro-
grammes. Les commentaires intelligents sont utiles au concepteur (celui qui écrit
le programme) et au lecteur (celui qui sera chargé de la maintenance).
Au minimum, chaque sous-programme devrait contenir des commentaires expli-
quant :
- les paramètres qui entrent dans le sous-programme ;
- les paramètres qui en sortent ;
- les actions (l’action) que fait le sous-programme.
Par exemple,
function fact (n : integer ) : real ;
(*
En e n t r é e , la fonction reç o i t un entier n, elle ressort un ré e l .
Elle calcule la factorielle d e n où

f act(n) = n! = n × (n − 1) × (n − 2) × · · · × 3 × 2 × 1
*)

Remarques - les commentaires ne devraient pas être écrits quand tout le travail
est fini, mais bien au début ou pendant l’écriture du code ;
- écrire des commentaires pour le seul plaisir d’en avoir est parfaitement in-
utile. Il faut que les commentaires apportent une information pertinente.
3. Noms des identificateurs Un programme (ou un sous-programme) sera d’autant
plus lisible que les noms des identificateurs (qu’ils désignent des types, constantes,
variables, fonctions, procédures, ...) auront été bien choisis. Ces identificateurs doivent
“parler” d’eux-mêmes.
4. Utilisation judicieuse des structures de contrôle Comparer les extraits de pro-
grammes suivants :

somme := 0; somme := 0;
for i := 1 to 100 do i := 1;
somme := somme + i ; ou : if i <= 1 0 0 then
begin
somme := somme + i ;
i := i +1;
goto ou ;
end ;

premier := true ; premier true := ;


i := 2; for i to − do
:= 2 nb 1
while ( i <= nb − 1) and begin
( premier = true do ) if modnb then i = 0
begin begin
if nb mod i = 0 then false
premier := ;
premier := false ; break ;
i := i + 1; end ;
end ; end ;

Pour le second exemple, cf. page 56

92
L’écriture de “gros” programmes Les sous-programmes

Un troisième exemple est l’utilisation d’un choix multiple plutôt qu’une série de
structures alternatives. Ce cas a été étudié en page 42.
5. Relecture ultérieure du programme Une méthode pour tester la lisibilité d’un pro-
gramme pourrait être celle consistant à relire celui-ci quelque temps après sa concep-
tion. Si le programmeur ne peut comprendre son propre programme immédiatement,
c’est que le code n’est pas suffisamment clair et il doit être modifié.
6. Utilisation d’une présentation adéquate Le programme qui suit est tout à fait
“compréhensible” par une machine mais pour une personne ...
program var
DiviseursNombre ; nombre , diviseur : integer ; begin
Write ( ' Quel est Readln
le nombre ? ' ); ( nombre ) ; diviseur
:=1; while do begin i f
d i v i s e u r <=nombre nombre mod diviseur
= 0 then begin Writeln ( diviseur , ' est un diviseur de ' , nombre ) ;
end ; end Readln end
d i v i s e u r := d i v i s e u r +1; ; ; .

Afin de clarifier encore davantage la clarté d’un programme, des commentaires dans
le genre de ceux qui suivent peuvent s’avérer très utiles :

case ... of while ... do


. begin
. .
. .
end ; (* Fin du Case Of *) .
if then
...
begin
.
.
.
end ; (* Fin du If *)
.
.
.
end ; (* Fin de la boucle While *)

Attention La présentation peut parfois s’avérer trompeuse :

if A > 0 then somme := 0;


if B > 0 then i := 1;
B := B+1 while i < 100 do
else somme := somme + i ;
A := A+1; i := i +1;
writeln ( somme ) ;

93
Les procédures et fonctions Les sous-programmes

6.3 Les procédures et fonctions


A la section précédente, on a vu la nécessité d’écrire des sous-programmes pour per-
mettre la décomposition d’un programme en modules 2 plus simples.
Un autre avantage des sous-programmes est leur utilisation ultérieure. Si on est amené
dans certains programmes à utiliser à plusieurs reprises une même séquence d’instruc-
tions, on souhaite alors ne pas devoir recopier systématiquement ces instructions. Ainsi,

Les sous-programmes permettent d’éviter de réécrire plusieurs fois la même chose.

Les procédures et les fonctions sont les deux types de sous-programmes qui existent
dans le langage Pascal.
Leur utilisation présente, au début, quelques difficultés. Il est important de maîtriser
ces difficultés si on veut progresser dans l’élaboration de bons programmes.

6.3.1 Les fonctions


1. Définition
Une fonction est un sous-programme qui fournit un résultat, elle calcule une valeur.
Par exemples,
- calculer la racine carrée d’un nombre réel ;
- transformer un nombre d’heures, minutes, secondes en secondes ;
- calculer la somme des N premiers nombres entiers ;
- calculer le PGCD de deux entiers ;
- tester si un nombre est premier ;
- calculer an où a est un nombre réel non nul et n est un nombre entier ;
- calculer le nombre de voyelles d’une chaîne de caractères ;
- mettre une chaîne en majuscules ;
- extraire une partie de chaîne ;
- calculer le nombre de mots d’un texte ;
- calculer l’élément maximum d’un tableau de réels ;
- calculer le nombre de fois que se trouve un entier dans un tableau d’entiers ;
- ...
Pour tous les énoncés qui précèdent, un seul résultat est calculé.

2. Les modules peuvent être programmés par des personnes différentes

94
Les procédures et fonctions Les sous-programmes

L’écriture d’une fonction impose qu’on se pose deux questions :


(a) Quel type de résultat la fonction calcule-t-elle ?
(b) Que doit connaître la fonction pour s’exécuter ?
Reprenons les exemples ci-dessus :

Que doit connaître la fonction


Enoncé Résultat
pour s’exécuter ?
Calculer la racine carrée d’un
Réel Un nombre réel
nombre réel
Transformer un nombre d’heures,
Entier Trois nombres entiers
minutes, secondes en secondes
Calculer la somme des N premiers
Entier Un nombre entier
nombres entiers
Calculer le PGCD de deux entiers Entier Deux nombres entiers
Calculer an où a est un nombre réel
Réel Un nombre réel et un nombre entier
non nul et n est un nombre entier
Tester si un nombre est premier Booléen Un nombre entier
Calculer le nombre de voyelles
Entier Une chaîne
d’une chaîne de caractères
Mettre une chaîne en majuscules Chaîne Une chaîne
Extraire une partie de chaîne Chaîne Une chaîne et deux entiers
Calculer le nombre de mots d’un
Entier Un fichier
texte
Calculer l’élément maximum d’un
Réel Un tableau de réels
tableau de réels
Calculer le nombre de fois que se
trouve un entier dans un tableau Entier Un tableau d’entiers et un entier
d’entiers
Figure 6.3 – Écriture d’entêtes de fonctions

La troisième colonne indique les paramètres de la fonction.

95
Les procédures et fonctions Les sous-programmes

2. Déclaration d’une fonction


Une fonction se déclare de la manière suivante :

function nom_de_la_fonction (liste_des_paramètres) : type_de_résultat ;

Reprenons nos exemples,

- calculer la racine carrée d’un nombre réel :


function racine (x : real ): real ;

- transformer un nombre d’heures, minutes, secondes en secondes :


function HMS ( h e u r e s , m i n u t e s , s e c o n d e s : i n t e g e r ) : integer ;

- calculer la somme des N premiers nombres entiers :


function sommeN (n : integer ) : integer :

- calculer le PGCD de deux entiers :


function PGCD( n1 , n2 : integer ) : integer :

- calculer an où a est un nombre réel non nul et n est un nombre entier :


function puissance (a : real ; n: integer ) : real ;

- tester si un nombre est premier :


function estPremier (n : integer ) : boolean ;

- calculer le nombre de voyelles d’une chaîne de caractères :


function voyelles (s : string ) : integer ;

- mettre une chaîne en majuscules :


function majuscules (s : string ) : string ;

- extraire une partie de chaîne :


function extract (s : string ; ou , combien : integer ) : string :

- calculer le nombre de mots d’un texte :


function nbMots (f : Text ) : integer ;

- calculer l’élément maximum d’un tableau de réels :


function maxTab ( tab : tableauReels ; n : integer ) : real ;

où tableauReels est défini comme


type tableauReels = array [1..1000] of real ;

et n est le nombre d’éléments réellement utilisés du tableau


- calculer le nombre de fois que se trouve un entier dans un tableau d’entiers :
function nbFois ( tab : tableauEntiers ; n : integer ) : integer ;

où tableauEntiers est défini comme


type tableauEntiers = array [1..10000] of integer ;

et n est le nombre d’éléments réellement utilisés du tableau

96
Les procédures et fonctions Les sous-programmes

3. Appel d’une fonction


L’appel d’une fonction est son utilisation (on se sert de la fonction). Il suffit d’écrire
le nom de la fonction et de respecter le nombre et le type des paramètres. Par exemple,
- appels de la fonction racine
y := racine (2.0); // y ≈ 1.414
z := racine (8); // z ≈ 2.828
writeln ( racine ( y+z ) : 0 : 5 ) ; // ache 2, 05977

où x,y et z sont des réels


- appels de la fonction HMS
nbSecondes := HMS ( 5 , 2 8 , 5 4 ) ; // nbSecondes vaut 19734
nbSecondes := n b S e c o n d e s + HMS( h , m, s ) ;

où h,m,s,nbSecondes sont des entiers


- calculer la somme des N premiers nombres entiers :
somme := sommeN (100); // somme vaut 5050
writeln ( sommeN ( sommeN ( 5 ) ) ) ; // ache 120

- calculer le PGCD de deux entiers :


resultat := PGCD( 6 4 , 4 0 ) ; // resultat vaut 8

- ···

97
Les procédures et fonctions Les sous-programmes

4. Programme complet
1 program exempleFonction ;
2
3 ( * *********** Fonction qui calcule 1+2+3+ ... +N ************ * )
4 function sommeN ( n : i n t e g e r ) : i n t e g e r ;
5 var som : integer ; // Variable de travail
6 i : integer ; // Indice de boucle
7 begin
8 som := 0;
9 for i := 1 to n do
10 som := som + i ;
11 Result := som ; // ou sommeN := som ;
12 end ;
13
14 ( * ******* Fonction qui calcule le nombre de voyelles ******** * )
15 function string
nbVoyelles ( s : ) : integer ;
16 const VOYELLES = // Constante qui contient toutes les voyelles
' aeiouyAEIOUY ' ;
17 var cptVoy // Compteur de voyelles
: integer ;
18 i // Indice de boucle
: integer ;
19 begin
20 cptVoy := 0;
21 for to Length
i := do1 (s)
22 i f Pos then
(s[ i ] , VOYELLES) > 0
23 inc // inc(v) signie augmenter v de 1
( cptVoy ) ;
24 Result // ou nbVoyelles := cptVoy ;
:= cptVoy ;
25 end ;
26
27 ( * ****************** Programme principal ******************** * )
28 var nombre : integer ;
29 chaine : string ;
30 cptVoy : integer ;
31 begin
32 write ( ' Veuillez entrer un entier : ' );
33 readln ( nombre ) ;
34 writeln ( ' 1+2+3+...+ ' , nombre , ' vaut ' , sommeN ( nombre ) ) ;
35
36 write ( ' Veuillez entrer une chaine : ' );
37 readln ( chaine ) ;
38 cptVoy := nbVoyelles ( chaine ) ;
39 writeln ( chaine , ' contient ' , cptVoy , ' voyelle ( s ) ' );
40
41 readln ;
42 end .

Commentaires
(a) La ligne 4 est la déclaration de la fonction. Elle comprend le nom de la fonc-
tion (sommeN), la liste des paramètres formels (n :integer) et le type de ré-
sultat (integer).
La ligne 15 est la déclaration de la fonction. Elle comprend le nom (nbVoyelles), la liste des
paramètres formels (s :string) et le type de résultat (integer).
(b) Les lignes 5 et 6 sont les variables locales de la fonction. Ces variables ne sont
connues que dans la fonction où elles sont déclarées.
Les lignes 16, 17 et 18 sont les variables et constante locales de la fonction. Ces variables et
constante ne sont utilisables que dans la fonction où elles sont déclarées.

98
Les procédures et fonctions Les sous-programmes

(c) Les lignes 5 → 12 forment le corps de la fonction.


Les lignes 16 → 25 forment le corps de la fonction.
(d) La ligne 11 est le résultat calculé par la fonction.
La ligne 24 est le résultat calculé par la fonction.
(e) Les lignes 28 → 42 forment le programme principal (c’est ce qui s’exécute).
i. Les lignes 28, 29 et 30 sont les variables du programme principal 3 .
ii. La ligne 34 est l’appel (exécution) de la fonction et nombre est le para-
mètre réel. Les paramètres formels et réels n’ont pas obligatoirement le
même nom mais doivent être de même type.
La ligne 38 est l’appel de la fonction et chaine est le paramètre réel. Les paramètres
formels et réels n’ont pas obligatoirement le même nom mais doivent être de même type.
iii. Au moment de l’appel, le paramètre réel est copié dans le paramètre for-
mel puis la fonction s’exécute.

6.3.2 Les procédures


1. Définitions
Les fonctions sont parfois d’un usage trop restrictif parce qu’elles ont pour but de
calculer une valeur unique. Les procédures lèvent cette restriction.
Exemples :
(a) on utilisera une procédure pour transformer un nombre de secondes en heures,
minutes, secondes (4000 secondes = 1H6’40”). Il y a trois valeurs à calculer.
(b) on utilisera une procédure pour dessiner un rectangle dont on connaît la largeur et
la hauteur a . Il n’y a rien à calculer.
a. on suppose qu’on dessine le rectangle à l’endroit où se trouve le curseur

Comme les fonctions, les procédures auront un nom, des paramètres formels et un
corps comprenant une partie déclarative et une séquence d’instructions. Contrai-
rement aux fonctions, les procédures ne retournent aucune valeur.
Une procédure se déclare de la manière suivante :

procedure nom_de_la_procedure (liste_des_paramètres) ;

3. Si les variables avaient été déclarées au début (ligne 2), elles devenaient des variables globales

99
Les procédures et fonctions Les sous-programmes

On distingue deux catégories de paramètres formels, selon que leur valeur doit être
connue au début de l’exécution de la procédure ou calculée dans la procédure. On
appelle paramètres d’entrée ceux dont la valeur doit être connue pour que les ins-
tructions de la procédure puissent être exécutées, mais qui ne doivent pas subir de
modification. Les paramètres pour lesquels la procédure détermine une valeur sont
les paramètres de sortie.
(a) pour le premier exemple, il y a un paramètre d’entrée (le nombre de secondes)
et trois paramètres de sortie (le nombre d’heures, de minutes, de secondes).
On la déclare :
procedure HMS( s e c o n d e s : i n t e g e r ; var h , m, s : i n t e g e r ) ;

les paramètres de sortie sont précédés du mot var.


(b) pour le deuxième exemple, il n’y a que des paramètres d’entrée (coordonnées
de deux points). On la déclare :
procedure d e s s i n e ( largeur , hauteur : i n t e g e r ) ;

2. Programme complet

1 program exempleProcedure ;
2
3 ( * ************ Procedure qui transforme en HMS ************ * )
4 procedure HMS( s e c o n d e s : i n t e g e r ; var h , m, s : i n t e g e r ) ;
5 var reste : integer ; // Variable de travail
6 begin
7 h := secondes div 3600;
8 reste := secondes mod 3600;
9 m := reste div 60;
10 s := reste mod 60;
11 end ;
12
13 ( * ************* Proc é d u r e qui dessine ************** * )
14 procedure d e s s i n e ( largeur , hauteur : i n t e g e r ) ;
15 var ligneEtoiles : string ; ( * **************************** * )
16 ligneBlancs : string ; (* *)
17 i : integer ;
18 begin
19 ligneEtoiles := StringOfChar * ( ' ' , largeur );
20 ligneBlancs := '* ' StringOfChar
+ ( ' ' , largeur − 2) + '* ' ;
21
22 writeln ( ligneEtoiles );
23 for to
i :=1 h a u t e u r −2 do
24 writeln ( ligneBlancs );
25 writeln ( ligneEtoiles );
26 end ;
27

100
Les procédures et fonctions Les sous-programmes

28 ( * ***************** Programme principal ****************** * )


29 var largeur , hauteur : integer ;
30 secondesDepart , heures , minutes , s e c o n d e s : integer ;
31 begin
32 write ( ' Veuillez entrer une largeur : ' );
33 readln ( largeur );
34 write ( ' Veuillez entrer une hauteur : ' );
35 readln ( hauteur ) ;
36 dessine ( largeur , hauteur ) ;
37
38 write ( ' Veuillez entrer un nombre de secondes : ' );
39 readln ( secondesDepart ) ;
40 HMS( s e c o n d e s D e p a r t , h e u r e s , m i n u t e s , s e c o n d e s ) ;
41 write (secondesDepart,' secondes = ',heures,'H',minutes, ,secondes,  ) ;
42
43 readln ;
44 end .

Commentaires
(a) La ligne 4 est la déclaration de la procédure. Elle comprend le nom de la
procédure (HMS) et la liste des paramètres formels (secondes :integer ; var
h,m,s :integer).
On écrit var 4 devant les paramètres de sortie (ceux qui sont calculés dans la
procédure).
La ligne 14 est la déclaration de la procédure. Elle comprend le nom de la procédure (dessine)
et la liste des paramètres formels (largeur,hauteur :integer).
(b) La ligne 5 est la variable locale de la procédure. Cette variable n’est connue
que dans la procédure où elle est déclarée.
Les lignes 15, 16 et 17 sont les variables locales de la procédure.
(c) Les lignes 6 → 11 forment le corps de la procédure.
Les lignes 18 → 26 forment le corps de la procédure.
(d) Les lignes 31 → 44 forment le programme principal (c’est ce qui s’exécute).
i. Les lignes 29 et 30 sont les variables du programme principal 5 .
ii. La ligne 36 est l’appel (exécution) de la procédure et largeur,hauteur sont
les paramètres réels. Les paramètres formels et réels n’ont pas obligatoi-
rement le même nom mais doivent être de même type.
La ligne 40 est l’appel de la fonction et secondesDepart,heures,minutes,secondes sont
les paramètres réels. Les paramètres formels et réels n’ont pas obligatoirement le même
nom mais doivent être de même type.
iii. Au moment de l’appel, les paramètres réels sont substitués aux paramètres
formels puis la procédure est exécutée. Le point suivant explique plus en
détail cette substitution qui est appelée le passage des paramètres.

4. ne pas confondre avec VAR qui permet la déclaration de variables


5. Si les variables avaient été déclarées au début (ligne 2), elles devenaient des variables globales

101
Les procédures et fonctions Les sous-programmes

6.3.3 Le passage des paramètres


Il existe deux types de paramètres : les paramètres formels, présents lors de la décla-
ration (définition) de la procédure ou de la fonction et qui ne prennent aucune valeur et
les paramètres réels qui, au moment de l’appel de la procédure ou de la fonction sont sub-
stitués aux paramètres formels. Cette substitution, appelée passage des paramètres, peut
prendre deux formes : le passage par valeur et le passage par adresse.

Le passage par valeur


Dans un passage par valeur, le paramètre formel est considéré comme une variable
locale dans le corps du sous-programme. Sa valeur est initialisée au début de chaque exé-
cution du sous-programme avec la valeur du paramètre réel correspondant.
Il y a recopie de la valeur du paramètre réel dans le paramètre formel. Toutes les
opérations qui sont effectuées sur le paramètre formel n’affectent que cette valeur locale.
procedure sp ( . . . x: real ....);

Figure 6.4 – Le passage par valeur

102
Les procédures et fonctions Les sous-programmes

Le passage par adresse


Dans un passage par adresse, le paramètre formel est traité comme une variable dont
l’adresse qui est transmise au moment de chaque appel est celle du paramètre réel corres-
pondant.
Le paramètre réel et le paramètre formel sont la même variable. Le passage par adresse
autorise toutes les modifications immédiatement sur le paramètre réel quelle que soit sa
localisation.
procedure sp (.... var x : real );

Figure 6.5 – Le passage par adresse

Le passage par adresse se reconnaît grâce au mot VAR.

Avantages et des inconvénients des passages par valeur et adresse


- Passage par valeur
Avantages : - puisque le paramètre formel est une copie du paramètre réel, il est
impossible pour le sous-programme de modifier le paramètre réel. C’est
donc une sécurité ;
- le paramètre réel peut être une constante.
Inconvénients : - “lenteur” due à la recopie des données et doublement de la
place mémoire occupée (mais convient bien pour des variables simples !) ;
- ne permet pas de ressortir un résultat.
- Passage par référence
Avantages : - rapidité d’accès aux données, moindre occupation mémoire puis-
qu’il ne s’agit que d’une adresse ;
- permet de « ressortir » une valeur.
Inconvénients : - puisque le sous-programme travaille en réalité sur le para-
mètre réel, il y a danger de modifier le paramètre réel de manière erronée ;
- le paramètre réel ne peut être une constante.

103
Les procédures et fonctions Les sous-programmes

Exemple
program Exemple ;

procedure B1 (x : integer ; var y : integer ) ;


begin
y := 10 * x;
end ;

procedure B2 (x : integer ; y : integer ) ;


begin
y := 10 * x;
end ;

// Programme principal ou appelant


var a, b: integer ;
begin
a := 100 ; b := 0 ;
B1 ( a , b ) ;
writeln ( 'a = ' , a, ' b = ' , b);
// a vaut 100 et b vaut 1000

a := 100 ; b := 0;
B2 ( a , b ) ;
writeln ( 'a = ' , a, ' b = ' , b);
// a vaut 100 et b vaut 0

readln ;
end .

6.3.4 Variables locales, globales – Effet de bord


On appelle variable locale à un sous-programme (procédure ou fonction), une variable
qui n’a de sens que pour ce sous-programme (ou pour tous les sous-programmes de niveau
hiérarchique inférieur 6 ).
Inversement, une variable globale est une variable qui a un sens en dehors du sous-
programme.

6. Ce cas ne sera pas étudié dans ce cours.

104
Les procédures et fonctions Les sous-programmes

Exemples et remarques

1 program Exemple ;
2 var a,b : real ;
3 procedure P1 ;
4 var c ,d : real ;
5 begin
6 .
7 .
8 .
9
10 end ;
11 procedure p2 ;
12 var e, f : real ;
13 begin
14 .
15 .
16 .
17 end ;
18 // Programme principal
19 begin
20 .
21 .
22 .
23 end .

- les variables a et b (ligne 2) sont globales et sont accessibles aux deux procédures
et au programme principal ;
- les variables c et d (ligne 4) ne sont accessibles que par la procédure P1 ;
- les variables e et f (ligne 12) ne sont accessibles que par la procédure P2 ;
- si une variable déclarée dans le corps d’un sous-programme (variable locale) porte
le même nom qu’une variable globale, c’est la variable locale qui sera accessible
dans le sous-programme ;
program Exemple ;
var a,b : real ;
procedure P1 ;
var a,c : real ;
begin
. // a représente la variable locale
.
.

end ;
// Programme principal
begin
.
.
.
end .

- la modification d’une variable globale par un sous-programme est appelée effet de


bord (”side effect”).
Bien qu’il soit parfois approprié de laisser agir les sous-programmes sur le variables

105
Les procédures et fonctions Les sous-programmes

globales, cette pratique doit être utilisée avec énormément de prudence et le pro-
grammeur débutant devrait toujours l’éviter. Considérons le programme suivant :
program effetDeBord ;
var g : integer ; // g est une variable globale
function F( x : i n t e g e r ) : integer ;
begin
g := g +1; // La variable globale est modiée ici : eet de bord
Result := x + g;
end ;
// Programme principal ou appelant
begin
g := 0;

writeln (F ( 0 ) ) ; // Ache 1
writeln (F ( 0 ) ) ; // Ache 2
writeln (F ( 0 ) ) ; // Ache 3
writeln (F ( 0 ) ) ; // Ache 4

readln ;
end .

La fonction F est appelée avec la même valeur de paramètre (0) et elle donne quatre
résultats différents.
De plus, il faut savoir que les modifications accidentelles de variables globales par
un sous-programme sont des erreurs qui sont souvent difficiles à détecter.

106
Les procédures et fonctions Les sous-programmes

6.3.5 Exercices
1. Considérons le programme suivant :
program principal ;
var a : real ;
procedure p(x : real ) ;
begin
x := 1.0;
end ;
begin
a := 0.0;
p(a ) ;
write (a );
end .

(a) qu’imprime par write(a) ?


(b) qu’imprime par write(a) si l’entête de la procédure est
procedure p( var x: real );

2. Considérons les deux procédures

procedure p1 ( x , y : i n t e g e r ) ; procedure p2 ( var x , y : integer );


var t : integer ; var t : integer ;
begin begin
t := x; t := x;
x := y; x := y;
y := t; y := t;
end ; end ;

Si a = 3 et b = 5,
(a) quel est le résultat de l’appel p1(a,b) ?
(b) quel est le résultat de l’appel p2(a,b) ?
3. Écrire un sous-programme qui calcule 1 + 2 + 3 + · · · + N .
4. Écrire un sous-programme qui calcule N ! = 1 × 2 × 3 · · · × N .
5. Écrire un sous-programme qui teste si un entier est premier.
6. Écrire un sous-programme qui calcule an (a est un double (réel) ; n est un entier
quelconque positif, négatif ou nul) sans utiliser [Link].
7. Écrire un sous-programme qui calcule le pgcd (plus grand commun diviseur) de
deux nombres entiers positifs.
pgcd(16, 24) = 8
pgcd(80, 90) = 10
8. Écrire un sous-programme qui réduit une fraction à sa plus simple expression :
39 13
=
42 14
128 32
=
12 3
107
Les procédures et fonctions Les sous-programmes

9. Écrire un sous-programme qui affiche tous les nombres de Pythagore compris entre
1 et N (x2 + y 2 = z 2 ).
10. Écrire un sous-programme qui calcule le nombre de voyelles d’une chaîne de carac-
tères.
11. Écrire un sous-programme qui calcule la somme des éléments d’un tableau d’entiers.
12. Écrire un sous-programme qui calcule le produit scalaire de deux tableaux (vecteurs)
n
X
T1 • T2 = T 1[i]T 2[i]
i=1

Par exemple, si T1 = 2,5,7,9 et T2 = 4,2,3,1 alors le produit scalaire vaut


2 × 4 + 5 × 2 + 7 × 3 + 9 × 1 = 48
13. Écrire un sous-programme qui calcule le minimum des éléments d’un tableau de
réels (double).
14. Écrire un sous-programme qui génère aléatoirement un tableau (préciser l’énoncé).
15. Écrire un sous-programme qui dit combien de fois un entier se trouve dans un tableau
d’entiers.
16. Écrire un sous-programme qui trie un tableau.
17. Écrire la recherche dichotomique grâce à une fonction ; le tableau sera au préalable
trié grâce à une autre fonction (ou procédure).
18. L’aire d’un cercle de rayon 1 est π et l’aire d’un carré qui contient exactement ce
cercle est 4. Ainsi, si un grand nombre de points sont choisis aléatoirement dans la
partie supérieure droite du carré, la proportion de ces points qui seront dans le cercle
est approximativement π/4. Calculer une valeur approximative de π.

19. Programmer le jeu du « pendu ».


20. Programmer le jeu « mastermind ».
21. Écrire un programme qui génère deux nombres aléatoires entre 0 et 100 et choisit une
opération au hasard (+,-,*,/). Le programme affiche l’opération et lit le résultat. Si
la réponse donnée est incorrecte, il donne une deuxième chance. Si elle est toujours
incorrecte, le programme donne la bonne réponse. Tous les 10 exercices, il rappelle
le nombre de bonnes réponses.

108
Les procédures et fonctions Les sous-programmes

22. Trouver une racine d’une équation grâce à la méthode des intervalles. Commençant
en un point arbitraire, f(x) est évalué en une série de points qui sont distants d’une
valeur ∆ donnée. Si on trouve que le signe de f(x) a changé entre deux évaluations
successives, c’est qu’on a passé une racine.

(a) (b)

(a) Entre x et x + ∆, la fonction f(x) ne change pas de signe

f (x) > 0 et f (x + ∆) > 0

c’est donc qu’il n’y a aucune racine entre x et x + ∆.


(b) Entre x + ∆ et x + 2∆, la fonction f(x) change de signe

f (x + ∆) > 0 et f (x + 2∆) < 0

c’est donc qu’il y a une racine entre x + ∆ et x + 2∆. Dans ce cas, on recom-
mence avec ∆ diminué de moitié et dans l’autre sens (en réalité ∆ = −∆/2)

109
Les procédures et fonctions Les sous-programmes

110
CHAPITRE 7
LES FICHIERS

Il est souvent nécessaire de stocker des informations de façon permanente. Le seul


moyen envisageable, mis à part l’utilisation d’une base de données, est l’utilisation de
fichiers.
Les fichiers sont universellement utilisés pour stocker des informations, et leur utilisa-
tion est permise de plusieurs manières en Pascal.

7.1 Différents types de fichiers


7.1.1 Fichiers texte
Les fichiers texte comportent du texte brut. Le texte contenu dans ce genre de fichiers
est réparti en lignes. Pour information, chaque ligne se termine, comme dans tous les fi-
chiers texte, par un marqueur de fin de ligne qui est constitué d’un ou de deux caractères
spéciaux : le retour chariot et éventuellement le saut de ligne (sous les environnements
Windows, les deux caractères sont généralement présents, contrairement aux environne-
ments de type UNIX qui favorisent le retour chariot seul).
Ces fichiers sont adaptés à des tâches très utiles :
- stocker du texte simple entré par l’utilisateur (fichiers TXT)
- écrire des fichiers de configuration (entre autre des fichiers INI)
- générer des fichiers lisibles par d’autres applications, comme des fichiers HTML
(pages web), CSV (texte réparti en colonnes).
- écrire des programmes dans différents langages (PAS, PHP, JAVA, C, ...)

7.1.2 Fichiers à accès direct


Ces fichiers sont structurés en éléments ou enregistrements (record) dont le type peut
être quelconque. Les éléments d’un fichier à accès direct se suivent logiquement, mais pas
forcément physiquement ; ils ont tous la même taille. Le terme accès direct signifie qu’il
est possible d’accéder directement à n’importe quel élément, pour autant que l’on spécifie
son rang.

111
Manipulation des fichiers texte Les fichiers

7.1.3 Fichiers binaires ou non typés


Ce dernier genre de fichier est en fait un genre universel, car tous les types de fichiers,
sans exception, peuvent être créés avec ce genre de fichier. Mais cela a un prix : les facilités
offertes en lecture/écriture par les fichiers texte ou les fichiers séquentiels n’existent pas
pour ce type de fichier.

7.2 Manipulation des fichiers texte


7.2.1 Ouverture et fermeture d’un fichier texte
Un fichier texte se manipule par l’intermédiaire d’une variable de type Text. La ma-
nipulation d’un fichier passe par trois étapes obligatoires : deux avant l’utilisation, et une
après. Voici la déclaration de la variable fichier :
var FichTest : Text ;

1. La première étape, avant utilisation, est l’étape d’assignation. Elle consiste à as-
socier à la variable-fichier le nom du fichier que nous voulons manipuler. Cette as-
signation se fait par l’appel d’une procédure très simple nommée Assign qui admet
deux paramètres. Le premier est la variable-fichier, le second est le nom du fichier
à manipuler. Voici l’instruction qui assigne le fichier c :\[Link] à la variable-fichier
FichTest déclarée ci-dessus :
Assign ( FichTest , ' c :\ test . txt ' ) ;

2. La deuxième étape consiste à ouvrir le fichier. Cette ouverture peut se faire suivant
trois modes différents suivant ce qu’on a besoin de faire pendant que le fichier est
ouvert. La méthode qu’on emploie pour ouvrir le fichier détermine ce mode d’ouver-
ture. Les trois modes possibles sont la lecture seule (écriture impossible), l’écriture
seule (lecture impossible), soit simplement l’ajout du texte à la fin du fichier (ajout
seul). Il n’est pas possible de pouvoir lire et écrire à la fois dans un fichier texte.
- Si on souhaite lire, il faut utiliser la procédure Reset. Si le fichier n’existe pas,
une erreur est générée (”File not found”). L’écriture n’est pas possible avec ce
mode d’ouverture.
- Si on souhaite écrire, il faut utiliser la procédure Rewrite. Si le fichier existe,
il sera écrasé. La lecture n’est pas possible avec ce mode d’ouverture.
- Si on souhaite juste ajouter du texte dans un fichier texte, il faut l’ouvrir en
utilisant la procédure Append. Cette procédure ouvre le fichier et permet d’y
écrire seulement. Ce qui est écrit sera ajouté à la fin du fichier.
Ces trois procédures s’utilisent de la même manière : on les appelle en donnant
comme unique paramètre la variable-fichier à ouvrir. Voici l’instruction qui com-
mande l’ouverture du fichier c :\[Link] en lecture seule :
Reset ( FichTest ) ;

Pour ouvrir le même fichier en écriture seule, il suffirait de substituer “Rewrite” (ou
“Append”) à “Reset”.

112
Manipulation des fichiers texte Les fichiers

3. La troisième étape est la fermeture du fichier. La procédure Close (qui accepte un


seul paramètre de type variable-fichier) ferme un fichier ouvert indifféremment avec
"Reset", "Rewrite" ou "Append". Voici l’instruction qui ferme le fichier :
Close ( FichTest ) ;

Voici donc une procédure qui ouvre un fichier en lecture seule et le ferme aussitôt.
procedure OuvrirFichier ;
var FichTest : Text ;
begin
Assign ( FichTest , 'C : \ T e s t \ F i c h . t x t ' ) ;
Reset ( FichTest ) ;
{ lecture possible dans le fichier ici }
Close ( FichTest ) ;
end ;

Existence d’un fichier Il est possible d’améliorer cette procédure d’ouverture, notam-
ment en contrôlant l’existence du fichier avant son ouverture, car un fichier inexis-
tant provoquerait une erreur gênante qu’il est possible d’éviter facilement. Voici une
méthode pour tester l’existence d’un fichier :
la fonction FileExists définie dans l’unité SysUtils teste si un fichier existe, le résultat
de cette fonction est donc un booléen.
program existenceFichier ;
{ Ce programme illustre l ' utilisation de FileExists }
uses sysutils ;
var fich : text ;
nomFichier String : ;
begin
write ( ' Entrez le chemin et le nom d ' ' un fichier : ' );
readln ( nomFichier ) ;
i f FileExists ( nomFichier ) then // = true inutile
begin
reset ( nomFichier ) ; // On est certain que le chier existe
.
.
.
end ;
end .

113
Manipulation des fichiers texte Les fichiers

7.2.2 Lecture depuis un fichier texte


La lecture se fait au choix par la procédure Read ou Readln ("READ LiNe", "lire ligne"
en anglais). La procédure Readln est la plus simple à utiliser car elle permet de lire une
ligne entière d’un fichier (pour rappel, un fichier texte est découpé en lignes). La procédure
Read, quant à elle, permet de lire de différentes manières : caractère par caractère, ou petit
morceau par petit morceau. Cette dernière technique est à éviter car elle prend plus de
temps que la lecture ligne par ligne, et tout ce que permet la procédure Read peut être
réalisé sur le texte lu au lieu d’être réalisé sur le texte à lire. La lecture ligne par ligne
(Readln) sera donc la seule étudiée ici.
Lorsqu’on ouvre un fichier texte, la “position” dans ce fichier est fixée à son début.
La “position” d’un fichier détermine à quel endroit aura lieu la prochaine opération sur ce
fichier. Pour lire une ligne d’un fichier, on utilise donc Readln. Readln est une procédure
très spéciale dans le sens où son nombre de paramètres est a priori indéterminé. Le premier
paramètre est la variable-fichier dans laquelle on désire lire. Les paramètres suivants sont
des variables permettant de stocker ce qui a été lu. Dans la pratique, on se limite très
souvent à une seule variable de type chaîne. Voici l’instruction qui lit une ligne du fichier
associé à la variable-fichier TestFile et qui la stocke dans la variable tmpS de type string :
Readln ( FichTest , tmpS ) ;

Il va de soi que pour que cette instruction fonctionne, il faut que le fichier soit ouvert.
Readln lit une ligne depuis la “position” en cours dans le fichier, jusqu’aux caractères de
fin de ligne (ceux-ci sont éliminés), puis fixe la nouvelle “position” au début de la ligne
suivante (sous réserve qu’elle existe, nous allons parler de l’autre cas un peu plus bas).
L’appel suivant à Readln lira la ligne suivante du fichier, et ainsi de suite jusqu’à ce qu’il
n’y ait plus de ligne après la position dans le fichier, c’est-à-dire lorsqu’on a atteint la
fin du fichier. Pour tester cette condition, on doit faire appel à une fonction nommée Eof
("End Of File", "Fin de fichier" en anglais). Cette fonction accepte en unique paramètre
une variable-fichier et renvoie un booléen qui indique si la position de fichier est la fin de
ce dernier, c’est-à-dire que lorsque Eof renvoie True, il n’y a plus de ligne à lire dans le
fichier.
La plupart du temps, lorsqu’on lit l’ensemble des lignes d’un fichier texte, il faut utiliser
une boucle while. Cette boucle permet de lire les lignes une par une et de tester à chaque
fois si la fin du fichier est atteinte. Voici un exemple d’une telle boucle while :
while not Eof ( FichTest ) do
Readln ( FichTest , tmpS ) ;

La boucle ci-dessus lit un fichier ligne par ligne jusqu’à la fin du fichier. Lorsque celle-
ci est atteinte, Eof devient vrai et la condition de continuation de la boucle n’est plus
respectée, et la lecture s’arrête donc d’elle-même.

114
Manipulation des fichiers texte Les fichiers

Voici notre procédure OuvrirFichier encore améliorée. Elle lit maintenant l’intégralité
du fichier transmis et ne fait rien avec ce qui a été lu :
procedure O u v r i r F i c h i e r ( chemin : string );
uses sysutils ;
var
FichTest : Text ;
tmpS : string ;
begin
i f not FileExists then
( chemin )
Exit // Arrêt si non existence
;
Assign ( FichTest , chemin ) ;
Reset ( FichTest ) ;
while not Eof do
( FichTest )
Readln ( FichTest , tmpS ) ;
Close ( FichTest ) ;
end;

7.2.3 Écriture dans un fichier texte


L’écriture dans un fichier texte s’effectue également ligne par ligne grâce à la procédure
Writeln, ou morceau par morceau avec la procédure Write. La procédure Writeln s’utilise
comme Readln, mis à part qu’elle effectue une écriture à la place d’une lecture. L’écriture
se fait à la position actuelle, qui est définie au début du fichier lors de son ouverture par
“Rewrite”, et à la fin par “Append”. Writeln ajoute la chaîne transmise sur la ligne actuelle
et insère les caractères de changement de ligne, passant la position dans le fichier à la
ligne suivante. Ainsi, pour écrire tout un fichier, il suffira d’écrire ligne par ligne en appe-
lant autant de fois Writeln qu’il sera nécessaire. Voici une procédure qui ouvre un fichier
c :\[Link] en tant que texte, et qui écrit deux lignes dans ce fichier. Après l’exécution de la
procédure, vous pourrez contrôler le résultat en ouvrant ce fichier dans le bloc-notes par
exemple. Attention au nom du fichier car l’ouverture avec Rewrite ne teste pas l’exis-
tence du fichier et il est donc possible d’écraser par mégarde un fichier important.
procedure T e s t E c r i t u r e ( Fich : string );
var F: Text ;
begin
Assign (F , Fich ) ;
Rewrite (F ) ;
Writeln (F , ` ceci est notre premier fichier texte ` ) ;
Writeln (F , ` rien de difficile ! `);
Close (F ) ;
end;

Dans l’exemple ci-dessus, le fichier texte est ouvert en écriture seule par Rewrite, puis
deux écritures successives d‘une ligne à chaque fois sont effectuées. Le fichier est ensuite
normalement refermé. L‘écriture est beaucoup plus simple que la lecture puisqu’on n’a
pas à se soucier de la fin du fichier.

115
Manipulation des fichiers texte Les fichiers

7.2.4 Exemple
procedure Ajout ;
(* Permet d`ajouter du texte (Bonjour) dans un chier Text *)
uses sysutils ;
var f : Text ;
string
ch : ;
string
chemin : ;
begin
chemin := ' c : \ temp \ t e s t . t x t ' ;

Assign ( f , chemin ) ;
i f not FileExists then ( chemin )
Rewrite // Création du chier
(f)
else
Append // Ouverture du chier pour y ajouter du texte
( f );

ch := ` Bonjour ` ;
writeln (f , ch ) ; // Ajoute ch et un n de ligne
Close ( f );
end ;

procedure Lire ;
( * Permet d e l i r e l e c o n t e n u d ` un f i c h i e r T e x t *)
uses sysutils ;
var f : Text ;
ch : string ;
chemin : string ;
begin
chemin := ' c : \ F i c h i e r s \ Fich . dat ' ;
i f not FileExists then
( chemin )
Exit // Arrêt si non existence
;
Assign ( f , chemin ) ;
Reset // Permet d`ouvrir le chier pour y lire
( f );
// Tant que la n de chier n`est pas atteinte
while Eof f a l s e do // ou while not Eof(f )
(f) =
begin
readln (f , // Lit une chaîne du chier
ch ) ;
writeln ( ch ) ; // et l'écrit à l'écran
end ;
Close ( f );
end ;

procedure Vider ;
( * V i d e un f i c h i e r −−> r e c r e l e f i c h i e r * )
é
var f : Text ;
begin
Assign ( f , ' c : \ temp \ t e s t . t x t ' ) ;
Rewrite ( f );// Création du chier
Close ( f );
end ;

116
Manipulation des fichiers texte Les fichiers

7.2.5 Effacement d’un fichier


L’effacement d’un fichier texte s’effectue grâce à la procédure Erase. Le fichier doit
être assigné mais pas ouvert.
Assign ( f , chemin ) ;
Erase ( f );

7.2.6 Renommage d’un fichier


Le renommage d’un fichier texte s’effectue grâce à la procédure Rename. Le fichier
doit être assigné mais pas ouvert.
Assign ( f , chemin ) ;
Rename (f , nouveau_nom ) ;

117
Manipulation des fichiers texte Les fichiers

7.2.7 Exercices
1. Compter le nombre de lignes d’un fichier texte.
2. Mettre tous les caractères d’un fichier texte en majuscules.
3. Lire un fichier texte et y remplacer les voyelles par #.
4. Dans un fichier HTML, remplacer les balises gras par italique.
5. Rechercher le nombre de fois qu’apparaît un mot donné dans un fichier texte.
6. Écrire un programme qui affiche le contenu d’un fichier texte en faisant précéder
chaque ligne par son numéro.
7. Créer un fichier texte appelé [Link] et y stocker des valeurs (de type string)
récupérées depuis le clavier jusqu’à la lecture de la chaîne ’FIN’ (peut importe la
casse, ’fin’ ou ’fIn’). La chaîne de caractère, ’FIN’ en l’occurrence ne sera pas sto-
ckée dans le fichier.
8. Compter le nombre de mots d’un fichier texte.
9. Calculer la fréquence d’apparition des lettres dans un fichier texte.
10. Écrire un programme qui affiche le contenu d’un fichier texte en ignorant les lignes
de commentaires et en supprimant les blancs en début de ligne.
- Les caractères “blancs” sont les espaces et les tabulations 1 .
- Les lignes dont le premier caractère non blanc est un § seront considérées
comme des commentaires.

Ainsi, le fichier texte suivant :

Ÿ Une famille
Raymonde
Robert
Ÿ et leurs enfants:
Jules
Jim
Ÿ fin

sera affiché comme ceci :

Raymonde
Robert
Jules
Jim

1. Chr(9) est le caractère qui représente une tabulation

118
Manipulation des fichiers à accès direct Les fichiers

11. Ajouter des élèves dans un fichier texte. On suppose que les lignes du fichier res-
semblent à celles-ci :
r e f e r e n c e : nom : prenom

Par exemple le fichier pourrait contenir :


1 2 : Bob : Morane
3 : B r u c e : Wayne
1 8 : Corben : D a l l a s

12. Ajouter des élèves dans un fichier texte. On suppose que les données sont de largeur
fixe : 3 caractères pour la référence, 20 pour le prénom et 15 pour le nom.
Par exemple le fichier pourrait contenir (sans la première ligne qui est un “repère”) :
12312345678901234567890123456789012345
12 Bob Morane
3 Bruce Wayne
18 Corben Dallas

7.3 Manipulation des fichiers à accès direct


Voici un exemple de déclarations liées au traitement d‘un fichier à accès direct :
type element =
record
nom : string [12];
age : integer ;
end ;
var personne : element ;
f : f i l e of element ;

Le schéma suivant illustre l’organisation logique des premiers enregistrements du fichier f :

Rang 0 1 2 3
Nom Durant Mercier César Alex
Age 24 44 37 67

Chaque enregistrement d’un fichier à accès direct peut être accédé en spécifiant son
rang. Un pointeur de fichier mémorise le rang de l’enregistrement concerné par la pro-
chaine opération de lecture ou d’écriture. Lorsqu’un fichier est ouvert, son pointeur indique
l’enregistrement de rang zéro, c’est-à-dire le premier enregistrement. Après chaque opéra-
tion de lecture ou d’écriture, le pointeur de fichier est incrémenté du nombre d’enregistre-
ments lus ou écrits. Un enregistrement est l’unité minimale de transfert d’information entre
un fichier et un programme. Le contenu des fichiers à accès direct est stocké sous forme
binaire compactée et n’est donc pas directement affichable à l’écran. Il est également im-
portant de savoir que l’on peut accéder de manière séquentielle à un fichier à accès direct.
Très souvent les éléments d’un fichier à accès direct sont de type enregistrement.

119
Manipulation des fichiers à accès direct Les fichiers

7.3.1 Déclaration du type de fichier à accès direct


La déclaration d’un fichier à accès direct est effectuée à l’aide des mots réservés file of :

type client =record


code : string [10];
nom : string [40];
solde : real ;
premiere_facture : integer ;
derniere_facture : integer ;
end ;
var fichier_client : f i l e of client ;
un_client : client ;
ch : char ;

En plus d’une variable de type fichier, il faut définir une variable dont le type est celui
des éléments de ce fichier. Cette dernière un_client est utilisée comme paramètre par les
procédures de lecture et d’écriture. Elle tient lieu de variable intermédiaire, ou de mémoire
tampon.

7.3.2 Assignation de fichier


La procédure Assign remplit le même rôle que pour les fichiers texte :
assign ( fichier_client , ` CLIENT . DAT` ) ;

7.3.3 Ouverture de fichier


Cette opération est effectuée par l’une des procédures reset ou rewrite, comme pour
les fichiers de type texte :
rewrite ( fichier_client ); { le fichier peut exister }
reset ( fichier_stock ); { le fichier doit exister }

L’emploi de la procédure reset nécessite l’existence préalable du fichier. En revanche


l’utilisation de la procédure rewrite crée et ouvre inconditionnellement un fichier. Si un
fichier portant le même nom existait déjà, son contenu serait perdu. Il convient donc d’être
prudent lors de la création d’un fichier à l’aide de cette procédure.
Contrairement aux fichiers texte, l’ouverture avec Reset permet la lecture et l’écri-
ture dans un fichier.

7.3.4 Positionnement à l’intérieur d’un fichier


A chaque fichier utilisé dans un programme est associé un pointeur permettant au sys-
tème et à l’utilisateur de connaître l’emplacement du prochain élément accessible. La pro-
cédure
seek ( nom_de_fichier , no )

permet de positionner le pointeur associé au fichier nom_de_fichier sur l’enregistrement


numéro no, en vue d’une opération de lecture ou d’écriture. Il faut se rappeler que le
premier enregistrement d’un fichier porte le numéro zéro.

120
Manipulation des fichiers à accès direct Les fichiers

7.3.5 Instructions de lecture et d’écriture


La procédure de lecture est
read ( nom_de_fichier , liste_elements )

et celle d’écriture est


write ( nom_de_fichier , liste_elements )

où liste_elements est une liste de variables du même type que les éléments du fichier. Il
est important de savoir qu’à chaque écriture et à chaque lecture le pointeur associé au
fichier est automatiquement incrémenté de manière à être positionné sur l’enregistrement
suivant. Partant de ce principe, la modification du contenu de l’enregistrement numéro 5
d’un fichier implique, par exemple, les opérations suivantes :
seek ( fichier_client , 5);
read ( fichier_client , un_client ) ;
. . .{ modification des donn é e s contenues dans un_client }
seek ( fichier_client , 5);
write ( fichier_client , un_client ) ;

7.3.6 Enregistrement courant et taille d’un fichier


La fonction
FilePos ( nom_de_fichier )

fournit le rang de l’enregistrement courant. La fonction


FileSize ( nom_de_fichier )

donne la taille du fichier, exprimée en nombre d’éléments. Le fragment de programme


suivant permet de déterminer si un fichier est vide :
if filesize (f) = 0 then
writeln ( ` Fichier vide ` ) ;

7.3.7 Fin de fichier


La fonction booléenne
Eof ( nom_de_fichier )

indique si la fin du fichier nom_de_fichier est atteinte, comme pour les fichiers texte

7.3.8 Fermeture de fichier


La fermeture d‘un fichier à accès direct s‘effectue de la même manière que pour un
fichier de type texte :
close ( fichier_client );

7.3.9 Effacement et renommage d’un fichier


L’effacement et le renommage s’utilisent de la même manière que pour les fichiers
texte.

121
Manipulation des fichiers à accès direct Les fichiers

7.3.10 Troncature d’un fichier


Cette procédure permet de couper à l’endroit actuel le contenu du fichier.
Truncate ( fichier_client );

7.3.11 Exemples
1. Lire le contenu d’un fichier d’enregistrements et afficher les renseignements à l’écran.
program LireFileRecord ;
uses sysutils ;
type TEleves =
record
numero : Integer ;
nom : String [20];
prenom String
: [20];
sexe : char ;
natio : String [3];
classe String
: [4];
localite String
: [30];
points : integer ;
end ;
var unEleve : TEleves ;
fichEleves f i l e of
: TEleves ;
chemin : string ;
begin
chemin := 'C : \ U s e r s \ H e n r o t t e \ Dropbox \ Travaux \ d e v _ P a s c a l \ R e c o r d \ E l e v e s N u m L i m
i f not FileExists ( chemin ) then
begin
writeln ( ' Le chemin du fichier n ' ' est pas correct ou alors le fichier n'
writeln ( ' Fermeture du programme . ' ) ;
readln ;
exit ;
end;

assign ( f i c h E l e v e s , chemin ) ;
reset ( fichEleves );
while eof ( fichEleves ) = f a l s e do
begin
read ( f i c h E l e v e s , unEleve ) ;
writeln ( u n E l e v e . numero : 3 , ' ' ,
u n E l e v e . nom , StringOfChar ( ' ' ,20 − length( u n E l e v e . nom ) ) ,
u n E l e v e . prenom , StringOfChar ( ' ' ,20 − length ( u n E l e v e . prenom ) ) ,
unEleve . sexe , StringOfChar ( ' ' ,2 − length( unEleve . s e x e ) ) ,
unEleve . natio , StringOfChar ( ' ' ,4 − length ( unEleve . n a t i o ) ) ,
unEleve . c l a s s e , StringOfChar ( ' ' ,5 − length ( unEleve . c l a s s e ) ) ,
[Link],' ', StringOfChar(' ',30-length([Link])) ,
unEleve . p o i n t s ) ;

end;
close ( fichEleves );
readln ;
end .

122
Manipulation des fichiers à accès direct Les fichiers

2. L’exemple qui suit


- copie un fichier d’élèves dans un tableau (le fichier est supposé existé et remplit
d’élèves) ;
- trie le tableau sur le champ nom ;
- affiche le tableau qui vient d’être trié ;
- recopie le tableau dans un autre fichier.

program ProgEl ;
uses sysutils ; // pour leExists

type TEleve = record


nom : String [20];
prenom String
: [20];
sexe : char ;
nationalite String: [3];
classe String
: [4];
localite String
: [30];
points : Integer ;
end ;
var eleve : TEleve ; // un élève
memoire : TEleve ; // pour le tri et contient un élève
f : f i l e of TEleve ; // chier de départ
f_tri : f i l e of TEleve ; // chier trié
tabEleves array
: [1..1000] of TEleve ; // pas plus de 1000 élèves
nbEleves : integer ; // le nombre d'élèves
i : integer ;
echange : boolean ; // pour le tri

begin
( * Arr t s i l e f i c h i e r
ê n' existe pas *)
i f not f i l e E x i s t s ( ' c : \ 5 6 TTi \ C r e e F i c h \ E l e v e s . d a t ' ) then
begin
write ( ' Fichier inexistant ! ' );
readln ;
halt ;
end ;

123
Manipulation des fichiers à accès direct Les fichiers

(* Copie du fichier dans le tableau *)


assign ( f , ' c : \ 5 6 TTi \ C r e e F i c h \ E l e v e s . d a t ' ) ;
reset ( f );
nbEleves := 0;
while not eof (f) do
begin
read ( f , eleve ); // lire un enregistrement
n b E l e v e s += 1 ; // incrémenter l'indice
tabEleves [ nbEleves ] := eleve ; // copier l'enregistrement dans le tableau
end ;
close ( f );

(* Tri ` ` bulle ' ' *)


repeat
echange := false ;
for i := 1 to n b E l e v e s −1 do
begin
if t a b E l e v e s [ i ] . nom > t a b E l e v e s [ i + 1 ] . nom then
begin
memoire := tabEleves [ i ] ;
tabEleves [ i ] := tabEleves [ i +1];
t a b E l e v e s [ i +1] := memoire ;
echange := true ;
end ;
end ;
until echange = false ;

(* Affichage du tableau *)
for to
i :=1 nbEleves do
begin
with tabEleves [ i ] do
begin
writeln ( nom , ' ' , prenom , ' ' , sexe , ' ' , nationalite , ' ' ,
classe , ' ' , localite , ' ' , points ) ;
end ;
end ;

(* Copie du tableau d a n s un fichier qu ' on c r ée *)


assign ( f _ t r i , ' c : \ 5 6 TTi \ C r e e F i c h \ E l e v e s T R I . d a t ' ) ;
rewrite ( f_tri );
for to
i :=1 nbEleves do
write ( f_tri , tabEleves [ i ] ) ;
close ( f_tri );

readln ;
end .

124
Manipulation des fichiers à accès direct Les fichiers

3. Le but de l’exemple ci-dessous est de remplir un fichier d’élèves mais sans devoir
encoder les renseignements soi-même. En général, il est facile de transférer les
données d’un logiciel ou d’une base de données vers un format texte.
On suppose qu’on dispose d’un fichier texte dont la structure est

Nom%Prénom%Sexe%Nationalité%Classe%Localité%Points%

Chaque renseignement est séparé du suivant par le caractère %


Par exemple,

COLPIN%Cyril%M%F%5Pb%LONGUYON%26%
FROGNET%Victorien%M%B%5Pb%IRE-LE-SEC%94%
GEORGES%Bastien%M%B%5Pb%ROBELMONT%76%
GOMEZ%Michel%M%F%5Pb%CHATILLON%21%
LUQUER%Christopher%M%F%5Pb%LUXEMBOURG%61%
WESOLOWSKI%Arnaud%M%F%5Pb%MONDELANGE%50%
ALEXANDRE%Valentin%M%B%5Pc%MEIX-DEVANT-VIRTON%96%
CHERIAK%Mustapha%M%DZ%5Pc%SAINT NICOLAS-DE-PORT%57%
COLLIGNON%Thomas%M%B%5Pc%SAINT-VINCENT%64%
FORGET%Dorian%M%B%5Pc%PALISEUL%23%
..
.

On voudrait créer un fichier d’enregistrements qui reprend le contenu du fichier texte


ci-dessus.
program Transfert ;
uses sysutils ;
type TEleves =// Renseignements pour chaque élève
record
nom String
: [20];
prenom String : [20];
sexe : char ;
natio String : [3];
classe String : [4];
localite String : [30];
point : integer ;
end ;

var f : text ;
unEleve : TEleves ;
fichEleves f i l e of : TEleves ;
chemin , c h string : ;
strPoint String // Points transformés en chaîne
: ;
position : integer ; // Trouve le prochain caractère %
code : Integer ;

125
Manipulation des fichiers à accès direct Les fichiers

begin
chemin := 'C : \ d e v _ P a s c a l \ Text_Record \ E l e v e s . t x t ' ;
// Teste l'existence du chier, arrêt s'il n'existe pas
i f not FileExists ( chemin ) then
begin
writeln ( ' Le chemin du fichier n ' ' est pas correct ou alors le fichier n ' ' existe
writeln ( ' Fermeture du programme . ' ) ;
readln ;
exit // Quitte
;
end ;

// Ouverture
assign ( f , chemin ) ;
reset ( f );
assign ( f i c h E l e v e s , 'C : \ d e v _ P a s c a l \ Text_Record \ E l e v e s . r e c ' ) ;
rewrite ( fichEleves );

while eof (f) = f a l s e do


begin
readln ( f , ch ) ;

// Extraction du nom
position := pos ( '% ' , c h ) ; // Recherche de la position du %
u n E l e v e . nom := copy ( ch , 1 , p o s i t i o n − 1 ) ; //Extraction du nom jusqu'au % non compris
Delete ( ch , 1 , p o s i t i o n ) ; // Eacement du nom et du %

// Extraction du prénom
position := pos ( '% ' , c h ) ;
u n E l e v e . prenom := copy ( ch , 1 , p o s i t i o n −1);
Delete ( ch , 1 , p o s i t i o n ) ;

// Extraction du sexe
unEleve . Sexe := c h [ 1 ] ;
Delete ( ch , 1 , 2 ) ;

// Extraction de la nationalité
position := pos ( '% ' , c h ) ;
unEleve . n a t i o := copy ( ch , 1 , p o s i t i o n −1);
Delete ( ch , 1 , p o s i t i o n ) ;

// Extraction de la classe
position := pos ( '% ' , c h ) ;
unEleve . c l a s s e := copy ( ch , 1 , p o s i t i o n −1);
Delete ( ch , 1 , p o s i t i o n ) ;

// Extraction de la localité
position := pos ( '% ' , c h ) ;
unEleve . l o c a l i t e := copy ( ch , 1 , p o s i t i o n −1);
Delete ( ch , 1 , p o s i t i o n ) ;

// Extraction des points (attention, c'est une chaîne dans le chier texte)
position := pos ( '% ' , c h ) ;
strPoint := copy ( ch , 1 , p o s i t i o n −1);
Val ( s t r P o i n t , unEleve . point , code ) ; // Transformation en numérique
Delete ( ch , 1 , p o s i t i o n ) ;

126
Manipulation des fichiers à accès direct Les fichiers

// Ecriture de l'enregistrement dans le chier d'enregistrements


write ( f i c h E l e v e s , unEleve ) ;
end ;

close ( f );
close ( fichEleves );

readln ;
end .

Remarque with : au lieu d’écrire


e l e v e . nom := ··· ;
e l e v e . prenom := ··· ;
.
.
.

on peut écrire
with eleve do
begin
nom := ··· ;
prenom := ··· ;
.
.
.
end ;

7.3.12 Exercice : gestion simplifiée d’un fichier d’élèves


Supposons qu’un fichier contienne des enregistrements dont la structure est :
type TEleves =
record
numero : Integer ;
nom : String [20];
prenom String
: [20];
sexe : char ;
natio : String [3];
classe String
: [4];
localite String
: [30];
points : integer ;
end ;

1. Afficher tous les renseignements de tous les élèves.


2. Rechercher un élève connaissant son nom (il peut y en avoir plusieurs).
3. Rechercher un élève connaissant son numéro.
4. Calculer le nombre de filles.
5. Trouver l’élève dont le champ "points" est maximum.
6. Supprimer un élève connaissant son numéro.
7. Insérer un nouvel élève (son numéro sera 1 de plus que le dernier numéro).
8. Modifier les renseignements d’un élève.
9. Trier le fichier par ordre alphabétique (le plus simple est de passer par un tableau).

127
Fichiers non typés Les fichiers

10. Trier le fichier par classe.


11. En supposant que le fichier soit trié par classe,
(a) compter le nombre d’élèves par classe (algorithme de rupture) ;
(b) calculer les points moyens par classe.
.
12. ..
Remarques
- ne pas utiliser de tableaux (sauf pour les tris)
- on peut utiliser Seek, FilePos et FileSize

7.4 Fichiers non typés


Les fichiers non typés se déclarent à l’aide du mot réservé file :
var fichier : file ; { et non : file of . . . }

Une variable de type file permet d’accéder à un fichier quelconque, sans connaître sa struc-
ture, ni son contenu. Les opérations de lecture et d’écriture sont effectuées par les pro-
cédures BlockRead et BlockWrite. Les opérations d’assignation et de fermeture sont les
mêmes que pour les fichiers à accès direct ou de type texte.
Program FichierSansType ;
(*
Ce programme illustre BlockRead et BlockWrite
en copiant un fichier d a n s un autre .
*)
Var F_In , F_Out : File ; // Fichiers entrée et sortie
NumRead , NumWritten : Word ;
Buf : Array [1..2048] of byte ;
Total : Longint ;
begin
Assign ( F_In , 'C: \ 5 6 TTi \ p r o j e c t . e x e ' ) ;
Assign ( F_Out , 'C: \ 5 6 TTi \ c o p i e . e x e ' ) ;
Reset ( F_In , 1); // 1 = taille d'un enregistrement
Rewrite ( F_Out , 1);

Total := 0;
Repeat
BlockRead ( F_In , Buf , Sizeof ( Buf ) , NumRead ) ;
BlockWrite ( F_Out , Buf , NumRead , NumWritten );
inc ( Total , NumWritten ) ;
Until ( NumRead = 0 ) or ( NumWritten <> NumRead ) ;
Write ( Total , ' caractères ont été copiés ! ' ) ;

Close ( F_In ) ;
Close ( F_Out ) ;

Readln ;
end .

128
CHAPITRE 8

COMPLÉMENTS

8.1 L’unité CRT


8.1.1 Quelques constantes
Black = 0 Green = 2 LightRed = 12
Blink = 128 LightBlue = 9 Magenta = 5
Blue = 1 LightCyan = 11 Red = 4
Brown = 6 LightGray = 7 White = 15
Cyan = 3 LightGreen = 10 Yellow = 14
DarkGray = 8 LightMagenta = 13

8.1.2 Quelques fonctions ou procédures


ClrEol KeyPressed TextColor
ClrScr ReadKey WhereX
Delay Sound WhereY
GotoXY TextBackground Window

ClrEol
ClrEol clears the current line, starting from the cursor position, to the end of the win-
dow. The cursor doesn’t move.

ClrScr
ClrScr clears the current window (using the current colors), and sets the cursor in the
top left corner of the current window.

Delay
Delay waits a specified number of milliseconds. The number of specified milliseconds
is an approximation, and may be off a lot, if system load is high.

129
L’unité CRT Compléments

GotoXY
GotoXY positions the cursor at (X,Y), X in horizontal, Y in vertical direction relative
to the origin of the current window. The origin is located at (1,1), the upper-left corner of
the window.
Program Example ;
uses Crt ;
begin
ClrScr ;
GotoXY (10 ,10) ;
Write ( ' 10 ,10 ' ) ;
GotoXY (70 ,20) ;
Write ( ' 70 ,20 ' ) ;
GotoXY (1 ,22) ;
end .

KeyPressed
Keypressed scans the keyboard buffer and sees if a key has been pressed. If this is the
case, True is returned. If not, False is returned.
The Shift, Alt, Ctrl keys are not reported. The key is not removed from the buffer, and can
hence still be read after the KeyPressed function has been called.

130
L’unité CRT Compléments

ReadKey

ReadKey reads 1 key from the keyboard buffer, and returns this. If an extended or
function key has been pressed, then the zero ASCII code is returned. You can then read
the scan code of the key with a second ReadKey call.
Program Example ;
uses Crt ;
var ch : char ;
begin
writeln ( ' Press L e f t / R i g h t /Up/Down , E s c=Q u i t ' ) ;
repeat
ReadKey
ch := ;
case of ch
begin
#0 :
ReadKey { Read
ch := ; ScanCode }
case of ch
writeln #75 : ( ' Left ' ) ;
writeln #77 : ( ' Right ' ) ;
writeln #80 : ( ' Down ' ) ;
writeln #72 : ( ' Up ' ) ;
end ;
end ;
writeln
#27 : ( ' ESC ' ) ;
end ;
until { Esc }
c h=#27
end .

On trouve la liste de tous les "scancodes" aux pages 720 et 721 du fichier [Link] (cf.
page 134).

Sound

Sound(hz) sounds the speaker at a frequency of hz. Under Windows, a system sound
is played and the frequency parameter is ignored.

TextBackground

TextBackground(color) sets the background color to color. color can be one of the
predefined color constants.
Program Example ;
uses Crt ;
begin
TextColor ( White ) ;
Writeln ( ' Ecriture en blanc sur le fond par dé f a u t ' ) ;
TextBackground ( Green ) ;
Writeln ( ' Ecriture en blanc sur un fond vert ' ) ;
TextBackground ( Brown ) ;
Writeln ( ' Ecriture en blanc sur un fond brun ' ) ;
TextBackground ( Black ) ;
Writeln ( ' Retour à un fond noir ' ) ;
end .

131
L’unité CRT Compléments

TextColor
TextColor(color) sets the foreground color to color. color can be one of the predefined
color constants.

WhereX
WhereX returns the current X-coordinate of the cursor, relative to the current window.
The origin is (1,1), in the upper-left corner of the window.

WhereY
WhereY returns the current Y-coordinate of the cursor, relative to the current window.
The origin is (1,1), in the upper-left corner of the window.

Window
Window creates a window on the screen, to which output will be sent. (X1,Y1) are
the coordinates of the upper left corner of the window, (X2,Y2) are the coordinates of
the bottom right corner of the window. These coordinates are relative to the entire screen,
with the top left corner equal to (1,1). Further coordinate operations, except for the next
Window call, are relative to the window’s top left corner.
Program Example ;
uses Crt ;
{ Program t o demonstrate the Window function }
begin
ClrScr ;
WriteLn ( ' Creating a window from 30 ,10 to 50 ,20 ' ) ;
Window ( 3 0 , 1 0 , 5 0 , 2 0 ) ;
WriteLn ( 'We a r e now writing in this small window we just created ' ) ;
Write ( ' Press any key to clear the window ' ) ;
ReadKey ;
ClrScr ;
Write ( ' The window is cleared , press any key to restore to full screen ' ) ;
ReadKey ;
{ Full Screen is 80 x 2 5 }
Window ( 1 , 1 , 8 0 , 2 5 ) ;
Clrscr ;
Writeln ( ' Back in Full Screen ' ) ;
end .

132
L’unité CRT Compléments

Réalisation d’un menu simple

program UMenuComplet ;
uses crt ;
var optionEncours : Integer ;
choix : Char ;
begin
optionEncours := 1; // C'est la premiere option qui est choisie au depart
CursorOff ; // Rend le curseur invisible

repeat
TextBackground ( Black ) ; // Remettre un fond noir
ClrScr ; // Eacement de l'écran

// Achage d'un titre


TextColor ( LightRed ) ;
GotoXY (1 ,1);
Writeln ( ' Titre de mon application ' ) ;
TextColor ( White ) ;

// Achage des options du menu


GotoXY (1 ,3);
if optionEncours = 1 then
TextBackground ( Green )
else
TextBackground ( Black ) ;
Write ( ' Premiere option du menu ' ) ;

GotoXY (1 ,4);
if optionEncours = 2 then
TextBackground ( Green )
else
TextBackground ( Black ) ;
Write ( ' Deuxieme option du menu ' ) ;

GotoXY (1 ,5);
if optionEncours = 3 then
TextBackground ( Green )
else
TextBackground ( Black ) ;
Write ( ' Troisieme option du menu ' ) ;

GotoXY (1 ,6);
if optionEncours = 4 then
TextBackground ( Green )
else
TextBackground ( Black ) ;
Write ( ' Quatri ' + Chr (138) + ' me option du menu ' ) ;

GotoXY (1 ,7);
if optionEncours = 5 then
TextBackground ( Green )
else
TextBackground ( Black ) ;
Write ( ' Quitter ' ) ;

133
L’unité CRT Compléments

// Test de la touche frappée


choix := readkey ;
case choix of
#0 : // Touche "spéciale"
begin
choix readkey // Lecture du scancode
:= ;
case of
choix
#80 :
begin // Down
if then
optionEncours = 5
optionEnCours := 1
else
optionEnCours := optionEncours + 1 ;
end ;
#72 :
begin // Up
if then
optionEncours = 1
optionEnCours := 5
else
optionEnCours := optionEncours − 1;
end ;
end ;
end // Fin du cas #0
;

#13 : // Enter
begin
Window ( 3 0 , 1 0 , 7 0 , 2 0 ) ; // Création d'une fenêtre
TextColor ( Blue ) ;
TextBackground ( Yellow ) ;
Write ( ' Vous avez choisi l ' ' option ' , optionEnCours ) ;
( * ********************************************
* C' e s t i c i qu ' on t e s t e l ' o p t i o n c h o i s i e e t *
* qu ' on e x é c u t e l a b o n n e p r o c é d u r e *
******************************************** * )
Readln ;
Window ( 1 , 1 , 8 0 , 2 5 ) ; // La fenêtre est tout l'écran
end ; // Fin du cas #13
end ; // Fin du Case choix
until ( c h o i x = #13) and ( optionEncours = 5);

end .

Pour plus de détails concernant l’unité CRT, veuillez consulter le chapitre 40 du manuel
de référence :
Free Pascal version 3.0.0:
Reference guide for RTL units.
Document version 3.0
November 2015

134
L’unité GRAPH Compléments

8.2 L’unité GRAPH


Cette unité contient des procédures et fonctions qui permettent de travailler au niveau
du pixel donc de dessiner ou de réaliser des graphiques.
Cf. The GRAPH unit ou le chapitre 18 du manuel de référence mentionné ci-dessus.

8.3 L’unité WINCRT


If you use the Graph unit under Win32, you can’t use the API mouse unit for
mouse support or use the win32 Crt unit to get keyboard data. The reason for
this is that the window popped up is a GUI window, and not a console one.
The wincrt unit provides some auxiliary routines for use with the graph unit,
namely keyboard support. It has no connection with the crt unit.

8.3.1 Fonctions et procédures


delay readkey
keypressed sound
Cf. le chapitre 45 du manuel de référence mentionné ci-dessus.

135
L’unité WINCRT Compléments

136
Deuxième partie

Exercices supplémentaires

137
CHAPITRE 1

LES BOUCLES

1. Écrire un programme qui affiche les nombres de 1 à 10.


2. Écrire un programme qui affiche les nombres de 20 à 1 de trois en trois. Exemple :
20 19 18
17 16 15
14 13 12
..
.
3. Écrire un programme qui calcule la somme des entiers de 1 à 100.
4. Même programme que précédemment, mais cette fois-ci l’utilisateur indique la li-
mite. Par exemple, si l’on entre 10, le programme doit calculer :
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 55
5. Écrire un programme qui saisit un entier et qui l’affiche à l’envers. Par exemple,
l’utilisateur saisit 123456 et le programme affiche 654321. Pour cela il faudra utili-
ser la division et le modulo.
Rappel : 153 mod 10 = 3 et 153 div 10 = 15
Remarque : Il est également possible d’utiliser les chaînes de caractères pour ré-
soudre cet exercice.
6. Écrire un programme qui saisit deux nombres entiers positifs et calcule le premier
à la puissance du second.
7. Écrire un programme qui demande un nombre de départ, et qui ensuite affiche les
dix nombres suivants. Par exemple, si l’utilisateur entre le nombre 17, le programme
affichera les nombres de 18 à 27.
8. Étant donné un entier naturel n, écrire un programme qui calcule la somme des
carrés des nombres entiers inférieurs ou égaux à n. Pour 5, il faut calculer
1 + 22 + 32 + 42 + 52 = 55
9. Écrire un programme qui saisit une date sous la forme de trois entiers (jour, mois
et année). Le programme doit tester si la date est correcte, et si ce n’est pas le cas,

139
Les boucles

doit signaler le type d’erreur rencontrée, puis demander une nouvelle saisie. Le pro-
gramme finit lorsqu’une date correcte est enfin saisie, avec l’affichage de celle-ci.
Dans le cas où le mois de la date est février, votre programme devra calculer si
l’année est bissextile 1 . De manière générale, il devra calculer le nombre de jours
maximal du mois de la date saisie, de manière à valider le numéro de jour qui a été
saisi.
10. Écrire un programme qui demande à l’utilisateur un jour, un mois et une année et
qui affiche le [Link] exemple, si l’utilisateur fournit :
jour : 31
mois : 12
année : 1999
le programme affiche : 1/01/2000.
11. Écrire un programme qui demande un nombre de départ, et qui ensuite écrit la table
de multiplication de ce nombre, présentée comme suit (cas où l’utilisateur entre le
nombre 7) :
Table de 7 :
7x1=7
7 x 2 = 14
7 x 3 = 21
···
7 x 10 = 70
12. Écrire un programme qui demande un nombre de départ, et qui calcule la somme des
inverses des entiers jusqu’à ce nombre. Par exemple, si l’on entre 5, le programme
doit calculer :
1 1 1 1
1 + + + + = 2, 2833
2 3 4 5
13. Écrire un programme qui demande un entier et qui calcule sa factorielle.
NB : la factorielle de 8, notée 8!, vaut 1 × 2 × 3 × 4 × 5 × 6 × 7 × 8 (= 40320)
14. Écrire un programme qui lit 10 nombres saisis au clavier et affiche le nombre de
valeurs négatives lues.
15. Écrire un programme qui lit des nombres saisis au clavier et s’arrête au premier
nombre négatif.
16. Écrire un programme qui demande successivement 8 nombres à l’utilisateur, et qui
lui dise ensuite quel était le plus grand parmi ces 8 nombres.
17. Modifiez ensuite le programme pour qu’il affiche, en plus, en quelle position était le
plus grand.
18. Réécrire le programme précédent, mais cette fois-ci on ne connaît pas d’avance com-
bien l’utilisateur souhaite saisir de nombres. La saisie des nombres s’arrête lorsque
l’utilisateur entre un zéro.
19. Le crible d’Ératosthène. La façon la plus simple de trouver des nombres premiers est
d’utiliser un algorithme appelé crible d’Eratosthène (IIIe av. JC). L’idée est simple.
Pour obtenir les nombres premiers inférieurs à n :
1. Une année A est bissextile si A est multiple de 4, toutefois, les années séculaires (siècles) ne sont
bissextiles que si A est multiple de 400.

140
Les boucles

- Écrire tous les entiers de 2 à n,


- Enlever (ou barrer) les multiples de 2 sauf 2,
- Récupérer le plus petit nombre non barré, c’est à dire 3, et barrer les multiples
de 3 sauf 3,
- Récupérer le plus petit nombre non barré, c’est à dire 5, et barrer les multiples
de 5 sauf 5,
- ···

- On s’arrête dès qu’on a atteint n.
Les nombres non barrés sont les nombres premiers.
20. L’utilisateur saisit un caractère, le programme teste s’il s’agit d’une lettre majuscule,
si oui il renvoie cette lettre en minuscule, sinon il renvoie un message d’erreur.
21. Saisir une suite de caractères, compter et afficher le nombre de lettres ’e’ et d’es-
paces.
22. L’utilisateur saisit le nom d’un fichier. Le programme vérifie que celui-ci possède
l’extension .PAS
23. Écrire un programme qui remplace dans une chaîne de caractères les voyelles par
des tirets ("-"). Par exemple, pour
'la balle au bond rebondit bien',
il faut obtenir
'l- b-ll- -- b-nd r-b-nd-t b--n'
24. Écrire un programme qui calcule la valeur d’un nombre écrit en chiffres romains.
25. Écrire un programme qui affiche le nombre des entiers qui sont des multiples de 3
et inférieurs à un nombre n donné par l’utilisateur.
26. Écrire un programme qui affiche tous les entiers pairs inférieurs à une valeur entière
n entrée par l’utilisateur.
27. On se propose de déterminer si un nombre est "couicable" (mot inventé), c’est-à-dire
si la somme des chiffres de sa partie gauche est égale à la somme des chiffres de sa
partie droite (le nombre de chiffres le composant doit être pair).
28. Écrire un programme qui lit un nombre entier et qui dessine ce qui suit (pour 10)

29. Écrire un programme qui demande à l’utilisateur de taper 10 entiers et qui affiche la
somme et le plus petit de ces entiers.

141
Les boucles

30. Écrire un programme affichant une table de multiplication sous la forme :

1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100

31. Écrire un programme qui demande à l’utilisateur de taper un entier n et qui calcule
un défini par :
u0 = 3
un+1 = 3un + 4
32. Écrire un programme qui demande à l’utilisateur de taper un entier n et qui calcule
un défini par :
u0 = 1
u1 = 1
un+1 = un + un−1
33. Écrire un programme qui permet de faire des opérations sur un entier (valeur initiale
à 0). Le programme affiche la valeur de l’entier puis affiche le menu suivant :
1 Ajouter 1
2 Multiplier par 2
3 Soustraire 4
4 Quitter
Le programme demande alors de taper un entier entre 1 et 4. Si l’utilisateur tape une
valeur entre 1 et 3, on effectue l’opération, on affiche la nouvelle valeur de l’entier
puis on réaffiche le menu et ainsi de suite jusqu’à ce qu’on tape 4. Lorsqu’on tape 4,
le programme se termine.
34. Écrire un programme qui demande à l’utilisateur de taper des entiers strictement po-
sitifs et qui affiche leur moyenne. Lorsqu’on tape une valeur négative, le programme
affiche Erreur et demande de retaper une valeur. Lorsqu’on tape 0, cela signifie que
le dernier entier a été tapé. On affiche alors la moyenne. Si le nombre d’entiers tapés
est égal à 0, on affiche Pas de moyenne.
35. Écrire un programme qui demande à l’utilisateur de saisir un entier n et qui affiche
le nombre de nombres premiers inférieurs ou égaux à n.
36. Écrire un programme qui demande à l’utilisateur de saisir un entier N et qui affiche
la figure suivante.

142
Les boucles

Pour N =1
*
Pour N =2
**
*
Pour N =3
***
**
*
..
.
37. Écrire un programme permettant d’estimer la valeur de π selon la formule suivante :
π 1 1 1 1 1 1
=1− + − + − + ··· −
4 3 5 7 9 11 9999

38. Réduire une chaîne de caractères qui contient des répétitions : "aaaaaabbbccd" donne
"abcd"
39. Extraire d’une chaîne de caractères différents éléments séparés entre eux par un ca-
ractère "séparateur". Par exemple, la chaîne "C :/Users/henrotte/Dropbox/Travaux/-
Word" contient 6 éléments séparés par le caractère "/"
40. Extraire les n derniers caractères d’une chaîne
41. Effacer toutes les occurrences 2 d’une sous-chaîne
42. Remplacer toutes les occurrences d’une sous-chaîne par une autre
43. Rechercher où apparaît la ne occurrence d’une chaîne
44. Le nombre 720 a 30 diviseurs (1, 2, 3, 4, 5, 6, 8, 9, ..., 360, 720). Un autre nombre,
supérieur à 720 mais inférieur à 1000, en a encore plus. Écrire un programme qui
permet de découvrir ce nombre et d’afficher ses diviseurs à raison de 5 diviseurs par
ligne.
45. Écrire un programme permettant de trouver les 3 premiers couples de nombres ami-
caux. Informations complémentaires : deux nombres sont dits amicaux si la somme
des diviseurs stricts de l’un est égale à l’autre.
Exemple :
diviseurs stricts de 220 : 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110
diviseurs stricts de 284 : 1, 2, 4, 71, 142
220 et 284 sont deux nombres amicaux car :
1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284
1 + 2 + 4 + 71 + 142 = 220
Solution : 220 et 284, 1184 et 1210, 2620 et 2924
46. La conjecture de Syracuse
L’algorithme de Syracuse consiste à itérer l’opération suivante : à un nombre entier
n, on associe n2 si n est pair et 3n + 1 si n est impair. On conjecture (on ne sait
toujours pas si c’est vrai) que quel que soit l’entier considéré initialement dans cet
algorithme, on arrive toujours à 1 après un certain nombre d’itérations. C’est en
2. Une occurrence est une apparition d’une unité linguistique dans un énoncé.

143
Les boucles

tout cas vrai pour tous les entiers avec lesquels l’algorithme a été testé. Écrire un
programme qui demande à l’utilisateur un entier initial, qui effectue l’algorithme de
Syracuse, affiche tous les nombres obtenus jusqu’au premier 1 et donne le nombre
d’itérations effectuées jusqu’à l’obtention du premier 1.
47. Factorisation d’un entier
2088 = 23 × 32 × 29
Il s’agit tout simplement de diviser le nombre par 2 le plus possible, puis par 3 le
plus possible, ...
Ainsi pour décomposer 2088 en produit de facteurs premiers
2088 2 2 divise 2088 le quotient est 1044
1044 2 2 divise 1044 le quotient est 522
522 2 2 divise 522 le quotient est 261
261 3 3 divise 261 le quotient est 87
87 3 3 divise 87 le quotient est 29
29 ni 3, ni 5 ne divisent 29 et 72 est plus grand que 29 (fin)
360 = 23 × 32 × 5
Autres exemples : 1050 = 2 × 3 × 52 × 7
1827 = 32 × 7 × 29
4752 = 24 × 33 × 11
48. Le code de César consiste à crypter un message en remplaçant chaque lettre par celle
qui se trouve 3 rangs à droite dans l’alphabet (et bien sûr "x", "y" et "z" deviennent
respectivement "a", "b" et "c"). Par exemple "exemple" devient "hahpsoh". Écrire
un algorithme qui crypte un mot entré au clavier en utilisant le code de César.
49. Combien un caissier a-t-il de façons de rendre la monnaie de n francs avec des pièces
de 1, 2, 5 et 10 francs ?
50. Écrire un programme qui calcule le nombre minimum de billets et/ou de pièces qu’il
faut pour un achat donné en euros sachant qu’il n’y a pas de centimes. Le programme
doit indiquer combien et quels pièces et/ou billets ont été nécessaire.
- Les billets sont 5, 10, 20, 50, 100, 200 et 500 €
- Les pièces sont 1 et 2 €.
51. Un numéro de compte bancaire au format belge BBAN (Belgian Bank Account Number)
est formé de 12 chiffres (par exemple, 510-0075470-61). La vérification de la vali-
dité d’un numéro de compte se base sur le modulo 97 des 10 premiers chiffres, le
résultat de l’opération donnant les deux derniers chiffres. Par exemple,
5100075470 mod 97 = 61 (car 5100075470 = 52578097 × 97 + 61)
Écrire un programme qui teste la validité d’un compte BBAN.
52. Écrire un programme qui calcule la racine carrée d’un réel a avec la suite récurrente :
un+1 = 21 (un + a
un
)
avec une précision de 10 . Combien d’étapes a-t-il fallu ?
−6

144
Les boucles

53. Écrire un programme


√ demandant à l’utilisateur de saisir deux valeurs numériques x
et p et affichant x avec une précision p. On utilisera une méthode par dichotomie.
Par exemple, calculons la racine carrée de 10 avec une précision 0,001.
Dans l’exemple qui suit, m est le milieu de l’intervalle.
- Commençons
√ par
√ la chercher dans [0, 10], on a m = 5, comme 5 > 10, alors
2

5 > 10, donc 10 se trouve dans l’intervalle [0, 5]



- On recommence, m = 2.5, comme 2.52 < 10, alors 2.5 < 10, on poursuit
la recherche dans [2.5, 5]

- On a m = 3.75, comme 3.752 > 10, alors 3.75 > 10, on poursuit la re-
cherche dans [2.5, 3.75]

- On a m = 3.125, comme 3.1252 < 10, alors 3.125 < 10, on poursuit la
recherche dans [3.125, 3.75]
- ···
m
54. Déterminer le nombre m tel que 1
> n ; n étant un nombre choisi par l’utilisa-
P
k
k=1
teur.
55. Écrire un programme qui calcule 1+
1
1
1+ 1
1+ 1
1
1+ 1+···

56. Écrire un programme qui calcule sin(x) en utilisant la formule d’approximation


suivante :
x3 x5 x7
sin(x) ≈ x − + − + ···
3! 5! 7!
x et le nombre de termes seront lus au clavier.

145
Les boucles

57. Écrire un programme qui calcule une valeur approchée de π avec trois méthodes
différentes.

Méthode 1
n
1 π X 1 1 1 1
− ≈ = + + + ···
2 8 k=1
(4k − 1)(4k + 1) 3 × 5 7 × 9 11 × 13
Si X est le résultat de l’approximation,
1 π
X= − ⇐⇒ π = 4 − 8X
2 8

Méthode 2 n
π2 X 1 1 1 1
≈ 2
=1+ + + + ···
6 k=1
k 4 9 16
Si X est le résultat de l’approximation,
π2 √
X= ⇐⇒ π = 6X
6

Méthode 3 n
π2 X 1 1 1 1
≈ 2
=1+ + + + ···
8 k=0
(2k + 1) 9 25 49
Si X est le résultat de l’approximation,
π2 √
X= ⇐⇒ π = 8X
8
Le programme doit indiquer l’erreur commise avec chacune des méthodes pour n
relativement grand (n ≥ 10000).
58. Les nombres a tels que (a + n + n2 ) est premier pour tout n tel que 0 6 n 6 (a − 2)
sont appelés nombres chanceux d’Euler.
5 est un nombre chanceux car 5 + 0 + 0 = 5 est premier, 5 + 1 + 1 = 7 est premier,
5 + 2 + 4 = 11 est premier et 5 + 3 + 9 = 17 est premier.
Leonhard Euler a identifié six nombres chanceux. Quels sont-ils ?.
59. Écrire un algorithme qui permette de connaître ses chances de gagner au tiercé,
quarté, quinté. On demande à l’utilisateur le nombre de chevaux partants, et le
nombre de chevaux joués. Les deux messages affichés devront être :
- Dans l’ordre : une chance sur X de gagner
- Dans le désordre : une chance sur Y de gagner
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,
n!
X=
(n − p)!
n!
Y =
p!(n − p)!

146
Les boucles

60. Recherche d’une racine d’une fonction par la méthode des intervalles.
Commençant en un point arbitraire, f(x) est évalué en une série de points qui sont
distants d’une valeur ∆ donnée. Si on trouve que le signe de f(x) a changé entre deux
évaluations successives, c’est qu’on a passé une racine.

(a) (b)

(a) Entre x et x + ∆, la fonction f(x) ne change pas de signe

f (x) > 0 et f (x + ∆) > 0

c’est donc qu’il n’y a aucune racine entre x et x + ∆.


(b) Entre x + ∆ et x + 2∆, la fonction f(x) change de signe

f (x + ∆) > 0 et f (x + 2∆) < 0

c’est donc qu’il y a une racine entre x + ∆ et x + 2∆. Dans ce cas, on recom-
mence avec ∆ diminué de moitié et dans l’autre sens (en réalité ∆ = −∆/2)

147
Les boucles

148
CHAPITRE 2
LES TABLEAUX

1. Générer un tableau de n éléments par des entiers aléatoires variant de 1 à n mais


tous différents.
2. Écrire un programme qui indique le nombre de fois où un élément apparaît dans un
tableau T d’entiers donnés.
3. Écrire un programme qui stocke la décomposition en facteurs premiers d’un nombre
entier strictement positif dans un tableau et ensuite affiche les éléments de ce tableau
sous la forme 18 = 2*3*3.
4. On dispose de 2 tableaux de même dimension note et coef qui contiennent respec-
tivement les notes d’un étudiant (sur 20) et les coefficients attribués aux matières
enseignées.
note[i] est la note obtenue dans la matière coef[i].
Écrire un programme pascal qui permet de calculer la moyenne de l’élève.
5. Écrire un programme qui lit (ou génère) un tableau de 10 caractères et effectue les
traitements suivants selon un menu :
- calcule le nombre de voyelles,
- compte le nombre d’occurrences d’un caractère,
- convertit les caractères en majuscule,
- affiche les caractères en horizontale,
- affiche les caractères en verticale,
- quitte.
6. Écrire un programme qui insère une valeur dans un tableau trié (en gardant bien sûr
le tableau trié).
7. Étant donné un tableau T de n nombres positifs ou nuls, écrire un programme qui le
tasse, c’est-à-dire qui détecte les éléments nuls du tableau et qui récupère leur place
en décalant vers le début du tableau tous les autres éléments.
Il ne faut donc utiliser qu’un seul tableau.
8. Écrire un programme qui calcule et renvoie la valeur d’un polynôme P (X), repré-
senté par le tableau de ses coefficients, pour une valeur donnée de la variable X.

149
Les tableaux

9. Écrire un programme qui lit la dimension N d’un tableau T (dimension maximale :


50 composantes), remplit le tableau par des valeurs générées aléatoirement et affiche
le tableau.
Le programme copiera ensuite toutes les composantes strictement positives dans un
deuxième tableau T P OS et toutes les valeurs strictement négatives dans un troi-
sième tableau T N EG. Afficher les tableaux T P OS et T N EG.
10. Écrire un programme qui génère deux tableaux d’entiers et qui calcule le schtroumph 1
de ces deux tableaux. Pour le calculer, il faut multiplier chaque élément du premier
tableau par chaque élément du second et additionner le tout. Par exemple,
Le schtroumph de 4 8 7 12 et 3 6 vaut 279 car

3 × 4 + 3 × 8 + 3 × 7 + 3 × 12 + 6 × 4 + 6 × 8 + 6 × 7 + 6 × 12 = 279
11. Soit T un tableau d’entiers. On suppose que ce tableau n’est pas trié. Écrire un
programme qui affiche l’élément qui apparaît le plus souvent dans le tableau T ,
ainsi que son nombre d’occurrences. Si plusieurs éléments différents répondent au
problème, votre programme doit en fournir un, quel qu’il soit.
(a) l’utilisation d’un second tableau est permise,
(b) il ne faut utiliser que le tableau T .
12. Soit T un tableau d’entiers de taille N . Une série dans T est une suite d’éléments
consécutifs et égaux de T . Le problème consiste à trouver la plus longue série dans
T , l’indice de son premier élément et sa longueur.
Par exemple, pour
2 2 6 6 6 6 9 9 9 9 9 1 0 0 0
le programme affichera la série est 9 elle commence à l’indice 7 et elle est de lon-
gueur 5.
13. Écrire un programme qui à partir d’un tableau d’entiers T , fournit le nombre de
sous-séquences strictement croissantes de ce tableau, ainsi que les indices de début
et de fin de la plus grande sous-séquence. Par exemple, si T vaut
1 2 5 3 12 25 13 8 4 7 24 28 32 11 14
Les séquences strictement croissantes sont :
- 1, 2, 5
- 3, 12, 25
- 13
- 8
- 4, 7, 24, 28, 32
- 11, 14.
Le nombre de sous-séquences est : 6 et la plus grande sous-séquence est : <4, 7, 24, 28, 32>.

1. Mot inventé

150
Les tableaux

14. Un point-clos est un élément d’une matrice qui est à la fois :


- un maximum sur la ligne et
- un minimum sur la colonne  
  0 7
3 2 1 !
Exemples : 
 
6 5 4
 1 7 9 8 8 9 
 
  4 6 0 6 6 7
9 8 7
 
8 8
Écrire un programme qui
(a) permet de lire une matrice au clavier, à savoir,
- lire le nombre de lignes,
- lire le nombre de colonnes,
- lire les différents éléments
(b) affiche la matrice,
(c) qui crée une nouvelle matrice M axLig à partir de la matrice saisie M at tel
que :
(
1 si M at[i, j] est un maximum sur la ligne i
M axLig[i, j] =
0 sinon

(d) qui crée une nouvelle matrice M inCol à partir de la matrice saisie M at tel
que :
(
1 si M at[i, j] est un minimum sur la ligne j
M inCol[i, j] =
0 sinon

(e) permet trouver et afficher tous les points-clos d’une matrice M at (affiche les
valeurs des éléments ainsi que leurs numéros de lignes et de colonnes) en uti-
lisant les matrices M axLig et M inCol
15. Écrire un programme qui multiplie deux matrices.
! ! !
1 0 3 1 3 1
× =
−1 3 2 1 3 2
 
! 5 1 !
1 2 0  9 7
× 2 3 =
4 3 −1   23 9
3 4
   
5 1 ! 9 13 −1
 
 2 3 × 1 2 0  
=
 14 13 −3 
  4 3 −1 
3 4 19 18 −4

151
Les tableaux

152
Troisième partie

Correction de quelques exercices

153
CHAPITRE 1

LES STRUCTURE DE CONTRÔLE

1.1 Exercices élémentaires : séquence


1. Afficher bonjour à l’écran.
program Bonjour ;
begin
//Ache Bonjour à l'écran, le curseur reste à la n de Bonjour
Write ( ' Bonjour ' ) ;

Readln //Pour éviter la fermeture de la fenêtre


;
end .

2. Afficher une carte de visite à l’écran.


program CarteDeVisite ;
begin
//Achage de la carte de visite
Writeln ( ' Jean // Writeln pour aller à la ligne après avoir écrit
Tanghe ' ) ;
Writeln ( ' rue des Alouettes , 68 ' ) ;
Writeln − ( 'B 6760 Virton ' ) ;

Readln //Pour éviter la fermeture de la fenêtre


;
end .

3. Calculer la somme et le produit de deux nombres réels.


program SommeProduit ;
var nombre1 , nombre2 , // Les deux nombres réels
somme , produit : // La somme et le produit
real ;
begin
//Lecture des deux nombres réels
Write ( ' Quel est le premier nombre ? ' );
Readln ( nombre1 ) ;
Write ( ' Quel est le second nombre ? ' );
Readln ( nombre2 ) ;

155
Exercices élémentaires : séquence Les structure de contrôle

//Calcul de la somme et du produit


somme := nombre1 + nombre2 ;
produit := nombre1 * nombre2 ;

//Achage de la somme et du produit


Writeln ( ' La somme est ' , somme : 0 : 3 ) ; // :0 :3 pour acher avec 3 décimales
Writeln ( ' Le produit est ' , produit : 0 : 3 ) ;

Readln ;
end .

4. Calculer l’aire et le périmètre d’un rectangle connaissant sa largeur et sa hauteur.


program AirePerimetre ;
var largeur , hauteur , // La largeur et la hauteur
aire , perimetre : real ; // L'aire et le périmètre
begin
//Lecture de la largeur et de la hauteur
Write ( ' Quelle est la largeur du rectangle ? ' );
Readln ( largeur );
Write ( ' Quelle est la hauteur du rectangle ? ' );
Readln ( hauteur ) ;

//Calcul de l'aire et du périmètre


aire := largeur * hauteur ;
perimetre := 2 * ( l a r g e u r+h a u t e u r ) ;

//Achage de l'aire et du périmètre


Writeln ( 'L ' ' a i r e est ' , aire :0:3); //deux ' pour en acher une
Writeln ( ' Le perimetre est ' , perimetre : 0 : 3 ) ;

Readln ;
end .

5. Calculer le volume de la sphère.


4
V = πR3
3

program VolumeSphere ;
var rayon , // Le rayon de la sphère
volume : // Le volume de la sphère
real ;
begin
// Lecture du rayon de la sphère
Write ( ' Quel est le rayon de la sphere ? ' );
Readln ( rayon ) ;

//Calcul du volume de la sphère


volume := 4/3* pi * rayon * rayon * rayon ;

//Achage du volume de la sphère


Writeln ( ' Le volume de la sphere est ' , volume : 0 : 3 ) ;

Readln ;
end .

156
Exercices élémentaires : séquence Les structure de contrôle

6. Échanger le contenu de deux variables.


program EchangeVariables ;
var variable1 , variable2 , // Les deux variables
echange : string ; // Une variable intermédiaire pour l'échange
// On peut prendre un autre type (integer, real...)
begin
// Lecture des deux variables
Write ( ' Quel est le contenu de la premiere variable ? ' );
Readln ( variable1 );
Write ( ' Quel est le contenu de la seconde variable ? ' );
Readln ( variable2 );

// Échange des contenus


echange := variable1 ; // On sauvegarde le contenu de variable1
variable1 := variable2 ; // On place le contenu de variable2 dans variable1
variable2 := echange ; //On récupère le contenu de variable1 et on le place dans variable2

// Achage du contenu des variables


Writeln ; //Pour acher une ligne blanche
Writeln ( ' Le contenu de la premiere variable est ' , variable1 );
Writeln ( ' Le contenu de la seconde variable est ' , variable2 );

Readln ;
end .

7. Calculer le quotient et le reste d’une division de deux entiers.


program QuotientReste ;
var dividende , // Le dividende et le diviseur
diviseur ,
quotient , reste // Le quotient et le reste
: integer ;
begin
// Lecture du dividende et du diviseur
Write ( ' Quel est le dividende ? ' );
Readln ( dividende ) ;
Write ( ' Quel est le diviseur ? ' );
Readln ( diviseur );

// Calcul du quotient et du reste


quotient := dividende div diviseur ; // div pour la division entière
// Ne pas confondre avec / pour la division réelle
r e s t e := d i v i d e n d e mod d i v i s e u r ; //mod pour le reste d'une division entière (modulo)

// Achage du quotient et du reste


Writeln ;
Writeln ( ' Le quotient est ' , quotient ) ;
Writeln ( ' Le reste est ' , reste );

Readln ;
end .

157
Exercices élémentaires : séquence Les structure de contrôle

8. Ce programme lit une température en degrés Celcius et l’affiche en degrés Fahren-


heit.
9
F arenheit = Celsius + 32
5
program CelciusVersFahrenheit ;
var celcius , // La température en degrés Celcius
fahrenheit // La température en degrés Fahtrenheit
: real ;
begin
// Lecture de la température en degrés Celcius
Write ( ' Quelle est la temperature en degres Celcius ? ' );
Readln ( celcius );

// Calcul de la température en degrés Fahrenheit


fahrenheit := 9/5* c e l c i u s + 32;

// Achage de la température en degrés Fahrenheit


Writeln ( ' La temperature en degres Fahrenheit est ' , fahrenheit : 0 : 3 ) ;

Readln ;
end .

9. Ce programme lit une température en degrés Fahrenheit et l’affiche en degrés Cel-


cius.
5
Celcius = (F arenheit − 32)
9
program CelciusVersFahrenheit ;
var fahrenheit , // La température en degrés Fahtrenheit
celcius // La température en degrés Celcius
: real ;
begin
// Lecture de la température en degrés Celcius
Write ( ' Quelle est la temperature en degres Fahrenheit ? ' );
Readln ( fahrenheit );

// Calcul de la température en degrés Fahrenheit


celcius := 5/9*( fa h re n he i t −32);

// Achage de la température en degrés Fahrenheit


Writeln ( ' La temperature en degres Celcius est ' , celcius :0:3);

Readln ;
end .

158
Exercices élémentaires : séquence Les structure de contrôle

10. Lire un nombre de secondes et le traduire en heures, minutes et secondes.


program SecondesHMS ;
var secondesTotales , // Le nombre de secondes lues
heures , minutes , secondes , // Le nombre d'heures, minutes et secondes
reste : integer ; // Le reste de la division
begin
// Lecture du nombre de secondes
Write ( ' Quel est le nombre de secondes ? ' );
Readln ( secondesTotales ) ;

// Calcul du nombre d'heures, minutes et secondes


heures := secondesTotales div 3600; //Il y a 3600 secondes dans une heure
reste := secondesTotales mod 3600; //Il reste encore des secondes
minutes := reste div 60; //Il y a 60 secondes dans une minute
secondes := reste mod 60; //Il reste des secondes

// Achage des heures, minutes et secondes


Writeln ( ' Il y a ' , heures , ' heure ( s ) ' , minutes , ' minute ( s ) ' ,
secondes , ' seconde ( s ) ' ) ;

Readln ;
end .

11. Ce programme transforme un angle donné en radians en degrés.


180
degre = radian
π

program RadiansVersDegres ;
var radians , degres // L'angle en radians et en degrés
: real ;
begin
// Lecture de l'angle en radians
Write ( ' Quelle est la valeur de l ' ' angle en radians ? ' );
Readln ( radians ) ;

// Transformation de l'angle en degrés


degres := 180/ pi * radians ;

// Achage de l'angle en degrés


Writeln ( 'L ' ' angle mesure ' , degres : 0 : 3 , ' degre ( s ) ' ) ;

Readln ;
end .

159
Exercices élémentaires : séquence Les structure de contrôle

12. Ce programme transforme un angle donné en degrés en radians.


π
radian = degre
180

program DegresVersRadians ;
var degres , radians : real ; //L'angle en degrés et en radians
begin
// Lecture de l'angle en degrés
Write ( ' Quelle est la valeur de l ' ' angle en degres ? ' );
Readln ( degres ) ;

// Transformation de l'angle en radians


radians := pi /180* d e g r e s ;

// Achage de l'angle en radians


Writeln ( 'L ' ' angle mesure ' , radians : 0: 3 , ' radian ( s ) ' ) ;
Readln ;
end .

13. Ce programme transforme un angle donné en degrés, minutes, secondes en radians.


program DMSVersRadians ;
var // L'angle en degrés, minutes et secondes
d e g r e s , minutes , s e c o n d e s : i n t e g e r ;
degresDecimaux , r a d i a n s // L'angle en degrés et en radians
: real ;
begin
// Lecture de l'angle en degrés, minutes et secondes
Write ( ' Quel le nombre de degres ? ' );
Readln ( degres ) ;
Write ( ' Quel le nombre de minutes ? ' );
Readln ( minutes ) ;
Write ( ' Quel le nombre de secondes ? ' );
Readln ( secondes ) ;

// Transformation de l'angle en radians


degresDecimaux := d e g r e s + minutes /60 + s e c o n d e s / 3 6 0 0 ;
radians := pi /180 * degresDecimaux ;

// Achage de l'angle en radians


Writeln ( 'L ' ' angle mesure ' , radians : 0: 3 , ' radian ( s ) ' ) ;

Readln ;
end .

160
Exercices élémentaires : séquence Les structure de contrôle

14. Ce programme transforme un angle donné en radians en degrés, minutes, secondes


et millièmes de secondes.
program RadiansVersDMSm ;
var degres , minutes , secondes , milliemes : integer ;
// L'angle en degrés, minutes, secondes, millièmes de seconde
degresDecimaux , minutesDecimales , s e c o n d e s D e c i m a l e s , r a d i a n s : real ;
// L'angle en degrés, minutes et en secondes décimales, et l'angle en radians
begin
// Lecture de l'angle en radians
Write ( ' Quel le nombre de radians ? ' );
Readln ( radians ) ;

// Transformation de l'angle en degrés, minutes, secondes et millièmes de seconde


degresDecimaux pi *
:= 180/ radians ;
degres := trunc ( degresDecimaux ) ; // Trunc = partie entière
minutesDecimales frac := ( degresDecimaux ) * 60; //Frac = partie décimale
minutes := trunc ( minutesDecimales ) ;
secondesDecimales frac := ( minutesDecimales ) * 60;
secondes := trunc ( secondesDecimales ) ;
milliemes := round frac ( ( secondesDecimales ) * 1000); //Round = arrondi

// Achage de l'angle en degrés, minutes, secondes et millièmes de seconde


Writeln ( 'L ' ' angle mesure ' , degres , ' degre ( s ) ' , minutes , ' minute ( s ) ' ,
secondes , ' seconde ( s ) ' , milliemes , ' millieme ( s ) ' ) ;

Readln ;
end .

15. Ce programme lit un nombre de jours et le transforme en années, mois, jours en


supposant qu’un mois contiendra toujours 30 jours.
program JoursVersAnneesMoisJours ;
var j o u r s T o t a l , a n n e e s , mois , j o u r s : i n t e g e r ; // Le nombre de jours total, d'années,
//de mois et de jours
reste : integer ; //Reste de division (pour le calcul)
begin
// Lecture du nombre de jours total
Write ( ' Quel est le nombre de jours ? ' );
Readln ( joursTotal ) ;

// Transformation du nombre de jours en années, mois et jours


annees := joursTotal div 360;
reste := joursTotal mod 360;
mois := reste div 30;
jours := reste mod 30;

// Achage du nombre d'années, mois et jours


Writeln ;
Writeln ( ' Il y a ' , annees , ' annee ( s ) ' , mois , ' mois ' , jours , ' jour ( s ) ' ) ;

Readln ;
end .

161
Exercices élémentaires : séquence Les structure de contrôle

16. Calculer la résistance totale de trois résistances en parallèle.


1 1 1 1
= + +
R R1 R2 R3

program ResistanceParallele ;
var R1 , R2 , R3 , R // Les trois résistances et la résistance totale
: real ;
begin
// Lecture des trois résistances
Write ( ' Quelle est la valeur de la premiere resistance ? ' );
Readln ( R1 ) ;
Write ( ' Quelle est la valeur de la deuxieme resistance ? ' );
Readln ( R2 ) ;
Write ( ' Quelle est la valeur de la troisieme resistance ? ' );
Readln ( R3 ) ;

// Calcul de la résistance totale


R := 1/R1 + 1/R2 + 1/R3 ;
R := 1/R ;

// Achage de la résistance totale


Writeln ( ' La resistance totale est ' ,R : 0 : 3 , ' ohm ( s ) ' ) ;

Readln ;
end .

17. Calculer le périmètre et l’aire d’un triangle dont on connaît la longueur des 3 côtés.
Si p est le demi-périmètre (p = a+b+c
2
), alors
p
Aire = p(p − a)(p − b)(p − c)

program AirePerimetreTriangle ;
var cote1 , cote2 , cote3 , // Les trois cotés
perimetre , aire : real ; // Le périmètre et l'aire
begin
// Lecture des côtés
Write ( ' Quelle est la longueur du premier cote ? ' );
Readln ( cote1 ) ;
Write ( ' Quelle est la longueur du deuxieme cote ? ' );
Readln ( cote2 ) ;
Write ( ' Quelle est la longueur du troisieme cote ? ' );
Readln ( cote3 ) ;

// Calcul du périmètre et de l'aire


perimetre := cote1 + cote2 + cote3 ;
aire := sqrt ( p e r i m e t r e /2 * ( p e r i m e t r e /2− c o t e 1 ) *
( p e r i m e t r e /2− c o t e 2 ) * ( p e r i m e t r e /2− c o t e 3 ) ) ;

// Achage du périmètre et de l'aire


Writeln ( ' Le perimetre est ' , perimetre : 0 : 3 ) ;
Writeln ( 'L ' ' a i r e est ' , aire :0:3);

Readln ;
end .

162
Exercices élémentaires : séquence Les structure de contrôle

18. Ce programme lit trois chaînes et les affiche en une seule.


program TroisChaines ;
var chaine1 , chaine2 , chaine3 , chaineTotale : string ;
// Les trois chaînes et la chaîne totale
begin
/ / Lecture des trois îchanes
Write ( ' Quelle est la premiere chaine ? ' );
Readln ( chaine1 ) ;
Write ( ' Quelle est la deuxieme chaine ? ' );
Readln ( chaine2 ) ;
Write ( ' Quelle est la troisieme chaine ? ' );
Readln ( chaine3 ) ;

// Calcul de la chaine totale


chaineTotale := chaine1 + chaine2 + chaine3 ;

// Achage de la chaîne totale


Writeln ( ' La chaine est ' , chaineTotale ) ;

Readln ;
end .

19. Calculer le temps écoulé entre deux événements.


Le plus simple est d’obtenir l’heure juste avant (temps1) et juste après (temps2)
l’événement et d’utiliser la formule :

(temps2 − temps1) ∗ 24 ∗ 3600

L’heure courante est donnée par la fonction Time.

163
Les tests Les structure de contrôle

1.2 Les tests


1. Afficher le plus grand et le plus petit de deux nombres.
program GrandPetit ;
var nombre1 , nombre2 : real ; // Les deux nombres
begin
// Lecture des deux nombres
Write ( ' Quel est le premier nombre ? ' );
Readln ( nombre1 ) ;
Write ( ' Quel est le second nombre ? ' );
Readln ( nombre2 ) ;

// Calcul est achage du plus grand et du plus petit


if nombre1 > nombre2 then
begin
Writeln ( ' Le plus grand nombre est ' , nombre1 : 0 : 3 ,
' et le plus petit est ' , nombre2 : 0 : 3 ) ;
end
else
begin
Writeln ( ' Le plus grand nombre est ' , nombre2 : 0 : 3 ,
' et le plus petit est ' , nombre1 : 0 : 3 ) ;
end ;

Readln ;
end .

2. Ce programme calcule la racine carrée d’un nombre si elle existe.


program RacineCarree ;
var nombre , racine : real ; // Le nombre et la racine
begin
//Lecture du nombre
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;

//Calcul et achage de la racine si elle existe


if nombre >= 0 then
begin
racine := sqrt ( nombre ) ;
Writeln ( ' La racine est ' , racine : 0 : 3 ) ;
end
else
begin
Writeln ( ' La racine d ' ' un nombre negatif n ' ' existe pas ! ' );
end ;

readln ;
end .

164
Les tests Les structure de contrôle

3. Résoudre l’équation du second degré ax2 + bx + c = 0


program EquationDuSecondDegre ;
var a,b,c , // Les coecients de l'équation du second degré
2
delta , // Delta = b − 4ac
x1 , x2 : real ; // Les éventuelles racines
begin
// Lecture des coecients de l'équation
Writeln ( ' Resolution de l ' ' equation du second degre ' ) ;
Writeln ;
Write ( ' Quelle est la valeur de a ? ' );
Readln (a );
Write ( ' Quelle est la valeur de b ? ' );
Readln (b ) ;
Write ( ' Quelle est la valeur de c ? ' );
Readln (c );
Writeln ;

// Calcul et achage des racines


delta := b*b − 4* a * c ;

if delta > 0 then


begin
x1 := (− b − sqrt ( delta ))/(2* a ) ;
x2 := (− b+ sqrt ( delta ))/(2* a ) ;
Writeln ( ' Les racines sont ' , x1 : 0 : 3 , ' et ' , x2 : 0 : 3 ) ;
end
else
begin
if delta = 0 then
begin
x1− := b/(2* a ) ;
Writeln ( ' La racine double est ' , x1 : 0 : 3 ) ;
end
else
begin
Writeln ( ' Il n ' 'y a pas de racine ! ' );
end ;
end ;
Readln ;
end .

165
Les tests Les structure de contrôle

4. Calculer le plus grand et le plus petit parmi trois nombres.


program PlusGrandPlusPetit ;
var nombre1 , nombre2 , nombre3 : R e a l ; // Les trois nombres
begin
// Lecture des 3 nombres
Write ( ' Quel est le premier nombre ? ' ); Readln ( nombre1 ) ;
Write ( ' Quel est le deuxieme nombre ? ' ); Readln ( nombre2 ) ;
Write ( ' Quel est le troisieme nombre ? ' ); Readln ( nombre3 ) ;

// Calcul et achage du plus petit


if ( nombre1 <= nombre2 ) and ( nombre1 <= nombre3 ) then
writeln ( nombre1 : 0 : 3 , ' est le plus petit ' )
else
if ( nombre2 <= nombre1 ) and ( nombre2 <= nombre3 ) then
writeln ( nombre2 : 0 : 3 , ' est le plus petit ' )
else
writeln ( nombre2 : 0 : 3 , ' est le plus petit ' );

// Calcul et achage du plus grand


.
.
.

Readln ;
end .

Une autre solution


program PlusGrandPlusPetit ;
var nombre1 , nombre2 , nombre3 : R e a l ; //Les trois nombres
begin
//Lecture des 3 nombres
Write ( ' Quel est le premier nombre ? ' ); Readln ( nombre1 ) ;
Write ( ' Quel est le deuxieme nombre ? ' ); Readln ( nombre2 ) ;
Write ( ' Quel est le troisieme nombre ? ' ); Readln ( nombre3 ) ;

//Calcul et achage du plus petit


if ( nombre1 <= nombre2 ) and ( nombre1 <= nombre3 ) then
writeln ( nombre1 : 0 : 3 , ' est le plus petit ' );
if ( nombre2 <= nombre1 ) and ( nombre2 <= nombre3 ) then
writeln ( nombre2 : 0 : 3 , ' est le plus petit ' )
if ( nombre3 <= nombre1 ) and ( nombre3 <= nombre2 ) then
writeln ( nombre3 : 0 : 3 , ' est le plus petit ' );

// Calcul et achage du plus grand


.
.
.

Readln ;
end .

166
Les tests Les structure de contrôle

5. Calculer le plus grand et le plus petit parmi six nombres.


program PlusGrandPlusPetit ;
var a,b,c ,d,e , f : real ; / / Les 6 nombres
min , max // Le plus petit et le plus grand
: real ;
begin
// Lecture des 6 nombres
Write ( ' Quel est le premier nombre ? ' );
Readln (a );
Write ( ' Quel est le deuxieme nombre ? ' );
Readln (b ) ;
Write ( ' Quel est le troisieme nombre ? ' );
Readln (c );
Write ( ' Quel est le quatrieme nombre ? ' );
Readln (d ) ;
Write ( ' Quel est le cinquieme nombre ? ' );
Readln (e );
Write ( ' Quel est le sixieme nombre ? ' );
Readln ( f );

// Calcul du plus petit


min := a;
if b < min then
min := b;
if c < min then
min := c;
if d < min then
min := d;
if e < min then
min := e;
if f < min then
min := f ;

// Calcul du plus grand


max := a;
if b > max then
max := b;
if c > max then
max := c;
if d > max then
max := d;
if e > max then
max := e;
if f > max then
max := f ;

// Achage du plus petit et du plus grand


Writeln ;
Writeln ( min : 0 : 3 , ' est le plus petit ! ' );
Writeln ( max : 0 : 3 , ' est le plus grand ! ' );

Readln ;
end .

167
Les tests Les structure de contrôle

6. Déterminer si une année est bissextile (une année est bissextile si elle est multiple de 4.
Toutefois les années séculaires ne sont bissextiles que si elles sont multiple de 400).
program AnneeBissextile ;
var annee : i n t e g e r ; //L'année
begin
//Lecture de l'année
Write ( ' Quelle est l ' ' annee ? ' );
Readln ( annee ) ;

//Détermination du caractère de l'année (bissextile ou non)


if anneemod 400 = 0 then
begin
Writeln ( 'L ' ' annee est bissextile ! ' );
end
else
begin
if mod
annee 100 = 0 then
begin
Writeln ( 'L ' ' annee n ' ' est pas bissextile ! ' );
end
else
begin
if mod
annee 4 = 0 then
begin
Writeln ( 'L ' ' annee est bissextile ! ' );
end
else
begin
Writeln ( 'L ' ' annee n ' ' est pas bissextile ! ' );
end ;
end ;
end ;
Readln ;
end .

7. Déterminer si un nombre de trois chiffres est d’Armstrong (un nombre est d’Armstrong
si la somme des cubes de ses trois chiffres est égale au nombre).
program Armstrong ;
var // Le nombre de trois chires
nombre : i n t e g e r ;
// Le chire des unités, des dizaines et des centaines
u,d, c : integer ;
begin
// Lecture du nombre
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;

// Décomposition du nombre en trois chires


u := nombre mod 10;
d := nombre div 10 mod 10;
c := nombre div 100;

168
Les tests Les structure de contrôle

// On regarde si le nombre est d'Armstrong


if * *u u u + d * d * d + c * c * c = nombre then
begin
Writeln ( nombre , ' est un nombre d ' ' Armstrong ! ' );
end
else
begin
Writeln ( nombre , ' n ' ' est pas un nombre d ' ' Armstrong ! ' );
end ;

Readln ;
end .

8. Déterminer si un triangle est rectangle en connaissant ses 3 côtés.


program TriangleRectangle ;
var a,b, c : // Les trois côtés
real ;
begin
// Lecture des trois côtés
Write ( ' Quelle est la longueur du premier cote ? ' );
Readln (a );
Write ( ' Quelle est la longueur du deuxieme cote ? ' );
Readln (b ) ;
Write ( ' Quelle est la longueur du troisieme cote ? ' );
Readln (c );

//On vérie si le triangle est rectangle en vériant Pythagore


if * (a a = b*b + c * c ) or ( b*b = a * a + c * c ) or ( c * c = a * a + b*b ) then
begin
Writeln ( ' Le triangle est rectangle ! ' );
end
else
begin
Writeln ( ' Le triangle n ' ' est pas rectangle ! ' );
end ;

Readln ;
end .

169
Les tests Les structure de contrôle

9. Ce programme calcule le prix à payer si une réduction de 5% est accordée sur la


partie qui dépasse 100 €.
program Reduction100 ;
var montantInitial , reduction : real ; //Le montant initial, la réduction
montantAPayer : real ; // et le trotal à payer
begin
// Lecture du montant initial
Write ( ' Quel est le montant total de vos achats ? ' );
Readln ( montantInitial ) ;

// Calcul du montant à payer


if m o n t a n t I n i t i a l < 100 then
begin
reduction := 0;
end
else
begin
reduction := ( montantInitial − 100) * 5/100;
end ;
montantAPayer := montantInitial − reduction ;

// Achage du montant à payer


Writeln ( ' Vous devez payer ' , montantAPayer : 0 : 2 , ' euro ( s ) ' ) ;

Readln ;
end .

10. Ce programme affiche la position de la droite ax + by + c = 0 par rapport aux axes


program Droite ;
var a,b, c // Les coecients de la droite
: real ;
begin
// Lecture des coecients de la droite
Writeln ( ' Position de la droite ax+by+c=0 ' ) ;
Writeln ;
Write ( ' Quelle est la valeur du coefficient "a" ? ' );
Readln (a );
Write ( ' Quelle est la valeur du coefficient "b" ? ' );
Readln (b ) ;
Write ( ' Quelle est la valeur du coefficient "c" ? ' );
Readln (c );

170
Les tests Les structure de contrôle

// Détermination et achage de la position de la droite par rapport aux axes


if then
a <> 0
begin
if then
b <> 0
begin
Writeln ( ' La droite est oblique ! ' );
end
else
begin
Writeln ( ' La droite est parallele a Oy ! ' );
end ;
end
else
begin // a=0
if then
b <> 0
begin
Writeln ( ' La droite est parallele a Ox ! ' );
end
else // a=0 et b=0
begin
Writeln ( ' Il n ' 'y a pas de droite ! ' );
end ;
end ;

Readln ;
end .

11. Lire un caractère, le programme teste s’il s’agit d’une lettre majuscule, si oui, il
renvoie cette lettre en minuscule, sinon il renvoie un message d’erreur.
program TesteMajuscule ;
var c : char ;
begin
// Lecture du caractère
write ( ' Quel est le caractere ? ' );
readln (c );

// Teste si majuscule
if ( c >= and
'A ' ) ( c <= 'Z ' ) then
begin
cLowerCase
:= (c );
writeln (c );
end
else
writeln ( ' Erreur ' ) ;

readln ;
end .

171
Les tests Les structure de contrôle

12. Lire deux chaînes de caractères et afficher à partir de quelle position commence la
première dans la seconde.
program Cherche ;
var chaine1 , chaine2 : string ; // Les deux chaînes
endroit : integer ; // Endroit où se trouve chaine2 dans chaine1
begin
/ / Lecture des deux chaines
Write ( ' Quelle est la premiere chaine ? ' );
Readln ( chaine1 ) ;
Write ( ' Quelle est la deuxieme chaine ? ' );
Readln ( chaine2 ) ;

// Recherche
endroit := Pos ( chaine2 , chaine1 ) ;

// Achage
if endroit > 0 then
writeln ( chaine2 , ' se trouve en ' , endroit , ' position dans ' , chaine1 )
else
writeln ( chaine2 , ' ne se trouve pas dans ' , chaine1 ) ;
readln ;
end .

13. Lire un caractère et déterminer si ce caractère est une lettre, un chiffre ou un autre
caractère.
program CaractereLettreChiffreAutre ;
const lettres = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ; // Toutes les lettres
chiffres = ' 0123456789 ' ; // Tous les chires
var caractere : char ; // Le caractère lu
begin
//Lecture du caractère
Write ( ' Quel est le caractere ? ' );
Readln ( caractere );

// Détermination du caractère (lettre, chire ou autre)


i f pos upcase
( ( caractere ) , lettres ) > 0 then
begin
Writeln ( ' Le caractere est une lettre ! ' );
end
else
begin
i f pos upcase
( ( caractere ) , chiffres ) > 0 then
begin
Writeln ( ' Le caractere est un chiffre ! ' );
end
else
begin
Writeln ( ' Le caractere n ' ' est ni une lettre , ni un chiffre ! ' );
end ;
end ;

Readln ;
end .

172
Les tests Les structure de contrôle

14. Lire une chaîne et déterminer si elle commence ou se termine par une consonne ou
une voyelle.
program ChaineConsonneVoyelle ;
const // Toutes les consonnes
c o n s o n n e s= 'BCDFGHJKLMNPQRSTVWXZ ' ;
// Toutes les voyelles
v o y e l l e s = 'AEIOUY ' ;
var string //La chaîne
chaine : ;
begin
//Lecture de la chaîne
Write ( ' Quelle est la chaine ? ' );
Readln ( chaine ) ;

//On vérie si le premier caractère est une consonne ou une voyelle


i f pos upcase
( ( chaine [ 1 ] ) , consonnes ) > 0 then
begin
Writeln ( ' Le premier caractere est une consonne ! ' );
end
else
begin
i f pos upcase
( ( chaine [ 1 ] ) , v o y e l l e s ) > 0 then
begin
Writeln ( ' Le premier caractere est une voyelle ! ' );
end
else
begin
Writeln ( 'Le premier caractere nest ni une consonne, ni une voyelle !' ) ;
end ;
end ;

//On vérie si le dernier caractère est une consonne ou une voyelle


i f pos upcase
( ( chaine [ length ( chaine ) ] ) , consonnes ) > 0 then
begin
Writeln ( ' Le dernier caractere est une consonne ! ' );
end
else
begin
i f pos upcase
( ( chaine [ length ( chaine ) ] ) , v o y e l l e s ) > 0 then
begin
Writeln ( ' Le dernier caractere est une voyelle ! ' );
end
else
begin
Writeln ( 'Le dernier caractere nest ni une consonne, ni une voyelle !' ) ;
end ;
end ;

Readln ;
end .

173
Les tests Les structure de contrôle

15. Ce programme lit deux réels et un symbole au clavier et


- additionne les deux réels si le symbole est ”+”
- soustrait le second du premier si le symbole est ”-”
- multiplie les deux réels si le symbole est ”*” ou ”.”
- divise le premier par le second si le symbole est ”/” ou ” :”
- affiche une erreur si le symbole ne vaut aucune de ces valeurs
program Calculatrice ;
var nombre1 , nombre2 : real ; // Les deux nombres
operateur : char ; // L'opérateur
resultat : real ; // Résultat de l'opération
begin
// Lecture des deux nombres et de l'opérateur
Write ( ' Quel est le premier nombre ? ' );
Readln ( nombre1 ) ;
Write ( ' Quel est le deuxieme nombre ? ' );
Readln ( nombre2 ) ;
Write ( ' Quel est l ' ' operateur ? ' );
Readln ( operateur ) ;

// Calcul et achage du résultat


case of
operateur
begin
'+ ' :
r e s u l t a t := nombre1+nombre2 ;
Writeln ( ' La somme est ' , resultat :0:3);
end ;
'− begin
' :
r e s u l t a t := nombre1−nombre2 ;
Writeln ( ' La difference est ' , resultat :0:3);
end ;
'* begin
' , ' . ' :
r e s u l t a t := nombre1 * nombre2 ;
Writeln ( ' Le produit est ' , resultat :0:3);
end ;
begin
'/ ' , ' : ' :
if nombre2<>0 then
begin
r e s u l t a t := nombre1 / nombre2 ;
Writeln ( ' Le quotient est ' , resultat :0:3);
end
else
begin
Writeln ( ' Division par zero ! ' );
end ;
end ;
else // Du Case Of
Writeln ( 'L ' ' operateur n ' ' est pas valide ! ' );
end ;

Readln ;
end .

174
Les tests Les structure de contrôle

16. Ce programme lit deux chaînes de caractères et supprime la seconde de la première


si elle s’y trouve.
program Supprimerchaine ;
var chaine1 , string
chaine2 : ;
begin
// Lecture des deux chaînes
Write ( ' Quelle est la chaine ? ' );
Readln ( chaine1 ) ;
Write ( ' Quelle est la partie a supprimer ? ' );
Readln ( chaine2 ) ;

// Vérication de la présence de la seconde chaine dans la première et suppression


i f pos ( chaine2 , chaine1 ) > 0 then
begin
delete ( chaine1 , pos ( chaine2 , chaine1 ) , length ( c h a i n e 2 ) ) ; //Suppression
Writeln ( ' La chaine devient ' , chaine1 ) ;
end
else
begin
Writeln ( ' La seconde chaine n ' ' est pas dans la premiere ! ' );
end ;

Readln ;
end .

17. Lire le nom d’un fichier (une chaîne). Le programme vérifie que celui-ci possède
l’extension « PAS ».
program Exercice15 ;
var fichier , extension : string ;
position : integer ;
begin
write ( ' Quel est le nom du fichier ? ' );
readln ( fichier );

position := pos ( ' . ' , fichier );


extension := copy ( fichier , position + 1 , length ( f i c h i e r )− p o s i t i o n ) ;

if position = 0 then
writeln ( ' Ce n ' ' e s t pas un nom valable . ' )
else
begin
if extension = ' pas ' then
writeln ( 'C ' ' e s t un fichier PAS . ' )
else
writeln ( 'C ' ' e s t un fichier ' , extension ) ;
end ;

readln ;
end .

175
Les tests Les structure de contrôle

18. Lire une expression sous forme de chaîne et l’évaluer.


Simplification On suppose qu’on évalue une expression simple, c’est-à-dire deux
opérandes entières et un opérateur.
program EvalSimple ;
uses sysUtils ; // pour Trim
var expression : String ;
strOperande1 , strOperande2 : string ; // Opérandes sous forme de chaîne
operande1 , operande2 : integer ; // Opérandes
code : integer ; // Pour Val
ouEstPlus , ouEstMoins , ouEstFois , ouEstDivise ,
ouEstDiv , ouEstMod : integer ; // position de l'opérateur
begin
// Lecture de l'expression
write ( ' Quelle est l ' ' expression ? ' );
readln ( expression );

// Recherche la position de l'opérateur


ouEstPlus := Pos ( '+ ' , e x p r e s s i o n ) ;
ouEstMoins := Pos ( '− ' , e x p r e s s i o n ) ;
ouEstFois := Pos ( '* ' , expression );
ouEstDivise := Pos ( '/ ' , expression );
ouEstDiv := Pos ( ' div ' , expression ) ;
ouEstMod := Pos ( ' mod ' , e x p r e s s i o n ) ;

// Calculer
if ouEstPlus > 0 then
begin
strOperande1 := Copy ( e x p r e s s i o n , 1 , ouEstPlus −1);
strOperande2 :=
Copy ( e x p r e s s i o n , o u E s t P l u s +1 , Length ( e x p r e s s i o n )− o u E s t P l u s ) ;
strOperande1 := Trim ( s t r O p e r a n d e 1 ) ;
strOperande2 := Trim ( s t r O p e r a n d e 2 ) ;
Val ( strOperande1 , operande1 , code ) ;
Val ( strOperande2 , operande2 , code ) ;
writeln ( operande1 , ' + ' , operande2 , ' = ' , operande1 + operande2 ) ;
end
else
if ouEstMoins > 0 then
begin
strOperande1 := Copy ( e x p r e s s i o n , 1 , ouEstMoins −1);
strOperande2 :=
Copy ( e x p r e s s i o n , o u E s t M o i n s +1 , Length ( e x p r e s s i o n )− o u E s t M o i n s ) ;
strOperande1 := Trim ( s t r O p e r a n d e 1 ) ;
strOperande2 := Trim ( s t r O p e r a n d e 2 ) ;
Val ( strOperande1 , operande1 , code ) ;
Val ( strOperande2 , operande2 , code ) ;
writeln ( operande1 , ' − ' , operande2 , ' = ' , operande1 − operande2 ) ;
end

176
Les tests Les structure de contrôle

else
if ouEstFois > 0 then
begin
strOperande1 := Copy ( e x p r e s s i o n , 1 , ouEstFois −1);
strOperande2 :=
Copy ( e x p r e s s i o n , o u E s t F o i s +1 , Length ( e x p r e s s i o n )− o u E s t F o i s ) ;
strOperande1 := Trim ( s t r O p e r a n d e 1 ) ;
strOperande2 := Trim ( s t r O p e r a n d e 2 ) ;
Val ( strOperande1 , operande1 , code ) ;
Val ( strOperande2 , operande2 , code ) ;
writeln ( operande1 , ' * ' , operande2 , ' = ' , operande1 * operande2 ) ;
end
else
if ouEstDivise > 0 then
begin
strOperande1 := Copy ( expression , 1 , ouEstDivise −1);
strOperande2 :=
Copy ( e x p r e s s i o n , o u E s t D i v i s e +1 , Length ( e x p r e s s i o n )− o u E s t D i v i s e ) ;
strOperande1 := Trim ( s t r O p e r a n d e 1 ) ;
strOperande2 := Trim ( s t r O p e r a n d e 2 ) ;
Val ( strOperande1 , operande1 , code ) ;
Val ( strOperande2 , operande2 , code ) ;
writeln ( operande1 , ' / ' , operande2 , ' = ' , ( operande1 / operande2 ) : 0 : 2 ) ;
end
else
if ouEstDiv > 0 then
begin
strOperande1 := Copy ( e x p r e s s i o n , 1 , ouEstDiv −1);
strOperande2 :=
Copy ( e x p r e s s i o n , o u E s t D i v +4 , Length ( e x p r e s s i o n )− o u E s t D i v −3);
strOperande1 := Trim ( s t r O p e r a n d e 1 ) ;
strOperande2 := Trim ( s t r O p e r a n d e 2 ) ;
Val ( strOperande1 , operande1 , code ) ;
Val ( strOperande2 , operande2 , code ) ;
writeln ( operande1 , ' div ' , operande2 , ' = ' , operande1 div operande2 ) ;
end
else
if ouEstMod > 0 then
begin
strOperande1 := Copy ( e x p r e s s i o n , 1 , ouEstMod − 1 ) ;
strOperande2 :=
Copy ( e x p r e s s i o n , ouEstMod +4 , Length ( e x p r e s s i o n )− ouEstMod − 3 ) ;
strOperande1 := Trim ( s t r O p e r a n d e 1 ) ;
strOperande2 := Trim ( s t r O p e r a n d e 2 ) ;
Val ( strOperande1 , operande1 , code ) ;
Val ( strOperande2 , operande2 , code ) ;
writeln ( operande1 , ' mod ' , operande2 , ' = ' , operande1 mod operande2 ) ;
end
else
writeln ( 'éOprateur manquant ! ' ) ;

readln ;
end .

177
Les boucles Les structure de contrôle

1.3 Les boucles


Passage d’une boucle à l’autre

I ←− 1
tant que I ≤ N faire
instruction(s)
I ←− I + 1
fin

I ←− 1
répéter
instruction(s)
I ←− I + 1
jusqu’à I > N

pour I ← 1 à N faire
instruction(s)
fin

178
Les boucles Les structure de contrôle

1. Calculer la somme et le produits des n premiers entiers.


(a) Somme
program SommeNPremiersEntiers ;
var n, // Le nombre d'entiers
nombre , // Le nombre ajouté
somme : integer ; // La somme
begin
//Lecture du nombre d'entiers
Write ( ' Combien d ' ' e n t i e r s v o u l e z −v o u s dans la somme ? ' );
Readln (n ) ;

//Calcul de la somme avec WHILE DO


somme := 0; // Au départ, la somme vaut 0
nombre := 1; // Le premier terme de la somme est 1
while nombre <= n do // Le dernier terme est n
begin
somme := somme + nombre ; // On ajoute le nombre à la somme
nombre := nombre + 1 ; // On passe au nombre suivant
end ;

// Achage de la somme
Writeln ( ' Avec la b o u c l e WHILE, la somme est ' , somme ) ;

// Calcul de la somme avec REPEAT UNTIL


somme := 0; // Au départ, la somme vaut 0
nombre := 1; // Le premier terme de la somme est 1
repeat
somme := somme + nombre ; // On ajoute le nombre à la somme
nombre := nombre + 1 ; // On passe au nombre suivant
until nombre > n ; // Le dernier terme est n

//Achage de la somme
Writeln ( ' Avec la b o u c l e REPEAT, la somme est ' , somme ) ;

//Calcul de la somme avec FOR TO


somme := 0; // Au départ, la somme vaut 0
for nombre := 1 to n do //Le premier terme est 1 et le dernier est n
begin
somme := somme + nombre ; //On ajoute le nombre à la somme
end ; //nombre est incrémenté automatiquement

//Achage de la somme
Writeln ( ' Avec la b o u c l e FOR, la somme est ' , somme ) ;

Readln ;
end .

179
Les boucles Les structure de contrôle

(b) Produit
program factorielle ;
var n, // Le nombre d'entiers
nombre , // Le nombre à multiplier
produit : integer ; // Le produit
begin
// Lecture du nombre d'entiers
Write ( ' Combien d ' ' e n t i e r s v o u l e z −v o u s dans le produit ? ' );
Readln (n ) ;

// Calcul du produit avec WHILE DO


produit := 1; // Au départ, le produit vaut 1
nombre := 1; // Le premier facteur est 1
while nombre <= n do // Le dernier facteur est n
begin
produit := produit * nombre ; // On multiplie le produit par le nombre
nombre := nombre + 1 ; // On passe au nombre suivant
end ;
// Achage du produit
Writeln ( ' Avec la b o u c l e WHILE, le produit est ' , produit ) ;

//Calcul de la somme avec REPEAT UNTIL


produit := 1; //Au départ, le produit vaut 1
nombre := 1; //Le premier facteur est 1
repeat
produit := produit * nombre ; // On multiplie le produit par le nombre
nombre := nombre + 1 ; // On passe au nombre suivant
until nombre > n ; // Le dernier terme est n
// Achage du produit
Writeln ( ' Avec la b o u c l e REPEAT, le produit est ' , produit ) ;

// Calcul de la somme avec FOR TO


produit := 1; //Au départ, le produit vaut 1
for nombreto do //Le premier facteur est 1 et le dernier est n
:= 1 n
begin
* //On multiplie le produit par le nombre
p r o d u i t := p r o d u i t nombre ;
end //nombre est incrémenté automatiquement
;
// Achage du produit
Writeln ( ' Avec la b o u c l e FOR, le produit est ' , produit ) ;

Readln ;
end .

180
Les boucles Les structure de contrôle

2. Lire 10 entiers, en afficher le nombre de valeurs négatives


program CombienNegatif ;
var nombre : integer ; // le nombre lu au clavier
compteur : integer ; // pour compter 10 nombres
compteurNegatif : integer ; // le nombre de nombre négatifs
begin
// Avec la boucle WHILE
compteurNegatif := 0;
compteur := 1;
while c o m p t e u r <= 10 do
begin
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;
if nombre < 0 then
compteurNegatif := compteurNegatif + 1 ;
c o m p t e u r += 1 ;
end ;
// Achage
Writeln ( ' Avec WHILE, le nombre de negatifs est ' , compteurNegatif ) ;

// Avec la boucle REPEAT


compteurNegatif := 0;
compteur := 1;
repeat
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;
if nombre < 0 then
compteurNegatif := compteurNegatif + 1 ;
c o m p t e u r += 1 ;
until compteur > 10;
// Achage
Writeln ( ' Avec REPEAT, le nombre de negatifs est ' , compteurNegatif ) ;

// Avec la boucle FOR


compteurNegatif := 0;
for compteur := 1 to 10 do
begin
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;
if nombre < 0 then
compteurNegatif := compteurNegatif + 1 ;
end ;
// Achage
Writeln ( ' Avec FOR, le nombre de negatifs est ' , compteurNegatif ) ;

Readln ;
end .

181
Les boucles Les structure de contrôle

3. Calculer le produit de réels lus au clavier. On arrête dès qu’on a lu le réel 0.


program ProduitNombres ;
var nombre , p r o d u i t : real ; // Le nombre lu au clavier et le produit
begin
/ / Avec la boucle WHILE
produit := 1; //Le produit est 1 car c'est le neutre pour la multiplication
// Lecture du premier nombre
Write ( ' Quel est le premier nombre ? ' );
Readln ( nombre ) ;
// Calcul du produit et lecture des autres nombres
while do
nombre <> 0
begin
produit := *
produit nombre ;
Write ( ' Quel est le nombre suivant ? ' );
Readln ( nombre ) ;
end ;
// Achage du produit
Writeln ( ' Avec WHILE, le produit est ' , produit : 0 : 3 ) ;

// Avec la boucle REPEAT


produit := 1; // Le produit est 1 car c'est le neutre pour la multiplication
repeat
Write ( ' Quel est le nombre a multiplier ? ' );
Readln ( nombre ) ;
// On multiplie le nombre au produit si le nombre est diérent de 0
if then
nombre <> 0
begin
produit *
:= produit nombre ;
end ;
until nombre = 0 ;
// Achage du produit
Writeln ( ' Avec REPEAT, le produit est ' , produit : 0 : 3 ) ;

// Il est impossible de faire cet exercice avec la boucle FOR car on ne connaît
// pas le nombre d'itérations de la boucle
Readln ;
end .

182
Les boucles Les structure de contrôle

4. Calculer la somme des n premiers nombres pairs.


program SommeNPremiersPairs ;
var n, // Le nombre d'entiers
nombre , // Le nombre ajouté
somme : integer ; // La somme
begin
// Lecture du nombre d'entiers
Write ( ' Combien d ' ' e n t i e r s v o u l e z −v o u s dans la somme ? ' );
Readln (n ) ;

// Calcul de la somme avec WHILE DO


somme := 0; // Au départ, la somme vaut 0
nombre := 1; // On commence par le premier terme
while nombre <= n do // Le dernier terme est le ennième
begin
somme := somme + nombre * 2 ; // On ajoute le nombree nombre pair à la somme
nombre := nombre + 1 ; // On passe au terme suivant
end ;
//Achage de la somme
Writeln ( ' Avec la b o u c l e WHILE, la somme est ' , somme ) ;

//Calcul de la somme avec REPEAT UNTIL


somme := 0; // Au départ, la somme vaut 0
nombre := 1; // On commence par le premier terme
repeat
somme := somme + nombre * 2 ; //On ajoute le nombree nombre pair à la somme
nombre := nombre + 1 ; //On passe au terme suivant
until //Le dernier terme est le ne
nombre > n ;
//Achage de la somme
Writeln ( ' Avec la b o u c l e REPEAT, la somme est ' , somme ) ;

//Calcul de la somme avec FOR TO


somme := 0; //Au départ, la somme vaut 0
for nombreto do // Il y a n termes dans le somme
:= 1 n
begin
*
somme := somme + nombre // On ajoute le nombree nombre pair à la somme
2;
end // nombre est incrémenté automatiquement
;
//Achage de la somme
Writeln ( ' Avec la b o u c l e FOR, la somme est ' , somme ) ;

Readln ;
end .

183
Les boucles Les structure de contrôle

5. Ce programme calcule la somme des n premiers nombres impairs.


program SommeNPremiersImpairs ;
var n, // Le nombre d'entiers
nombre , // Le nombre ajouté
somme : i n t e g e r ; // La somme
begin
// Lecture du nombre d'entiers
Write ( ' Combien d ' ' e n t i e r s v o u l e z −v o u s dans la somme ? ' );
Readln (n ) ;

// Calcul de la somme avec WHILE DO


somme := 0; //Au départ, la somme vaut 0
nombre := 1; //On commence par le premier terme
while nombre <= n do // Le dernier terme est le ennième
begin
somme := somme + nombre * 2 − 1; // On ajoute le nombree nombre impair à la somme
nombre := nombre + 1 ; // On passe au terme suivant
end ;
// Achage de la somme
Writeln ( ' Avec la b o u c l e WHILE, la somme est ' , somme ) ;

// Calcul de la somme avec REPEAT UNTIL


somme := 0; // Au départ, la somme vaut 0
nombre := 1; // On commence par le premier terme
repeat
somme := somme + nombre * 2 − 1; // On ajoute le nombree nombre impair à la somme
nombre := nombre + 1 ; //On passe au terme suivant
until //Le dernier terme est le ennième
nombre>n ;
// Achage de la somme
Writeln ( ' Avec la b o u c l e REPEAT, la somme est ' , somme ) ;

// Calcul de la somme avec FOR TO


somme : = 0 ; // Au départ, la somme vaut 0
for nombreto do // Il y a n termes dans la somme
:= 1 n
begin
* −
somme := somme + nombre // On ajoute le nombre
2 1; e nombre impair à la somme
end //nombre est incrémenté automatiquement
;
//Achage de la somme
Writeln ( ' Avec la b o u c l e FOR, la somme est ' , somme ) ;

Readln ;
end .

184
Les boucles Les structure de contrôle

6. Afficher tous les diviseurs d’un nombre (entier).


program DiviseursNombre ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
begin
// Lecture du nombre
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;

// Avec la boucle WHILE


Writeln ;
Writeln ( ' Avec la b o u c l e WHILE ' ) ;
//Achage des diviseurs
diviseur := 1; // Le premier diviseur est 1
// On essaie tous les diviseurs entre 1 et le nombre
while do
d i v i s e u r <= nombre
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
Writeln ( diviseur , ' est un diviseur de ' , nombre ) ;
end ;
diviseur := // On passe au diviseur suivant
diviseur + 1;
end ;

//Avec la boucle REPEAT


Writeln ;
Writeln ( ' Avec la b o u c l e REPEAT ' ) ;
// Achage des diviseurs
diviseur := 1; // Le premier diviseur est 1
//On essaie tous les diviseurs entre 1 et le nombre
repeat
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
Writeln ( diviseur , ' est un diviseur de ' , nombre ) ;
end ;
diviseur := //On passe au diviseur suivant
diviseur + 1;
until d i v i s e u r > nombre ;

//Avec la boucle FOR


Writeln ;
Writeln ( ' Avec la b o u c l e FOR ' ) ;
// Achage des diviseurs
for diviseur to:= 1 do nombre
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
Writeln ( diviseur , ' est un diviseur de ' , nombre ) ;
end ;
end ;

Readln ;
end .

185
Les boucles Les structure de contrôle

7. Compter le nombre de diviseurs d’un nombre.


program DiviseursNombre ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
compteur : integer ; // Le nombre de diviseurs
begin
//Lecture du nombre
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;

//Avec la boucle WHILE


Writeln ;
Writeln ( ' Avec la b o u c l e WHILE ' ) ;
// Comptage des diviseurs
compteur := 0; // On n'a pas encore trouvé de diviseurs
diviseur := 1; // Le premier diviseur est 1
// On essaie tous les diviseurs entre 1 et le nombre
while d i v i s e u r <= nombredo
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if nombremod then // Le reste de la division doit être 0
diviseur = 0
begin
c o m p t e u r := c o m p t e u r +1;
end ;
diviseur := // On passe au diviseur suivant
diviseur + 1;
end ;
//Achage du nombre de diviseurs
Writeln ( nombre , ' a ' , compteur , ' diviseurs ' );

// Avec la boucle REPEAT


Writeln ;
Writeln ( ' Avec la b o u c l e REPEAT ' ) ;
//Comptage des diviseurs
compteur := 0; // On n'a pas encore trouvé de diviseurs
diviseur := 1; // Le premier diviseur est 1
//On essaie tous les diviseurs entre 1 et le nombre
repeat
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
c o m p t e u r := c o m p t e u r +1;
end ;
diviseur := // On passe au diviseur suivant
diviseur + 1;
until d i v i s e u r >nombre ;
//Achage du nombre de diviseurs
Writeln ( nombre , ' a ' , compteur , ' diviseurs ' );

186
Les boucles Les structure de contrôle

// Avec la boucle FOR


Writeln ;
Writeln ( ' Avec la b o u c l e FOR ' ) ;
// Comptage des diviseurs
compteur := 0; // On n'a pas encore trouvé de diviseurs
for diviseur to do
:= 1 nombre
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
compteur := compteur + 1 ;
end ;
end ;
// Achage du nombre de diviseurs
Writeln ( nombre , ' a ' , compteur , ' diviseurs ' );

Readln ;
end .

8. Calculer le plus grand et le plus petit parmi n nombres réels.


program PlusGrandPlusPetit ;
var n, // Le nombre de nombres
compteur : integer ; //Le nombre de nombres déjà entrés
nombre , // Le nombre entré
min , max : real ; // Le plus petit et le plus grand
begin
//Lecture du nombre de nombres
Write ( ' Combien de nombres allez −v o u s entrer ? ' );
Readln (n ) ;
Writeln ;

//Avec la boucle WHILE


Write ( ' Quel est le premier nombre ? ' );
Readln ( nombre ) ;
min := nombre ; // Le plus petit est provisoirement le seul entré
max := nombre ; // Le plus grand est provisoirement le seul entré
compteur := 1; // On a entré un seul nombre
// Le programme lit les nombres suivants et cherche le minimum et le maximum
while do
compteur < n
begin
// Lecture du nombre suivant
Write ( ' Quel est le nombre suivant ? ' );
Readln ( nombre ) ;
// On vérie si c'est le nombre entré qui est le plus petit
if then
nombre < min
begin
min := nombre ;
end ;
// On vérie si c'est le nombre entré qui est le plus grand
if then
nombre > max
begin
max := nombre ;
end ;
compteur :=//On a encodé un nombre de plus
compteur + 1 ;
end ;

187
Les boucles Les structure de contrôle

// Achage du minimum et du maximum


Writeln ;
Writeln ( ' Avec la b o u c l e WHILE ' ) ;
Writeln ( ' Le plus petit est ' , min : 0 : 3 ) ;
Writeln ( ' Le plus grand est ' , max : 0 : 3 ) ;
Writeln ;

// Avec la boucle REPEAT


min := 1 . 0 E+ 3 0 0 ; // Le plus petit est provisoirement un nombre très grand
max := − 1.0E+ 3 0 0 ; // Le plus grand est provisoirement un nombre très petit
compteur := 0; //On n'a encore rien entré

// On encode les nombres suivants et on cherche le minimum et le maximum


repeat
// Lecture du nombre suivant
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;
// On vérie si c'est le nombre entré qui est le plus petit
if then
nombre < min
begin
min := nombre ;
end ;
// On vérie si c'est le nombre entré qui est le plus grand
if then
nombre > max
begin
max:= nombre ;
end ;
compteur := // On a encodé un nombre de plus
compteur + 1 ;
until compteur = n ;
//Achage du minimum et du maximum
Writeln ;
Writeln ( ' Avec la b o u c l e REPEAT ' ) ;
Writeln ( ' Le plus petit est ' , min : 0 : 3 ) ;
Writeln ( ' Le plus grand est ' , max : 0 : 3 ) ;
Writeln ;

//Avec la boucle FOR


min := 1 . 0 E+ 3 0 0 ; // Le plus petit est provisoirement un nombre très grand
max := − 1.0E+ 3 0 0 ; // Le plus grand est provisoirement un nombre très petit
//On encode les nombres suivants et on cherche le minimum et le maximum
for compteur to do := 1 n
begin
// Lecture du nombre suivant
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;
// On vérie si c'est le nombre entré qui est le plus petit
if then
nombre < min
begin
min := nombre ;
end ;
// On vérie si c'est le nombre entré qui est le plus grand
if then
nombre > max
begin
max := nombre ;
end ;
end ;

188
Les boucles Les structure de contrôle

//Achage du minimum et du maximum


Writeln ;
Writeln ( ' Avec la b o u c l e FOR ' ) ;
Writeln ( ' Le plus petit est ' , min : 0 : 3 ) ;
Writeln ( ' Le plus grand est ' , max : 0 : 3 ) ;
Writeln ;

Readln ;
end .

9. Calculer le plus grand et le plus petit des nombres entrés. On arrête si le nombre
entré est 0.
program PlusGrandPlusPetit ;
var // Le nombre entré
nombre ,
min , max // Le plus petit et le plus grand
: real ;
begin
//Avec la boucle WHILE
Write ( ' Quel est le premier nombre ? ' );
Readln ( nombre ) ;

min := nombre ; // Le plus petit est provisoirement le seul entré


max := nombre ; // Le plus grand est provisoirement le seul entré

// On encode les nombres suivants et on cherche le minimum et le maximum


while do
nombre <> 0
begin
// Lecture du nombre suivant
Write ( ' Quel est le nombre suivant ? ' );
Readln ( nombre ) ;
// On vérie si c'est le nombre entré (non nul) qui est le plus petit
if then
nombre <> 0
begin
if then
nombre < min
begin
min := nombre ;
end ;
//On vérie si c'est le nombre entré (non nul) qui est le plus grand
if then
nombre > max
begin
max := nombre ;
end ;
end ;
end ;
//Achage du minimum et du maximum
Writeln ;
Writeln ( ' Avec la b o u c l e WHILE ' ) ;
Writeln ( ' Le plus petit est ' , min : 0 : 3 ) ;
Writeln ( ' Le plus grand est ' , max : 0 : 3 ) ;
Writeln ;

189
Les boucles Les structure de contrôle

// Avec la boucle REPEAT


min := 1 . 0 E+ 3 0 0 ; // Le plus petit est provisoirement un nombre très grand
max := − 1.0E+ 3 0 0 ; // Le plus grand est provisoirement un nombre très petit
// On encode les nombres suivants et on cherche le minimum et le maximum
repeat
// Lecture du nombre suivant
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;
// On vérie si c'est le nombre entré (non nul) qui est le plus petit
if nombre <> 0then
begin
if then
nombre < min
begin
min := nombre ;
end ;
//On vérie si c'est le nombre entré (non nul) qui est le plus grand
if then
nombre > max
begin
max := nombre ;
end ;
end ;
until nombre = 0 ;
//Achage du minimum et du maximum
Writeln ;
Writeln ( ' Avec la b o u c l e REPEAT ' ) ;
Writeln ( ' Le plus petit est ' , min : 0 : 3 ) ;
Writeln ( ' Le plus grand est ' , max : 0 : 3 ) ;
Writeln ;

// Il est impossible d'utiliser la boucle FOR car on ne connaît pas le nombre d'itérations
Readln ;
end .

10. Afficher le nombre de diviseurs de tous les entiers de 10 à 100.


program DiviseursNombre ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
compteur : integer ; // Le nombre de divisuers
begin
// Avec la boucle WHILE
Writeln ( ' Avec la b o u c l e WHILE ' ) ;
// Comptage des diviseurs
nombre := 10; // On commence avec le nombre 10
while nombre <= 1 0 0 do // Le dernier nombre est 100
begin
compteur := 0; // On n'a pas encore trouvé de diviseurs
diviseur := 1; // Le premier diviseur est 1

190
Les boucles Les structure de contrôle

// On essaie tous les diviseurs entre 1 et le nombre


while do
d i v i s e u r <= nombre
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
compteur := c o m p t e u r +1;
end ;
diviseur := // On passe au diviseur suivant
d i v i s e u r +1;
end ;
// Achage du nombre de diviseurs
Writeln ( nombre : 3 , ' a ' , compteur : 2 , ' diviseurs ' );
nombre := nombre +1; // On passe au nombre suivant
end ;

// Avec la boucle REPEAT


Writeln ( ' Avec la b o u c l e REPEAT ' ) ;
nombre := 10; // On commence avec le nombre 10
repeat
// Comptage des diviseurs
compteur := 0; // On n'a pas encore trouvé de diviseurs
diviseur := 1; // Le premier diviseur est 1
// On essaie tous les diviseurs entre 1 et le nombre
repeat
// On vérie si le diviseur testé est bien un diviseur du nombre
if modnombre then // Le reste de la division doit être 0
diviseur = 0
begin
compteur := compteur + 1 ;
end ;
diviseur := // On passe au diviseur suivant
diviseur + 1;
until d i v i s e u r > nombre ;
//Achage du nombre de diviseurs
Writeln ( nombre : 3 , ' a ' , compteur : 2 , ' diviseurs ' );
nombre := // On passe au nombre suivant
nombre +1;
until nombre > 1 0 0 ;

// Avec la boucle FOR


Writeln ( ' Avec la b o u c l e FOR ' ) ;
for nombre := 10 to 100 do
begin
// Comptage des diviseurs
compteur := 0; // On n'a pas encore trouvé de diviseurs
for diviseur to := do
1 nombre
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
compteur := compteur + 1 ;
end ;
end ;
//Achage du nombre de diviseurs
Writeln ( nombre : 3 , ' a ' , compteur : 2 , ' diviseurs ' );
end ;

Readln ;
end .

191
Les boucles Les structure de contrôle

11. Afficher le nombre de diviseurs de tous les entiers de 10 à 100. Il affiche aussi celui
qui a le plus de diviseurs.

Remarque : Quand on connaît le nombre d’étapes à exécuter, la boucle FOR


est souvent la plus simple à utiliser. Ainsi, les exercices qui suivent utili-
seront cette boucle quand cela sera possible. Transformer la boucle FOR
en utilisant une boucle WHILE ou REPEAT est laissé à titre d’exercices.

program DiviseursNombre ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
compteur : integer ; // Le nombre de diviseurs
nombreMax , max : integer ; // Le nombre qui a le plus de diviseurs et son nombre de diviseurs
begin
max := 0;
for nombre := 10 to 100 do
begin
// Comptage des diviseurs
compteur := 0; // On n'a pas encore trouvé de diviseurs
for diviseur to := do
1 nombre
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
compteur := compteur + 1 ;
end ;
end ;

// Achage du nombre de diviseurs


Writeln ( nombre : 3 , ' a ' , compteur : 2 , ' diviseurs ' );
// On vérie si le nombre contient le plus de diviseurs
if c o m p t e u r > max then
begin
max := compteur ;
nombreMax := nombre ;
end ;
end ;

// Achage du niombre qui a le plus de diviseurs


Writeln ( 'C ' ' e s t ' , nombreMax ,
' qui a le plus de diviseurs , il en a ' , max ) ;

Readln ;
end .

192
Les boucles Les structure de contrôle

12. Déterminer si un nombre est premier.


program NombrePremier ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
compteur : integer ; // Le nombre de diviseurs
begin
/ / Lecture du nombre
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;

// Comptage des diviseurs


compteur := 0; // On n'a pas encore trouvé de diviseurs
for diviseur to:= 1 do nombre
begin
// On vérie si le diviseur testé est bien un diviseur du nombre
if mod
nombre then // Le reste de la division doit être 0
diviseur = 0
begin
compteur := c o m p t e u r +1;
end ;
end ;

//Achage du résultat
if compteur = 2 then
begin
Writeln ( nombre , ' est un nombre premier ' ) ;
end
else
begin
Writeln ( nombre , ' n ' ' est pas un nombre premier ' ) ;
end ;

Readln ;
end .

⇐⇒
program NombrePremier ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
compteur : integer ; //Le nombre de diviseurs
begin
/ / Lecture du nombre
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;

// Comptage des diviseurs


compteur := 0; // On n'a pas encore trouvé de diviseurs
for diviseur := 1 to nombre do
if nombre mod diviseur = 0 then // Le reste de la division doit être 0
compteur := c o m p t e u r +1;

//Achage du résultat
if compteur = 2 then
Writeln ( nombre , ' est un nombre premier ' )
else
Writeln ( nombre , ' n ' ' est pas un nombre premier ' ) ;
Readln ;
end .

193
Les boucles Les structure de contrôle

13. Déterminer si un nombre est parfait (il est égal à la somme de ses diviseurs excepté
lui-même).
program NombreParfait ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
somme : integer ; // La somme des diviseurs
begin
// Lecture du nombre
Write ( ' Quel est le nombre ? ' );
Readln ( nombre ) ;

//Comptage des diviseurs


somme := 0; // On n'a pas encore trouvé de diviseurs
for diviseur := 1 to nombre −1 do
//On vérie si le diviseur testé est bien un diviseur du nombre
if nombre mod diviseur = 0 then // Le reste de la division doit être 0
somme := somme + d i v i s e u r ; // On ajoute le diviseur à la somme

// Achage du résultat
if somme = nombre then
Writeln ( nombre , ' est un nombre parfait ' )
else
Writeln ( nombre , ' n ' ' est pas un nombre parfait ' );

Readln ;
end .

14. Calculer an (n entier positif)


program aExposantN ;
var a : real ; // La base de la puissance
n : integer ; // L'exposant de la puissance
puissance : real ; // La puissance a exposant n
compteur : integer ; / / Le nombre de fois que la base àéé t émultiplie
begin
// Lecture de la base et de l'exposant
Write ( ' Quelle est la base ? ' );
Readln (a );
Write ( ' Quel est l ' ' exposant ? ' );
Readln (n ) ;

// Calcul de la puissance
puissance := 1; //Le neutre pour le produit
//On multiplie n fois puissance par a
for compteur := 1 to n do
puissance := puissance * a;

//Achage du résultat
Writeln ;
Writeln ( ' La puissance est ' , puissance : 0 : 3 ) ;

Readln ;
end .

194
Les boucles Les structure de contrôle

15. Calculer an (n entier quelconque).


Rappels :
1
an = et a0 = 1 pour a 6= 0
a−n
program aExposantN ;
var a : real ; // La base de la puissance
n : integer ; // L'exposant de la puissance
puissance : real ; // La puissance a exposant n
compteur : integer ; // Le nombre de fois que la base à été multipliée
begin
// Lecture de la base et de l'exposant
Write ( ' Quelle est la base ? ' );
Readln (a );
Write ( ' Quel est l ' ' exposant ? ' );
Readln (n ) ;

if then
n = 0
if then a = 0
Writeln ( ' Indetermination ' )
else
Writeln ( ' La puissance est 1')
else
begin
// Calcul de la puissance
puissance := 1; // Le neutre pour le produit
// On multiplie abs(n) fois puissance par a (abs est la valeur absolue.)
for compteur := 1 to abs (n) do
puissance := puissance * a;

// Si l'exposant est négatif, on prends l'inverse


if n < 0 then
puissance : = 1/ p u i s s a n c e ;

// Achage du résultat
Writeln ;
Writeln ( ' La puissance est ' , puissance : 0 : 3 ) ;
end ;

Readln ;
end .

195
Les boucles Les structure de contrôle

16. Calculer la probabilité d’obtenir un 6 avec un dé.


program Probabilite6 ;
var lance , // Résultat d'un lancé de dé
compteur , // Compteur de lancés de dé
nombre6 : integer ; // Nombre de 6 obtenus
probabilite : real ; // Inverse de la probabilité d'obtenir 6
begin
randomize ; // Initiation du générateur aléatoire

// On simule 1 000 000 de lancés


nombre6 := 0; // On n'a pas encore obtenu de 6
for compteur := 1 to 1000000 do
begin
lance := 1 + random (6); // On lance un dé
if lance = 6 then
nombre6 := nombre6 + 1 ; // On compte le 6 obtenu
end ;

// Calcul de l'inverse de la probabilité


probabilite := 1000000 / nombre6 ;

// Achage de la probabilité
Writeln ( ' On a 1 chance sur ' , probabilite :0:2 , ' d ' ' obtenir 6 ' );
Writeln ;

Readln ;
end .

17. Afficher tous les nombres d’Armstrong. (Un nombre est d’Armstrong si la somme des
cubes de ses trois chiffres est égale au nombre).
program Armstrong ;
var nombre : integer ; // Le nombre de trois chires
u,d, c : integer ; // Le chire des unités, des dizaines et des centaines
begin
for nombre := 100 to 999 do // 100 est le premier et 999 est le dernier nombre de 3 chires
begin
// Décomposition du nombre en trois chires
u := nombre mod 10;
d := nombre div 10 mod 10;
c := nombre div 100;

// On regarde si le nombre est d'Armstrong


if u * u * u + d * d * d + c * c * c = nombre then
Writeln ( nombre , ' est un nombre d ' ' Armstrong ! ' );
end ;

Readln ;
end .

196
Les boucles Les structure de contrôle

18. Ce programme affiche tous les nombres premiers entre 2 et 1000.


program NombrePremier ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
compteur : integer ; // Le nombre de diviseurs
begin
for nombre := 2 to 1000 do
begin
// Comptage des diviseurs
compteur : = 0 ; //On n'a pas encore trouvé de diviseurs
for diviseur := 1 to nombre do
// On vérie si le diviseur testé est bien un diviseur du nombre
if nombre mod diviseur = 0 then // Le reste de la division doit être 0
compteur := compteur + 1 ;

// Achage du résultat
if compteur = 2 then
Writeln ( nombre , ' est un nombre premier ' ) ;
end ;

Readln ;
end .

19. Afficher tous les nombres parfaits de 1 à 10000.


program NombreParfait ;
var nombre , diviseur : integer ; // Le nombre et un diviseur
somme : integer ; // La somme des diviseurs
begin
for nombre := 1 to 10000 do
begin
// Comptage des diviseurs
somme := 0; // On n'a pas encore trouvé de diviseurs
for diviseur := 1 to nombre −1 do
// On vérie si le diviseur testé est bien un diviseur du nombre
if nombre mod diviseur = 0 then // Le reste de la division doit être 0
somme := somme + d i v i s e u r ; // On ajoute le diviseur à la somme

// Achage du résultat
if somme = nombre then
Writeln ( nombre , ' est un nombre parfait ' );
end ;

Readln ;
end .

197
Les boucles Les structure de contrôle

20. Afficher tous les couples d’entiers entre -100 et 100 vérifiant la relation 9x−4y = 35
program couples ;
var x , y : integer ; //Les valeurs de x et y
begin
Writeln ( ' Voici les couples qui verifient la relation 9 x −4y=35 : ' );
for x := −100 100 to do
for y := − 100 100 to do
if 9* x − 4* y = 35 then
Writeln ( ' ( ' ,x:3 , ' ; ' ,y:3 , ' ) ' );

Readln ;
end .

21. Afficher tous les triplets de nombres entiers entre 1 et 100 qui vérifient la relation
de Pythagore (ils vérifient la relation x2 + y 2 = z 2 ).
program TripletsPythagore ;
var x,y,z : // Le triplet
integer ;
begin
Writeln ( ' Voici les triplets de Pythagore : ' );

for x to := do 1 100
for to y do
:= 1 100
for to do
z := 1 100
if * * * then
x x + y y = z z
Writeln ( ' ( ' ,x:3 , ' ; ' ,y:3 , ' ; ' ,z :3 , ' ) ' );

Readln ;
end .

22. Calculer le capital obtenu en plaçant un capital initial à intérêts simples et à intérêts
composés.
program interets ;
var Cf , Cd , t : real ; // Le capital nal, le capital de départ et le taux
n : integer ; // Le nombre d'années
i : integer ;
begin
Write ( ' Capital de depart ? ' );
Readln ( Cd ) ;
Write ( ' Combien d ' ' a n n e e s ? ' );
Readln (n ) ;
Write ( ' Taux interets ( e n %) ? ' );
Readln (t );

t := t /100;

198
Les boucles Les structure de contrôle

// Intérêts simples
Cf := Cd * (1+ n * t ) ;
Writeln ( ' Interets simples = ' , Cf : 0 : 2 ) ;

// Intérêts composes
n
// Calculer (1 + t)
Cf := 1;
for i :=1 to n do
Cf := Cf * (1+ t ) ;
// Multiplier par Cd
Cf := Cd * Cf ;

Writeln ( ' Interets composes = ' , Cf : 0 : 2 ) ;

Readln ;
end .

23. Programmer le jeu de la fourchette.


program NombreAleatoire ;
var nombreOrdinateur , nombreUtilisateur , nombreEssais , essaiMax : integer ;
begin
randomize ;

essaiMax := 0;
nombreOrdinateur := random (1000); // 0..999
essaiMax := 10;

nombreEssais := 1;
Write ( ' Quelle est votre proposition ? ' );
Readln ( nombreUtilisateur ) ;

while ( n o m b r e E s s a i s <= e s s a i M a x ) and


( n o m b r e U t i l i s a t e u r <> n o m b r e O r d i n a t e u r ) do
begin
if n o m b r e U t i l i s a t e u r < nombreOrdinateur then
Writeln ( ' Trop petit ! ' )
else
Writeln ( ' Trop grand ! ' ) ;
Write ( ' Quelle est votre proposition ? ' );
Readln ( nombreUtilisateur ) ;
nombreEssais := nombreEssais + 1 ;
end ;

if n o m b r e E s s a i s <= e s s a i M a x then
Writeln ( ' Bravo , vous avez trouve en ' , nombreEssais , ' essai ! ')
else
Writeln ( ' Le nombre a trouver etait ' , nombreOrdinateur ) ;

Readln ;
end .

199
Les boucles Les structure de contrôle

24. Calculer le nombre de ’e’ d’une chaîne. (Il faut tenir compte des majuscules et des
minuscules).
program NombreE ;
const VOYELLES = ' aeiouyAEIOUY ' ;
var String
ch : ;
i : Integer ;
cpt : Integer ;
begin
Write ( ' Quelle est la chaine ? ' );
ReadLn ( ch ) ;

cpt := 0;
for i :=1 to Length ( ch ) do
i f Pos ( c h [ i ] , VOYELLES) > 0 then // le ieme caractère est-il une voyelle ?
cpt := cpt + 1 ;

WriteLn ( ch , ' contient ' , cpt , ' voyelles ' );

ReadLn ;
end .

25. Calculer le nombre de voyelles, de consonnes et des autres caractères d’une chaîne.
program NombreChar ;
const VOYELLES = 'AEIOUY ' ;
CONSONNES = 'ZRTPQSDFGHJKLMWXCVBN ' ;
var String
ch : ;
i : Integer ;
cptVoy , cptCons , cptAutres : Integer ;
begin
Write ( ' Quelle est la chaine ? ' );
ReadLn ( ch ) ;

ch := Upcase ( c h ) ; // Mettre la chaine en majuscules

cptVoy : = 0 ; cptCons : = 0 ; CptAutres : = 0 ;


for i :=1 to Length do ( ch )
i f Pos then // le ieme caractère est-il une voyelle ?
( c h [ i ] , VOYELLES) > 0
cptVoy := cptVoy + 1
else
i f Pos then // le ieme caractère est-il une consonne ?
( c h [ i ] , CONSONNES) > 0
cptCons := cptCons + 1
else // C'est que c'est autre chose
cptAutres := cptAutres + 1 ;

WriteLn ( ch , ' contient ' , cptVoy , ' voyelles , ' , cptCons , ' consonnes et ' ,
cptAutres , ' autres caracteres ' );

ReadLn ;
end .

200
Les boucles Les structure de contrôle

26. Remplacer toutes les minuscules d’une chaîne par des étoiles (*).
program RemplacerMinEtoile ;
const MINUSCULES = ' azertyuiopqsdfghjklmwxcvbn ' ;
var chDepart , chFin : String ;
i : Integer ;
begin
Write ( ' Quelle est la chaine ? ' );
ReadLn ( chDepart ) ;

chFin := ' ' ; // La seconde chaine est vide au départ


for i :=1 to Length do
( chDepart )
// le ieme caractère est-il une minuscule ?
i f Pos ( c h D e p a r t [ i ] , MINUSCULES) > 0 then
chFin := chFin + * ' '
else
chFin := chFin + chDepart [ i ] ;

WriteLn ( chDepart , ' est devenue ' , chFin ) ;

ReadLn ;
end .

27. Renverser une chaîne.


program RenverseChaine ;
var chDepart , chFin : String ;
i : Integer ;
begin
Write ( ' Quelle est la chaine ? ' );
ReadLn ( chDepart ) ;

chFin := ' ' ; // La seconde chaine est vide au départ


for i := Length ( chDepart ) downto 1 do
chFin := chFin + chDepart [ i ] ;

WriteLn ( chDepart , ' renversee est ' , chFin ) ;

ReadLn ;
end .

201
Les boucles Les structure de contrôle

28. Compter le nombre de mots d’une chaîne. On suppose qu’il n’y a pas de lettres
accentuées.
program CompterMots ;
const LETTRES = ' azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN ' ;
var nMots : integer ;
chaine : string ;
i : Integer ;
nouveauMot : boolean ;
begin
Write ( ' Quelle est la chaine ? ' );
ReadLn ( chaine ) ;

// Comptage
nMots := 0;
nouveauMot := False ;
for i := 1 to Length ( chaine ) do
begin
// Pour chaque caractère, on regarde si c'est une lettre
// et qu'on n'est pas entrain de traiter un nouveau mot
i f Pos ( ( chaine [ i ] , LETTRES) > 0 ) and ( nouveauMot = False then
)
begin
inc ( nMots ) ; // Si on n'est pas déjà entrain de traiter un mot,
// on augmente le compteur de mots
nouveauMot := True ; // On est entrain de traiter un nouveau mot
end
else
i f Pos ( chaine [ i ] , LETTRES) = 0 then // Le caractère n'est plus une lettre
nouveauMot := False ;
end ;

Write ( ' Il y a ' , nMots , ' mots ' ) ;

ReadLn ;
end .

Une autre solution est de partir de l’idée qu’on a un nouveau mot si une lettre est
suivie d’un caractère qui n’est pas une lettre (on traite chaine[i] et chaine[i + 1] en
même temps).

202
CHAPITRE 2
TABLEAUX | SOUS-PROGRAMMES | FICHIERS

2.1 Les tableaux


1. Multiplier tous les éléments d’un tableau par 4.
program T a b l ea u E x 1 ;
// Le tableau est lu au clavier.
var Tarray : of [1..6] integer ;
i : integer ;
begin
for to do i :=1 6
begin
write ( ' Entrez un nombre entier : ' );
readln (T [ i ] ) ;
end ;

// Acher le tableau de départ


write ( ' T1 : ' );
for to i :=1 6 do
write (T [ i ] , ' ' );
writeln ;

// Multiplication par 4
for i :=1 to 6 do
T[ i ] := T [ i ] * 4;

// Acher le tableau modié


write ( ' Tx4 : ' );
for i := 1 to 6 do
write (T [ i ] , ' ' );

readln ;
end .

203
Les tableaux Tableaux | Sous-programmes | Fichiers

2. Calculer la somme de deux tableaux à une dimension (utiliser trois tableaux).


program tableaux2 ;
var T1 , array
T2 , T3 of
: [1..6] integer ;
i : integer ;
begin
// Lecture du premier tableau au clavier
for to do
i := 1 6
begin
write ( ' Entrez un nombre pour le premier tableau : ' );
readln ( T1 [ i ] ) ;
end ;

// Lecture du second tableau au clavier


for toi := 1 6 do
begin
write ( ' Entrez un nombre pour le deuxieme tableau : ' );
readln ( T2 [ i ] ) ;
end ;

// Somme
for i := 1 to 6 do
begin
T3 [ i ] := T1 [ i ] + T2 [ i ] ;
end ;

// Achages des trois tableaux


write ( ' T1= ' );
for i := 1 to 6 do
write ( T1 [ i ] , ' ' );
writeln ;

write ( ' T2= ' );


for i := 1 to 6 do
write ( T2 [ i ] , ' ' );
writeln ;

write ( ' T3= ' );


for i := 1 to 6 do
write ( T3 [ i ] , ' ' );

readln ;
end .

204
Les tableaux Tableaux | Sous-programmes | Fichiers

3. Afficher un tableau de N éléments sur M colonnes.


program ExTableauMColonnes ;
const nMax = 1 0 0 0 ;
var array
tab : [ 1 . . NMax ] of integer ;
N, M, i : integer ;
begin
randomize ;
repeat
write ( ' Nombre d ' ' e l e m e n t s du tableau ( entre 1 et ' , nMax , ' ) : ' );
readln (N ) ;
until (N > 0 ) and ( N <= nMax ) ;

write ( ' Nombre de colonnes pour l ' ' affichage du tableau : ' );
readln (M) ;

// Génération aléatoire
for i := 1 to N do
tab [ i ] := 1 + random (100);

// Achage sur M colonnes


for i to := 1 N do
i f mod i M = 0 then
writeln ( tab [ i ] : 5)
else
write ( tab [ i ] :5 );

readln ;
end .

4. Inverser le premier et le dernier élément d’un tableau.


program T a b l ea u E x 7 ;
var array
tab : [1..100] of integer ;
i , N, echange : integer ;
begin
randomize ;
write ( ' Combien d ' ' e l e m e n t s dans le tableau ? ' );
readln (N ) ;

// Génération
for to
i :=1 N do
begin
tab [ i ] := 1 + random (100);
write ( tab [ i ] , ' ' );
end ;
writeln ;

// Échange
echange := tab [N ] ;
tab [N] := tab [1];
tab [1] := echange ;

205
Les tableaux Tableaux | Sous-programmes | Fichiers

// Achage
for i :=1 to N do
write ( tab [ i ] , ' ' );

readln ;
end .

5. Permuter circulairement un tableau vers la gauche.


program T a b l ea u E x 8 ;
const nMax= 1 0 0 0 ;
var array
tab : of [ 1 . . nMax ] integer ;
i , N, memoire : integer ;
begin
randomize ;
repeat
write 'Combien delements dans le tableau (entre 1 et ',nMax,') : '
( );
readln (N ) ;
until and(N > 0 ) (N <= nMax ) ;

for ito do
:= 1 N
begin
tab − random
[ i ] := 100 + (201);
write ( tab [ i ] , ' ' );
end ;
writeln ;

// Permutation vers la gauche


memoire := tab [ 1 ] ; // Retenir le premier
for i := 1 to N−1 do // Décaler
begin
tab [ i ] := tab [ i +1];
end ;
tab [ n ] := memoire ; // Mettre l'élément retenu en dernière place

// Acher
for i := 1 to N do
begin
write ( tab [ i ] , ' ' );
end ;

readln ;
end .

206
Les tableaux Tableaux | Sous-programmes | Fichiers

6. Permuter circulairement un tableau vers la droite.


program T a b l ea u E x 8 ;
const nMax= 1 0 0 0 ;
var array
tab : of [ 1 . . NMax ] integer ;
i , N, memoire : integer ;
begin
randomize ;
repeat
write 'Combien delements dans le tableau (entre 1 et ',nMax,') : '
( );
readln (N ) ;
until and(N > 0 ) (N <= nMax ) ;

for ito do
:= 1 N
begin
tab − random
[ i ] := 100 + (201);
write ( tab [ i ] , ' ' );
end ;
writeln ;

// Permutation vers la droite (on utilise DownTo)


memoire := tab [N ] ; // Retenir le dernier
for i := N downto 2 do // Décaler
begin
tab [ i ] := tab [ i −1];
end ;
tab [ 1 ] := memoire ; // Mettre l'élément retenu en première place

// Acher
for i := 1 to N do
begin
write ( tab [ i ] , ' ' );
end ;

readln ;
end .

207
Les tableaux Tableaux | Sous-programmes | Fichiers

7. Permuter circulairement un tableau d’un nombre quelconque de positions vers la


droite ou vers la gauche.
program Ex10Tableaux ;
var tab : array [1..1000] of integer ;
tab2 : array [1..1000] of integer ;
i , N, p , DG: integer ;
begin
randomize ;
write ( ' Combien d ' ' e l e m e n t s dans le tableau ? ' );
readln (n ) ;
write ( ' De combien voulez vous permuter ? ' );
readln (p ) ;
write ( ' Dans quel sens ( Gauche = 0 ou Droite = 1 )? ' );
readln (DG) ;

// Générer aléatoirement et achage


for to do
i :=1 N
begin
tab − [ i ]random := 100+ (201);
write ( tab [ i ] , ' ' );
end ;
writeln ;

If then // vers la gauche


DG = 0
begin
for to − do
i := 1 N p
tab2 [ i ] := t a b [ i +p ] ;
for − i to do
:= n p+1 n
tab2 [ i ] − − := tab [ i (n p ) ] ;
end
else // vers la droite
begin
for to do
i := 1 p
tab2 [ i ] − := t a b [ n p+ i ] ;
for to − do
i := 1 n p
t a b 2 [ i +p ] := tab [ i ] ;
end ;

// Achage
for i :=1 to N do
write ( tab2 [ i ] , ' ' );

readln ;
end .

208
Les tableaux Tableaux | Sous-programmes | Fichiers

8. Créer un tableau contenant les nombres de Fibonacci.


program TableauxAvecNombreDeFibonacci ;
var array
tab : [1..100] of integer ;
i , N : integer ;
begin
randomize ;
write ( ' Combien d ' ' e l e m e n t s dans le tableau ? ' );
readln (N ) ;

tab [ 1 ] := 1;
tab [ 2 ] := 1;

For i := 3 to N do
tab [ i ] := tab [ i − 1] + tab [ i −2];

For i :=1 to N do
write ( tab [ i ] , ' ' );

readln ;
end .

9. Calculer combien de fois est un élément dans un tableau.


program Ex14Tableaux ;
var array
tab : [1..100] of integer ;
i , N, compteur : integer ;
begin
randomize ;

write ( ' Quel est le nombre que vous recherchez ? ' );


readln (n ) ;

// Génération aléatoire
for i to := 1 100 do
begin
tab [ i ] − := 10 + random (21);
i f mod i 10 = 0 then
writeln ( tab [ i ] :5)
else
write ( tab [ i ] : 5);
end ;

compteur := 0;
for i := 1 to 100 do
if tab [ i ] = n then
c o m p t e u r += 1 ;

writeln ;
write 'Le nombre que vous recherchez est ', compteur, ' fois dans le tableau.'
( );

readln ;
end .

209
Les tableaux Tableaux | Sous-programmes | Fichiers

10. Calculer le minimum des éléments d’un tableau de réels, donner sa position.
program T a b l ea u E x 8 ;
const nMax= 1 0 0 0 ;
var array
tab : [ 1 . . NMax ] of real ;
i , N : integer ;
min : real ;
position : integer ;
begin
randomize ;

repeat
write 'Combien delements dans le tableau (entre 1 et ',nMax,') : '
( );
readln (N ) ;
until and (N > 0 ) (N <= nMax ) ;

for to do
i := 1 N
begin
tab random * [ i ] := 100;
write ( tab [ i ] : 0 : 3 , ' ' );
end ;
writeln ;

// Au départ, le minimum est en première position


min := tab [ 1 ] ;
position := 1;
// Si on rencontre un élément plus petit que min, alors min devient cet élément
for i := 2 to N do
if t a b [ i ] < min then
begin
min := tab [ i ] ;
position := i ;
end ;

// Acher le minimum et sa position


write ( ' Le minimum est ' , min : 0 : 3 , ' en position ' , position );

readln ;
end .

210
Les tableaux Tableaux | Sous-programmes | Fichiers

11. Trier un tableau avec la méthode du tri par sélection du minimum.


program MinimumEnPremier ;
const nMax= 1 0 0 0 ;
var tab : array [ 1 . . NMax ] of integer ;
j , i , N, Min : integer ;
position : integer ;
begin
randomize ;

repeat
write 'Combien delements dans le tableau (entre 1 et ',nMax,') : '
( );
readln (N ) ;
until and (N > 0 ) (N <= nMax ) ;

for to do
i := 1 N
begin

tab [ i ] random := 100 + (100);
write ( tab [ i ] , ' ' );
end ;
writeln ;

// Tri
for j := 1 to n−1 do
begin
Min := Tab [ j ] ;
position := j ;

For i := j +1 to N do
if t a b [ i ] < Min then
begin
min := tab [ i ];
position := i ;
end ;

// Échanger le minimum et le je
tab [ p o s i t i o n ] := tab [ j ] ;
tab [ j ] := min ;
end ;

for i :=1 to n do
write ( tab [ i ] , ' ' );

readln ;
end .

211
Les tableaux Tableaux | Sous-programmes | Fichiers

12. Trier un tableau en utilisant le tri « Bulles ».


program TriBulle ;
const nMax= 1 0 0 0 ;
var tab : array [ 1 . . NMax ] of integer ;
i , N, memoire : integer ;
echange : boolean ;
begin
randomize ;

repeat
write ( 'Combien delements dans le tableau (entre 1 et ',nMax,') : ' ) ;
readln (N ) ;
until (N > 0 ) and (N <= nMax ) ;

// Génération du tableau et achage


for to
i :=1 N do
begin
tab [ i ] := 1 + random (100);
write ( tab [ i ] , ' ' );
end ;
writeln ;

// Tri
repeat
echange := false ;
For i := 1 to − do
N 1
begin
if t a b [ i ] > t a b [ i +1] then
begin
memoire := tab [ i ] ;
tab [ i ] := tab [ i +1];
t a b [ i +1] := memoire ;
echange := true ;
end ;
end ;
until echange = false ; // Arrêt si pas d'échange

// Achage du tableau trié


for i := 1 to n do
write ( tab [ i ] , ' ' );

readln ;
end .

212
Les tableaux Tableaux | Sous-programmes | Fichiers

13. Trier un tableau en utilisant le tri à peigne.


program TriPeigne ;
const nMax= 1 0 0 0 ;
var tab : array [ 1 . . NMax ] of integer ;
i , N : integer ;
echange : boolean ;
begin
randomize ;

repeat
write ( 'Combien delements dans le tableau (entre 1 et ',nMax,') : ' ) ;
readln (N ) ;
until (N > 0 ) and (N <= nMax ) ;

// Génération du tableau et achage


for to
i :=1 N do
begin
tab [ i ] := 1 + random (100);
write ( tab [ i ] , ' ' );
end ;
writeln ;

// Tri
pas := N ;
repeat
pas trunc := ( pas / 1 . 3 ) ;
if then
pas < 1 pas := 1;
fin True := ;
for to − i :=1 (N pas ) do
begin
if tab [ i ] > tab [ i + pas ] then
begin
False fin := ;
echange := tab [ i ] ;
tab [ i ] := t a b [ i +p a s ] ;
t a b [ i +p a s ] := echange ;
end ;
end ;
until ( pas = 1 ) and ( fin = true );

// Achage du tableau trié


for i := 1 to N do
write ( tab [ i ] , ' ' );

readln ;
end .

213
Les tableaux Tableaux | Sous-programmes | Fichiers

14. Comparer les tris en mesurant le temps nécessaire pour trier un ”grand” tableau. Les
tris utilisés sont :
- le tri bulle ;
- le tri par sélection du minimum ;
- le tri par sélection du minimum et du maximum ;
- le tri par insertion ;
- le tri Shell (le tri à peigne).
On trie un tableau de réels puis d’entiers.
program TriComparaison ;
uses dos , crt ;

const nMax = 1 0 0 0 0 0 ; // Nombre d'éléments maximum à trier

var tab1 , tab2 : array [ 1 . . nMax ] of real ;


// On trie tab1 et on retient le tableau de départ dans tab2
tab3 , tab4 : array [ 1 . . nMax ] of integer ;
// On trie tab3 et on retient le tableau de départ dans tab4
e c h a n g e , min , max , i n s e r e : real ;
e c h a n g e 1 , min1 , max1 , i n s e r e 1 : integer ;
temps : array [1..10] of real ;
// Les 5 premiers éléments servent pour le temps de tri d'un tableau de réels ;
// Les 5 derniers éléments servent pour le temps de tri d'un tableau d'entiers ;
i , j , pas , n , placemin , placemax : integer ;
h , m, s , c : word ;
// heure, minute, seconde, centième de seconde
Total_sec_depart , Total_sec_fin : real ;
fin : boolean ;
f ,g : integer ;
// f est le nombre de fois qu'on exécute chaque tri
// g est l'indice de boucle qui va de 1 à f
coeff : array [1..5] of real ;
// Rapports entre les temps de tris pour des réels et des entiers

begin
// Lecture du nombre d'éléments (n)
repeat
write ( ' Combien d ' ' e l e m e n t s ? ' );
readln (n ) ;
until and
(n > 0) ( n <= nMax ) ;

// Lecture du nombre de tris à eectuer pour calculer la moyenne des temps


repeat
write ( ' Combien de fois v o u l e z −v o u s trier ? ' );
readln ( f );
until f > 0;

// Initialisation du tableau des temps


for i :=1 to 10 do
temps [ i ] := 0;

214
Les tableaux Tableaux | Sous-programmes | Fichiers

// On trie f fois un tableau de réels puis d'entiers avec les cinq méthodes
for g to do
:= 1 f
begin
// Génération des éléments des tableaux (un de réels et un d'entiers) et les retenir
Randomize ;
for to do
i := 1 n
begin
random *
tab1 [ i ] := 100;
tab2 [ i ] := tab1 [ i ] ;
round
tab3 [ i ] := ( tab1 [ i ] ) ;
tab4 [ i ] := tab3 [ i ] ;
end ;

// ***********************************************************************

// Tris de réels
// ***********************************************************************
// Calcul de l'heure de départ
g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

// Tribulle
j := 1;
repeat
true
f i n := ;
for to i := 1 n− j do
if t a b 1 [ i ] > t a b 1 [ i +1] then
begin
echange := tab1 [ i ] ;
tab1 [ i ] := tab1 [ i +1];
t a b 1 [ i +1]:= echange ;
fin := false ;
end ;
j += 1 ;
until fin = true ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 1 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i := 1 to n do
tab1 [ i ] := tab2 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

215
Les tableaux Tableaux | Sous-programmes | Fichiers

// Tri par sélection du minimum


for i := 1 to − do n 1
begin
// Recherche du minimum et de sa place dans le tableau
min := tab1 [ i ] ;
placemin := i ;
for j := i +1 to n do
if min > t a b 1 [ j ] then
begin
min := tab1 [ j ] ;
placemin := j ;
end ;
// Échanger le minimum et le ie élément du tableau
tab1 [ placemin ] := tab1 [ i ] ;
tab1 [ i ] := min ;
end ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 2 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i :=1 to n do
tab1 [ i ] := tab2 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

216
Les tableaux Tableaux | Sous-programmes | Fichiers

// Tri par sélection du minimum et du maximum.


// Le minimum est placé au début et en même temps, le maximum est placé à la n
for i := 1 to div do // Que jusqu'à la moitié
n 2
begin
// Recherche du minimum et du maximum et de leur place dans le tableau
min := tab1 [ i ] ;
placemin := i ;
max := tab1 [ i ] ;
placemax := i ;
for j := i +1 to n− i +1 do
begin
if min > t a b 1 [ j ] then
begin
min := tab1 [ j ] ;
placemin := j ;
end ;
if max < t a b 1 [ j ] then
begin
max := tab1 [ j ] ;
placemax := j ;
end ;
end ;
// Échanger le minimum et le ie élément du tableau
// Échanger le maximum et le (n-i+1)e élément du tableau
tab1 [ placemin ] := tab1 [ i ] ;
tab1 [ i ] := min ;
if placemax = i then
placemax := placemin ;
tab1 [ placemax ] := t a b 1 [ n− i + 1 ] ;
t a b 1 [ n− i +1] := max ;
end ;
// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 3 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i :=1 to n do
tab1 [ i ]:= tab2 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

217
Les tableaux Tableaux | Sous-programmes | Fichiers

// Tri par insertion


for i := to do
2 n
begin
insere := tab1 [ i ] ;
j := i − 1;
while ( j >= 1 ) and ( t a b 1 [ j ] >= insere ) do
begin
t a b 1 [ j +1] := tab1 [ j ] ;
j −= 1;
end ;
t a b 1 [ j +1] := insere ;
end ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 4 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i :=1 to n do
tab1 [ i ] := tab2 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

// Tri Shell
p a s := n ;
while dop a s >1
begin
pas div:= pas 2;
for to i := 1 n−p a s do
begin
j := i ;
while ( j > 0) and ( t a b 1 [ j ] > t a b 1 [ j+p a s ] ) do
begin
echange := tab1 [ j ] ;
tab1 [ j ] := t a b 1 [ j+p a s ] ;
t a b 1 [ j+p a s ] := echange ;
j := j −p a s ;
end ;
end ;
end ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 5 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

218
Les tableaux Tableaux | Sous-programmes | Fichiers

// ***********************************************************************

// Tris d'entiers
// ***********************************************************************
// Calcul de l'heure de départ
g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

// Tribulle
j := 1;
repeat
fin true:= ;
for ito := 1 n− j do
if t a b 3 [ i ] > t a b 3 [ i +1] then
begin
echange1 := tab3 [ i ] ;
tab3 [ i ] := tab3 [ i +1];
t a b 3 [ i + 1 ] : =e c h a n g e 1 ;
fin := false ;
end ;
j += 1 ;
until fin = true ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 6 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i :=1 to n do
tab3 [ i ] := tab4 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

219
Les tableaux Tableaux | Sous-programmes | Fichiers

// Tri par sélection du minimum


for i :=1 to − do
n 1
begin
// Recherche du minimum et de sa place dans le tableau
min1 := tab3 [ i ] ;
placemin := i ;
for j := i +1 to n do
if min1 > t a b 3 [ j ] then
begin
min1 := tab3 [ j ] ;
placemin := j ;
end ;
// Échanger le minimum et le ie élément du tableau considéré
tab3 [ placemin ] := tab3 [ i ] ;
tab3 [ i ] := min1 ;
end ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 7 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i :=1 to n do
tab3 [ i ]:= tab4 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

220
Les tableaux Tableaux | Sous-programmes | Fichiers

// Tri par sélection du minimum et du maximum


for i :=1 to div do
n 2
begin
// Recherche du minimum et du maximum et de leur place dans le tableau
min1 := tab3 [ i ] ;
placemin := i ;
max1 := tab3 [ i ] ;
placemax := i ;
for j := i +1 to n− i +1 do
begin
if min1 > t a b 3 [ j ] then
begin
min1 := tab3 [ j ] ;
placemin := j ;
end ;
if max1 < t a b 3 [ j ] then
begin
max1 := tab3 [ j ] ;
placemax := j ;
end ;
end ;
// Échanger le minimum et le ie élément du tableau
// Échanger le maximum et le (n-i+1)ie élément du tableau
tab3 [ placemin ] := tab3 [ i ] ;
tab3 [ i ] := min1 ;
if p l a c e m a x= i then
p l a c e m a x := p l a c e m i n ;
tab3 [ placemax ] := t a b 3 [ n− i + 1 ] ;
t a b 3 [ n− i +1] := max1 ;
end ;

//Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 8 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i :=1 to n do
tab3 [ i ] := tab4 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

221
Les tableaux Tableaux | Sous-programmes | Fichiers

// Tri par insertion


for i :=2 to do n
begin
insere1 := tab3 [ i ] ;
j := i − 1;
while ( j >= 1 ) and ( t a b 3 [ j ] >= i n s e r e 1 ) do
begin
t a b 3 [ j +1] := tab3 [ j ] ;
j −= 1;
end ;
t a b 3 [ j +1] := insere1 ;
end ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 9 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;

// On recopie le deuxième tableau dans le premier pour trier le même tableau


for i := 1 to n do
tab3 [ i ]:= tab4 [ i ] ;

// Calcul de l'heure de départ


g e t T i m e ( h , m, s , c ) ;
Total_sec_depart := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;

// Tri Shell
p a s := n ;
while dop a s >1
begin
pas div:= pas 2;
for to i := 1 n−p a s do
begin
j := i ;
while ( j > 0) and ( t a b 3 [ j ] > t a b 3 [ j+p a s ] ) do
begin
echange1 := tab3 [ j ] ;
tab3 [ j ] := t a b 3 [ j+p a s ] ;
t a b 3 [ j+p a s ] := echange1 ;
j := j −p a s ;
end ;
end ;
end ;

// Calcul de l'heure de n
g e t T i m e ( h , m, s , c ) ;
Total_sec_fin := h * 3 6 0 0 + m* 6 0 + s + c / 1 0 0 . 0 ;
temps [ 1 0 ] += T o t a l _ s e c _ f i n − Total_sec_depart ;
end ; // Boucle sur g qui varie de 1 à f

222
Les tableaux Tableaux | Sous-programmes | Fichiers

// Calcul du temps moyen


for i := 1 to 10 do
temps [ i ] := temps [ i ] / f ;

// Calcul des coecients


for i :=1 to 5 do
if temps [ i +5] > 0 then
coeff [ i ] := temps [ i ] / temps [ i +5]
else
coeff [ i ] := 0;

//Achage des temps (voir le résultat en page 224)


clrscr ;
write chr ( (218));
for to
i :=1 do 20
write chr ( (196));
write chr ( (194));
for to do
i :=1 9
write chr ( (196));
write chr ( (194));
for to do
i :=1 9
write chr ( (196));
write chr ( (194));
for to do
i :=1 9
write chr ( (196));
writeln chr ( (191));

writeln (
chr(179),' Tri ',chr(179),' Reels ',chr(179),' Entiers ',chr(179),' k ',chr(179) ) ;

write chr ( (195));


for i :=1 to do 20
write chr ( (196));
write chr ( (197));
for i :=1 to do 9
write chr ( (196));
write chr ( (197));
for i :=1 to do 9
write chr ( (196));
write chr ( (197));
for i :=1 to do 9
write chr ( (196));
writeln chr ( (180));

writeln (
chr(179),' Tri Bulle ',chr(179),temps[1] :8 :2,' ',chr(179),temps[6] :8 :2,' ',chr(179),coe[1] :8 :2,' ',chr(179) );
writeln (
chr(179),' Tri sel. min.',chr(179),temps[2] :8 :2,' ',chr(179),temps[7] :8 :2,' ',chr(179),coe[2] :8 :2,' ',chr(179) );
writeln (
chr(179),' Tri sel. min. Max. ',chr(179),temps[3] :8 :2,' ',chr(179),temps[8] :8 :2,' ',chr(179),coe[3] :8 :2,'
',chr(179) ) ;
writeln (
chr(179),' Tri par insertion ',chr(179),temps[4] :8 :2,' ',chr(179),temps[9] :8 :2,' ',chr(179),coe[4] :8 :2,'
',chr(179) ) ;
writeln (

223
Les tableaux Tableaux | Sous-programmes | Fichiers

chr(179),' Tri Shell ',chr(179),temps[5] :8 :2,' ',chr(179),temps[10] :8 :2,' ',chr(179),coe[5] :8 :2,' ',chr(179) ) ;

write chr ( (192));


for to
i :=1do 20
write chr ( (196));
write chr ( (193));
for to do
i :=1 9
write chr ( (196));
write chr ( (193));
for to do
i :=1 9
write chr ( (196));
write chr ( (193));
for to do
i :=1 9
write chr ( (196));
writeln chr ( (217));

readln ;

end .

Voici ce qu’on obtient avec 50000 éléments 1 :


- Reels est le temps obtenu pour trier un tableau de réels ;
- Entiers est le temps obtenu pour trier un tableau d’entiers ;
- k est le rapport entre les temps de tris de réels par rapport à celui d’entiers.

1. Les temps dépendent, évidemment, de la machine utilisée

224
Les sous-programmes Tableaux | Sous-programmes | Fichiers

2.2 Les sous-programmes


1. Écrire un sous-programme qui calcule 1 + 2 + 3 + · · · + N .
program Exercice1SsProgramme ;

function somme ( nombre : integer ) : integer ;


var i : integer ;
som : integer ;
begin
som := 0;

for i := 1 to nombre do
som += i ;

somme := som ; // ou Result := som ;


end ;

// Programme principal
var n : integer ;
begin
write ( ' Entrez un nombre : ' );
readln (n ) ;

writeln ( ' La somme est : ' , somme ( n ) ) ; // Appel de la fonction

readln ;
end .

2. Écrire un sous-programme qui teste si un entier est premier.


program Exercice2SsProgramme ;

function e s t P r e m i e r ( nombre : integer ) : boolean ;


var compteur : integer ; // Compte des diviseurs
i : integer ;
begin
compteur := 0;

for i := 1 to nombre do
if nombre mod i = 0 then // C'est un diviseur
c o m p t e u r += 1 ;

if compteur = 2 then
estPremier := true
else
estPremier := false ;
end ;

225
Les sous-programmes Tableaux | Sous-programmes | Fichiers

// Programme principal
var n : integer ;
begin
write ( ' Entrez un nombre : ' );
readln (n ) ;

if estPremier (n) = true then // Appel de la fonction


writeln ( ' Le nombre est premier ' )
else
writeln ( ' Le nombre n ' ' est pas premier ' ) ;

readln ;
end .

3. Écrire un sous-programme qui calcule an (a est un double ; n est un entier positif).


program exerciceSsProgramme ;

function exposant ( a : real ; n : integer ) : real ;


var i : integer ;
produit : real ;
begin
produit := 1;
for i := 1 to n do
produit *= a;

result := produit ; // Ou exposant := produit


end ;

var base : real ;


expos : integer ;

begin
write ( ' Entrez un nombre : ' );
readln ( base ) ;
write ( ' Entrez l ' ' exposant de ce nombre : ' );
readln ( expos ) ;

writeln ;
write ( ' La reponse est ' , exposant ( base , expos ) : 0 : 2 ) ;

readln ;
end .

226
Les sous-programmes Tableaux | Sous-programmes | Fichiers

4. Écrire un sous-programme qui calcule an (a est un double ; n est un entier quelconque


positif, négatif ou nul).
program exerciceSsProgramme ;

function exposant ( a : real ; n : integer ) : real ;


var i : integer ;
produit : real ;
begin
if then
n = 0
begin
if then
a = 0

Result := 1E99 // Valeur spéciale
else
Result := 1;
end
else
begin
produit := 1;
for to abs
i := 1 (n) do // Valeur absolue
produit := produit * a;

if n < 0 then
Result := 1 / produit
else
Result := produit ;
end ;
end ;

var base : real ;


expos : integer ;

begin
write ( ' Entrez un nombre : ' );
readln ( base ) ;
write ( ' Entrez l ' ' exposant de ce nombre : ' );
readln ( expos ) ;

writeln ;
write ( ' La reponse est ' , exposant ( base , expos ) : 0 : 2 ) ;

readln ;
end .

227
Les sous-programmes Tableaux | Sous-programmes | Fichiers

5. Écrire un sous-programme qui calcule le pgcd (plus grand commun diviseur) de


deux nombres entiers positifs.
program exerciceSsProgramme ;

function PGCD(A, B : integer ) : integer ;


var Min , Diviseur : integer ;
trouve : boolean ;
begin
// Quel est le plus petit nombre ?
if A > B then
Min := A
else
Min := B ;

Trouve := false ;
Diviseur := Min ; // Le PGCD est au plus le plus petit nombre

// On diminue jusqu'à trouver un diviseur commun


repeat
if mod (A Diviseur = 0) and (B mod Diviseur = 0) then
trouve := true
else
Diviseur := Diviseur − 1;
until trouve ;

Result := Diviseur ;
end ;

var n1 , n2 : integer ;
begin
write ( ' Premier nombre : ' );
readln ( n1 ) ;
write ( ' Second nombre : ' );
readln ( n2 ) ;

writeln ;
write ( ' Le pgcd de ces deux nombres est ' ,PGCD( n1 , n2 ) ) ;

readln ;
end .

228
Les sous-programmes Tableaux | Sous-programmes | Fichiers

6. Écrire un sous-programme qui réduit une fraction à sa plus simple expression.

Remarque : Cet exercice utilise une procédure et cette procédure utilise une
fonction.
program reduireSsProgramme ;
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fonction PGCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
function PGCD(A, B : integer ) : integer ;
var Diviseur : integer ;
begin
// Le PGCD est au maximum le plus petit des deux nombres.
if A > B then
Diviseur := B
else
Diviseur := A ;

// On retire 1 tant qu'au moins un deux nombres de départ n'est pas


// multiple de Diviseur
// Utilisation d'une boucle while plutôt que repeat
while (A mod D i v i s e u r <> 0 ) or (B mod D i v i s e u r <> 0 ) do
Diviseur := Diviseur − 1;

// Diviseur est le résultat désiré


Result := Diviseur ;
end ;

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Procedure Simplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// Réduire une fraction à sa plus simple expression.
// Attention : VAR N2,D2 car ce sont deux résultats mais
// N1,D1 sans var car ce sont des paramètres d'entrée
procedure S i m p l i f i c a t i o n ( N1 , D1 : i n t e g e r ; var N2 , D2 : i n t e g e r ) ;
begin
// La procédure se sert de la fonction PGCD (elle l'appelle deux fois)
N2 := N1 div PGCD( N1 , D1 ) ;
D2 := D1 div PGCD( N1 , D1 ) ;
end ;

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programme principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
var N1 , D1 , N2 , D2 : integer ;
begin
write ( ' Numerateur : ' );
readln ( n1 ) ;
write ( ' Denominateur : ' );
readln ( d1 ) ;

// Appel de la procédure
S i m p l i f i c a t i o n ( n1 , d1 , n2 , d2 ) ;

writeln ;
write ( n1 , ' / ' , d1 , ' = ' , n2 , ' / ' , d2 ) ;

readln ;
end .

229
Les sous-programmes Tableaux | Sous-programmes | Fichiers

7. Écrire un sous-programme qui affiche tous les nombres de Armstrong.


program afficheArmstrong ;

procedure Armstrong ; // Il n'y a pas de paramètre


var nomb : integer ;
reste : integer ;
centaine , dizaine , unite : integer ;
begin
// De part la dénition d'un nombre d'Armstrong, la procédure sait qu'il y a trois chires
for nomb :=to do 100 999
begin
// Recherche le chire des centaines, des dizaines et des unités
centaine div := nomb 100;
reste mod := nomb 100;
dizaine div := reste 10;
unite mod := reste 10;

// Armstrong ?
if nomb = c e n t a i n e * c e n t a i n e * c e n t a i n e + d i z a i n e * d i z a i n e * d i z a i n e +
unite * unite * unite then
writeln ( nomb , ' est un nombre d ' ' Armstrong ' ) ;
end ;
end ;

begin
// Appel de la procédure
Armstrong ;

readln ;
end .

8. Écrire un sous-programme qui affiche tous les nombres de Pythagore compris entre
1 et N
program pythagore ;

procedure pytha ( n : integer );


var i , j ,k : integer ;
begin
for i := 1do to n
for j := do 1 to n
for to do
k := 1 n
if * * i i + j j = k*k then
writeln (i , ' + ' ,j , ' = ' ,k , ' ' ) ;
end ;

var nb : i n t e g e r ;
begin
write ( ' J u s q u ' ' ou chercher les nombres de Pythagore ? ' );
readln ( nb ) ;

p y t h a ( nb ) ;

readln ;
end .

230
Les sous-programmes Tableaux | Sous-programmes | Fichiers

9. Écrire un sous-programme qui calcule le nombre de voyelles d’une chaîne de carac-


tères.
program calculerNombreVoyelles ;

function nbvoyelles ( chaine : string ) : integer ;


var nbchar : integer ; // Nombre de caractères de la chaîne
i : integer ;
compteur : integer ;
begin
nbchar := Length ( chaine ) ;
compteur := 0;

for i := 1 to nbchar do
if ( chaine [ i ] = 'a ' ) or ( chaine [ i ] = 'e ') or ( chaine [ i ] = ' i ') or
( chaine [ i ] = 'o ' ) or ( chaine [ i ] = 'u ' ) or ( chaine [ i ] = 'y ' ) then
c o m p t e u r += 1 ;

Result := compteur ;
end ;

var string
chaine : ;
begin
write ( ' Entrez la chaine de caracteres : ' );
readln ( chaine ) ;

writeln ( ' Le nombre de voyelles dans la chaine = ' , nbvoyelles ( chaine ) ) ;


readln ;
end .

10. Écrire un sous-programme qui retourne une chaîne de caractères en majuscules. Par
exemple, ’oiseau’ donne ’UAESIO’.
program reverseChaine ;

function r e v e r s e M a j ( ch : string ) : string ;


var string
maj : ;
i : integer ;
begin
maj := ' ' ; // Chaine vide

for i := Length ( ch ) downto 1 do


maj := maj + ch [ i ] ;
maj := Upcase ( maj ) ;

Result := maj ;
end ;

var string
chaine : ;
begin
write ( ' Entrez la chaine de caracteres : ' );
readln ( chaine ) ;

writeln ( ' La chaine de caractere en majuscule = ' , reverseMaj ( chaine ) ) ;


readln ;
end .

231
Les sous-programmes Tableaux | Sous-programmes | Fichiers

11. Écrire un sous-programme qui calcule le produit scalaire de deux tableaux.


n
X
T1 • T2 = T 1[i]T 2[i]
i=1

program produitScalaire ;
type tableau = array [1..1000] of integer ;

function s c a l a i r e ( t1 , t2 : tableau ; taille : integer ) : integer ;


var i : integer ;
resultat : integer ;

begin
resultat := 0;
for i := 1 to taille do
resultat := resultat + t1 [ i ] * t2 [ i ] ;

Result := resultat ;
end ;

var tab1 : tableau ;


tab2 : tableau ;
n : integer ;
i : integer ;

begin
Randomize ;

write ( ' Combien de valeurs par tableau ? ' );


readln (n ) ;

// Génération aléatoire
for i := 1 to n do
tab1 [ i ] := 1 + random (11);
for i := 1 to n do
tab2 [ i ] := 1 + random (11);

// Achage des deux tableaux


for to do i :=1 n
write ( tab1 [ i ] , ' ' );
writeln ;
for to do
i := 1 n
write ( tab2 [ i ] , ' ' );

// Calcul et achage du résultat


writeln ;
writeln ( ' Le produit scalaire de ces nombres est ' ,
s c a l a i r e ( tab1 , tab2 , n ) );

readln ;
end .

232
Les sous-programmes Tableaux | Sous-programmes | Fichiers

12. Écrire un sous-programme qui calcule le minimum des éléments d’un tableau de
réels (double).
program minimumTableau ;
const nMax = 1 0 0 0 ;
type tableau = array [ 1 . . nMax ] of real ;

function minimum ( t : t a b l e a u ; t a i l l e : integer ) : real ;


var i : integer ;
mini : real ;
begin
mini := t [1];

for i := 2 to taille do
if t [ i ] < mini then
mini := t [ i ];

Result := mini ;
end ;

var tab : tableau ;


i : integer ;
n : integer ;

begin
repeat
write ( ' Combien de valeurs dans le tableau ? ' );
readln (n ) ;
until (n > 0) and ( n <= nMax ) ;

for to i :=1 do
n
tab [ i ] := random * 100;

for i := 1 to do n
begin
write ( tab [ i ] : 0 : 2 , ' ' );
i f mod i 8 = 0 then
writeln ;
end ;

writeln ;
writeln ( ' Le minimum du tableau est : ' , minimum ( t a b , n ) : 0 : 2 ) ;

readln ;
end .

233
Les sous-programmes Tableaux | Sous-programmes | Fichiers

13. Écrire un sous-programme qui génère un tableau d’entiers.


(a) Avec une fonction.
program genereTab ;
const nMax = 1 0 0 0 ;
type array
tableau = [ 1 . . nMax ] of integer ;

function genere ( t a i l l e : integer ) : tableau ;


var i : integer ;
tab : tableau ;
begin
Randomize ;

for to i := 1 taille do
tab [ i ] := 1 + random (100);

Result := tab ;
end ;

var i ,n : integer ;
t : tableau ;
begin
write ( ' Taille du tableau ? ' );
readln (n ) ;

t := genere (n ) ;

for to i := 1 n do
begin
write (t [ i ] , ' ' );
i f mod i 8 = 0 then
writeln ;
end ;

readln ;
end .

234
Les sous-programmes Tableaux | Sous-programmes | Fichiers

(b) Avec une procédure.


program genereTab ;
const nMax = 1 0 0 0 ;
type tableau = array [ 1 . . nMax ] of integer ;

// Attention : VAR (passage par adresse)


procedure var genere ( tab : tableau ; taille : integer );
var i : integer ;
begin
Randomize ;

for to ido := 1 taille


random
tab [ i ] := 1 + (100);
end ;

var i ,n : integer ;
t : tableau ;
begin
write ( ' Taille du tableau ? ' );
readln (n ) ;

genere ( t , n ) ;

for to i := 1 n do
begin
write (t [ i ] , ' ' );
i f mod i 8 = 0 then
writeln ;
end ;

readln ;
end .

14. Écrire la recherche dichotomique grâce à une fonction ; le tableau sera au préalable
trié avec une procédure.
program triTableauRechercheDichotmique ;
const nMax = 1 0 0 0 ;
type tableau = array [ 1 . . nMax ] of integer ;

procedure tri ( var t : tableau ; t a i l l e : integer ); // Utilisation du tri par insertion


var i , j : integer ;
insere : integer ;
begin
for i :=2 to taille do
begin
insere := t [ i ];
j := i − 1;
while ( j >= 1 ) and ( t [ j ] >= insere ) do
begin
t [ j +1] := t [ j ];
j −= 1;
end ;
t [ j +1] := insere ;
end ;
end ;

235
Les sous-programmes Tableaux | Sous-programmes | Fichiers

(*
La fonction qui suit recherche un é l é ment dans le tableau en utilisant
la recherche dichotomique . Elle retourne
−1 si l ' é l é ment n ' e s t pas le tableau ,
la place de l ' é l é ment s ' i l y est .
*)
function dichosearch ( t : tableau ; t a i l l e : integer ; cle : integer ) : integer ;
var debut , f i n , m i l i e u : integer ;
trouve : boolean ;
begin
debut := 1;
fin := taille ;
trouve := false ;

while and
( d e b u t <= f a l s e do
fin ) ( trouve = )
begin
milieu div
:= ( d e b u t+ f i n ) 2;
if then
t [ milieu ] = cle
true
trouve :=
else
if then
t [ milieu ] < cle
debut := milieu + 1
else

fin := milieu 1;
end ;

if then // ⇐⇒ if trouve = true


trouve
Result := milieu
else
Result := − 1; // cle ne se trouve pas sans le tableau
end ;

// Procédure d'achage
procedure afficheTableau ( t : tableau ; t a i l l e : integer );
var i : integer ;
begin
for toi := 1 taille do
begin
write (t [ i ] , ' ' );
i f mod i 8 = 0 then
writeln ;
end ;
end ;

236
Les sous-programmes Tableaux | Sous-programmes | Fichiers

// Programme principal
var tab : tableau ;
i : integer ;
n : integer ;
search : integer ; // Élément à rechercher
ou : integer ; // Résultat de la recherche
begin
Randomize ;

repeat
write ( ' Combien de valeurs dans le tableau ? ' );
readln (n ) ;
until (n > 0) and ( n <= nMax ) ;

for to i :=1 n do
tab [ i ] := 1 + random (100);

// Achage du tableau en appelant la procédure acheTableau


writeln ;
a f f i c h e t a b l e a u ( tab , n ) ;

// Appel de la procédure de tri


t r i ( tab , n ) ;

// Réachage du tableau (trié)


writeln ;
writeln ;
a f f i c h e T a b l e a u ( tab , n ) ;

writeln ;
writeln ;
writeln ( ' Quel nombre r e c h e r c h e z −v o u s ? ' );
readln ( search ) ;

ou := d i c h o s e a r c h ( tab , n , s e a r c h ) ;
if − then
ou <> 1
writeln ( search , ' a ete trouve a la place ' , ou )
else
writeln ( search , ' n ' 'a pas ete trouve dans le tableau ' ) ;

readln ;
end .

237
Les sous-programmes Tableaux | Sous-programmes | Fichiers

15. L’aire d’un cercle de rayon 1 est π et l’aire d’un carré qui contient exactement ce
cercle est 4. Ainsi, si un grand nombre de points sont choisis aléatoirement dans la
partie supérieure droite du carré, la proportion de ces points qui seront dans le cercle
est approximativement π/4. Calculer une valeur approximative de π.
Pour rappel, l’équation du cercle de rayon 1 est x2 + y 2 = 1.
program CalculPI ;

// La fonction exécute la génération aléatoire n fois


function approchePI ( n : i n t e g e r ) : real ;
var i : integer ;
x,y : real ; // Nombres générés aléatoirement entre 0 et 1
compteur : integer ; // Nombre de fois que l'expérience est à l'intérieur du cercle
begin
compteur := 0;

for i :=1 to do n
begin
x := random ; // x ∈ [0, 1[
y := random ; // y ∈ [0, 1[
if x * x + y * y <= 1 then // Tombe dans le cercle
compteur := compteur + 1 ;
end ;

Result := compteur /n * 4;
end ;

begin
write ( approchePI ( 1 0 0 0 0 0 0 ) : 0 : 8 ) ; // 1000000 de fois l'expérience

readln ;
end .

238
Graphisme Tableaux | Sous-programmes | Fichiers

2.3 Graphisme
Réaliser l’exercice suivant :

program Graphe ;
uses Graph , c r t ;
var pilote , mode : smallint ;
i : integer ;
Largeur , // Largeur de la fenêtre graphique
Hauteur , // Hauteur de la fenêtre graphique
Echelle , // Une unité mathématique correspond à Echelle pixels
MilieuX , milieuY : integer ; // Origine (0, 0) mathématique
pas : Real ;
xMath , yMath : Real ; // Coordonnées mathématiques
xPixels , yPixels : Integer ; // Coordonnées en pixels
x1 , x2 , y1 , y2 : R e a l ; // Coordonnées de deux points (peuvent avoir des décimales)

// La fonction à tracer
function f (x : real ) : real ;
begin
Result := Sqrt (x) * sin (x );
end ;

239
Graphisme Tableaux | Sous-programmes | Fichiers

begin
I n i t G r a p h ( p i l o t e , mode , ' ' ) ; // Initialisation de la fenêtre graphique

// Initialisation des variables


Echelle := 150;
Largeur := GetMaxX ;
Hauteur := GetMaxY ;
MilieuX := 2 * Echelle ;
MilieuY := Hauteur div 2;

// Mettre un fond blanc (plus lisible qu'un fond noir)


S e t B k C o l o r ( White ) ;
ClearViewPort ;

// Dénition du style des axes


S e t L i n e S t y l e ( DottedLn , 0, NormWidth ) ; // Pointillés
S e t C o l o r ( Blue ) ; // Les axes seront en bleu

// Axe des X
MoveTo ( 0 , M i l i e u Y ) ;
LineTo ( L a r g e u r , Mi li eu Y ) ;
// Axe des Y
MoveTo ( M i l i e u X , 0);
LineTo ( MilieuX , hauteur ) ;
// Graduations de l'axe des X (10 pixels de haut)
// Gauche de l'axe
i := 0;
repeat
MoveTo ( M i l i e u X −i , MilieuY −5);
L i n e T o ( M i l i e u X −i , MilieuY +5);
i := i + echelle ;
until i >= 2 * E c h e l l e ;
// Droite de l'axe
i := 0;
repeat
MoveTo ( M i l i e u X+i , MilieuY −5);
L i n e T o ( M i l i e u X+i , MilieuY +5);
i := i + echelle ;
until i >= l a r g e u r ;

// Graduations sur l'axe des Y (10 pixels de large)


i := 0;
repeat
MoveTo ( M i l i e u X −5 , MilieuY−i ) ;
L i n e T o ( M i l i e u X +5 , MilieuY−i ) ;
MoveTo ( M i l i e u X −5 , M i l i e u Y+ i ) ;
L i n e T o ( M i l i e u X +5 , M i l i e u Y+ i ) ;
i := i + echelle ;
until i > hauteur div 2;

240
Graphisme Tableaux | Sous-programmes | Fichiers

// Tracé d'un segment de droite entre deux points dont les coordonnées
// seront lues à l'écran
write ( ' Abcisse du premier point : ' );
readln ( x1 ) ;
write ( ' Ordonnee du premier point : ' );
readln ( y1 ) ;
write ( ' Abcisse du deuxieme point : ' );
readln ( x2 ) ;
write ( ' Ordonnee du deuxieme point : ' );
readln ( y2 ) ;
SetColor ( Red ) ;
S e t L i n e S t y l e ( SolidLn , 0, NormWidth ) ; // Continu
MoveTo ( milieuX + Round ( x1 * E c h e l l e ) , milieuY − Round ( y1 * E c h e l l e ) ) ;
LineTo ( milieuX + Round ( x2 * E c h e l l e ) , milieuY − Round ( y2 * E c h e l l e ) ) ;

// Tracé de f(x) entre 0 et 2π


S e t L i n e S t y l e ( SolidLn , 0, NormWidth ) ; // Pointillés
S e t C o l o r ( Magenta ) ;
pas := 1/ E c h e l l e ;
xMath := 0;
yMath := f (0); // Vaut 0
xPixels := milieuX + Round ( xMath * E c h e l l e ) ;
yPixels := milieuY − Round ( yMath * E c h e l l e ) ;
MoveTo ( x P i x e l s , y P i x e l s ) ; // Bien se positionner au départ

repeat
xMath := xMath + p a s ;
yMath := f ( xMath ) ;
xPixels := milieuX + Round ( xMath * E c h e l l e ) ;
yPixels := milieuY − Round ( yMath * E c h e l l e ) ;
LineTo ( x P i x e l s , y P i x e l s ) ;
until xMath > 2 * pi ;

// Ecrit le texte f(x) = sqrt(x)*sin(x)


S e t T e x t S t y l e ( GothicFont , HorizDir , 2 ) ;
OutTextXY ( M i l i e u X + 2 0 0 , 2 5 0 , ' f ( x ) = S q r t ( x ) * s i n ( x ) ' ) ;

readln ;
CloseGraph ;
end .

241
Les fichiers texte Tableaux | Sous-programmes | Fichiers

2.4 Les fichiers texte


1. Compter le nombre de lignes d’un fichier texte.
program ExFichiers ;
var fich : text ;
ligne : string ;
compteur : integer ;
begin
Assign ( fich , 'C : \ E x e r c i c e s \ f i c h i e r . t x t ' ) ;
Reset ( fich );

compteur := 0;
while not Eof ( fich ) do
begin
Readln ( fich , ligne );
compteur := compteur + 1 ;
end ;

Close ( fich );
writeln ;
writeln ( ' Il y a ' , compteur , ' lignes dans le texte ' ) ;
readln ;
end .

2. Mettre tous les caractères d’un fichier texte en majuscules (dans un autre fichier).
program ExFichiers ;
var fichIn , fichOut : text ;
ligne string
: ;
begin
Assign ( fichIn , 'C : \ f p c \ b d l o g . t x t ' ) ;
Reset ( fichIn ); // Ouverture en lecture
Assign ( fichOut , 'C : \ f p c \ maj . t x t ' ) ;
Rewrite ( fichOut ) ; // Création (ou eacement) du chier

while not Eof ( fichIn ) do


begin
Readln ( fichIn , ligne );
Writeln ( fichOut , upCase ( ligne ));
end ;

Close ( fichIn );
Close ( fichOut ) ;
end .

242
Les fichiers texte Tableaux | Sous-programmes | Fichiers

3. Calculer la fréquence d’apparition des lettres dans un fichier texte.


program frequenceLettres ;
var fich : text ;

// Tableau qui permet de compter le nombre de fois que chaque lettre apparaît.
// tab['A'] contient le nombre de 'A', . . ., tab['Z'] contient le nombre de 'Z'.
tab : array [ 'A ' . . ' Z ' ] of integer ;
tabFrequence : array [ 'A ' . . ' Z ' ] of real ;

i : integer ;
ligne : string ;
j : char ; // Pour les boucles sur le tableau de char (tab)
compteurLettres : integer ; // Nombre de lettres
begin
for j := 'A ' to 'Z ' do
tab [ j ] : = 0 ;
compteurLettres :=0;

Assign ( fich , 'C : \ f p c \ b d l o g . t x t ' ) ;


Reset ( fich );

while not Eof do ( fich )


begin
Readln ( fich , ligne );
ligneUpcase := // Mise en majuscules
( ligne );
// Parcourir tous les caractères de la chaîne
for to Length
i := 1 do ( ligne )
begin
// Ne tenir compte que des lettres
if and
( l i g n e [ i ] >= 'A ' ) ( l i g n e [ i ] <= 'Z ' ) then
begin
tab[ligne[i]] += 1 ; // Le c÷ur de l'exercice
c o m p t e u r L e t t r e s += 1 ;
end ;
end ;
end ;

Close ( fich );

writeln ;
writeln ( ' Il y a ' , compteurLettres , ' lettres dans le fichier ' );
writeln ;

// Transformer tab en tableau des fréquences (pourcentage)


for j := 'A ' to 'Z ' do
tabFrequence [ j ] := tab [ j ] / compteurLettres * 100;

for j := 'A ' to 'Z ' do


writeln (j , ' : ' , tabFrequence [ j ] : 0 : 1 , ' %' ) ;

readln ;
end .

243
Les fichiers texte Tableaux | Sous-programmes | Fichiers

4. Compter le nombre de mots d’un fichier texte.


(*
Compte le nombre de mots d ' un fichier en supposant qu ' i l n'y ai pas de
lettres accentuées .
Cette programme utilise les ensembles mais pourrait s ' en passer
*)
program CompteurMots ;
var fichier : Text ;
nMots : integer ;
ligne : string ;
i : integer ;
nouveauMot : boolean ;
begin
// Ouverture
Assign ( fichier , 'C : \ f p c \ b d l o g . t x t ' ) ;
Reset ( fichier );

// Comptage
nMots := 0;

while not eof do ( fichier )


begin
Readln ( fichier , ligne );
nouveauMot False := ;
for to Length
i := 1 do ( ligne )
begin
// Pour chaque caractère, on regarde si c'est une lettre
if IN
( ligne [ i ] and False then
[ 'A ' . . ' Z ' , ' a ' . . ' z ' ] ) ( nouveauMot = )
begin
inc // Si on n'est pas déjà entrain de traiter un mot,
( nMots ) ;
// on augmente le compteur de mots
True // On est entrain de traiter un nouveau mot
nouveauMot := ;
end
else
i f not IN ( ligne [ i ] then // Pas une lettre
[ 'A ' . . ' Z ' , ' a ' . . ' z ' ] )
False
nouveauMot := ;
end ;
end ;

Close // Fermeture du chier


( fichier );

writeln ( ' Il y a ' , nMots , ' mots dans le fichier ' );

readln ;
end ;

244
Les fichiers texte Tableaux | Sous-programmes | Fichiers

5. Lire un fichier texte et y remplacer les voyelles par #.


Première solution
program ExFichiers ;
var fichIn , fichOut : text ;
ligne : string ;
i : integer ;
car : char ; // ie caractère de la ligne en majuscule
begin
Assign ( fichIn , 'C : \ f p c \ b d l o g . t x t ' ) ;
Reset // Ouverture en lecture
( fichIn );
Assign ( fichOut , 'C : \ f p c \ v o y e l l e s . t x t ' ) ;
Rewrite // Création (ou eacement) du chier
( fichOut ) ;

while not Eof do ( fichIn )


begin
Readln ( fichIn , ligne );
// Traitement de la ligne
for to Length
i := 1do ( ligne )
begin
// Mettre le caractère (ie)en majuscule dans une autre variable
// pour ne pas changer la valeur du caractère.
car := upCase ( ligne [ i ] ) ;
if ( car = 'A ' ) or ( car = 'E ' ) or ( car = 'I ') or
( car = 'O ' ) or ( car = 'U ' ) or ( car = 'Y ' ) then
ligne [ i ] := '# ' ;
end ;
Writeln ( fichOut , ligne );
end ;

Close ( fichIn ); Close ( fichOut ) ;


end .

Deuxième solution (utilisation de Pos qui indique la position d’une sous-chaîne dans une chaîne).
program ExFichiers ;
var fichIn , fichOut : text ;
ligne : string ;
i : integer ;
voyelles : string ; // Contiendra toutes les voyelles
begin
Assign ( fichIn , 'C : \ f p c \ U C o n t r o l e . p a s ' ) ; Reset ( fichIn );
Assign ( fichOut , 'C : \ f p c \ v o y e l l e s s . t x t ' ) ; Rewrite ( fichOut ) ;

voyelles := ' aeiouyAEIOUY ' ;

while not Eof do ( fichIn )


begin
Readln ( fichIn , ligne );
for to Length
i := 1 ( ligne ) do // Traitement de la ligne
i f Pos ( ligne [ i ] , voyelles ) > 0 then // C'est une voyelle
ligne [ i ] := '# ' ;
Writeln ( fichOut , ligne );
end ;

Close Close
( fichIn ); ( fichOut ) ;
end .

245
Les fichiers texte Tableaux | Sous-programmes | Fichiers

6. Dans un fichier HTML, remplacer les balises gras par italique.


- <b> devient <i>
- </b> devient </i>
program ExFichiers ;
var fichIn : text ;
fichOut : text ;
ligne : string ;
i : integer ;
begin
Assign ( fichIn , 'C : \ f p c \ e s s a i . h t m l ' ) ;
Assign ( fichOut , 'C : \ f p c \ r e s u l t a t . h t m l ' ) ;

Reset ( fichIn );
Rewrite ( fichOut ) ;

while not Eof ( fichIn ) do


begin
Readln ( fichIn , ligne );

// Remplacer <b> par <i>


for i := 1 to Length ( l i g n e ) −2 do
begin
if l i g n e [ i ]+ l i g n e [ i +1]+ l i g n e [ i +2] = '<b> ' then
begin
ligne[i] := '<' ; // Inutile
l i g n e [ i +1] := ' i ' ;
ligne[i+2] := '>' ;
end ;
end ;

// Remplacer </b> par </i>


for i := 1 to Length ( l i g n e ) −3 do
begin
if l i g n e [ i ]+ l i g n e [ i +1]+ l i g n e [ i +2]+ l i g n e [ i +3] = ' </b> ' then
begin
ligne[i] := '<' ;
ligne[i+1] := '/' ;
l i g n e [ i +2] := ' i ' ;
ligne[i+3] := '>' ;
end ;
end ;

// Écriture dans le chier


Writeln ( fichOut , l i g n e ) ;
end ;

Close ( fichIn );
Close ( fichOut ) ;

write ( ' Travail termine ! ' ) ;


readln ;
end .

246
Les fichiers texte Tableaux | Sous-programmes | Fichiers

7. Compter le nombre de fois qu’un mot apparaît dans un fichier.


program CompterMot ;
var fichier_Texte : Text ;
ligne : string ;
motACompter : string ;
compteur : integer ; // Compte combien de fois le mot est dans le chier
i : integer ;
begin
Assign ( f i c h i e r _ T e x t e , 'C : \ f i c h i e r . p a s ' ) ;
Reset ( fichier_Texte ) ;

// Quel mot recherche-t-on ?


write ( ' Quel mot ? ' );
readln ( motACompter ) ;

compteur := 0;
while not Eof ( fichier_Texte ) do
begin
Readln ( f i c h i e r _ T e x t e , l i g n e ) ; // Lire une ligne du chier
// Tester si le mot se trouve à la ie position
// Le programme extrait à partir du ie caractère autant de caractères
// que la longueur du mot
for i := 1 to Length ( ligne ) − Length ( motACompter ) + 1 do
i f Copy ( ligne , i , Length ( motACompter ) ) = motACompter then
compteur := compteur + 1 ;
end ;

Close ( fichier_Texte ) ;

writeln ( compteur ) ;

readln ;
end .

247
Les fichiers d’enregistrements Tableaux | Sous-programmes | Fichiers

2.5 Les fichiers d’enregistrements


Gestion "simplifiée" d’un fichier d’élèves (cf. exercice page 127)
program FichierEleves ;
uses sysutils , crt ;

type TEleve =
record
numero : i n t e g e r ;
nom : string ;
prenom : string ;
sexe : char ;
nat : string ;
classe : string ;
localite : string ;
points : integer ;
end ;
fichierEleves = f i l e of TEleve ;

( * ************************** Affiche tous les é l èves ************************** * )


procedure string
s h o w A l l ( chemin : ) ;
var unEleve : TEleve ;
fich : fichierEleves ;
begin
// Quitte la procédure si le chier n'existe pas
i f not f i l e E x i s t s then
( chemin )
begin
write ( ' Fichier inexistant ! ' );
readln ;
exit ;
end ;

c l r s c r // Eace l'écran
;
assign ( f i c h , chemin ) ;
reset ( fich );

while not eof do


( fich )
begin
read ( f i c h , unEleve ) ;
writeln ( u n E l e v e . numero , ' ' ,
StringOfChar
u n E l e v e . nom , − length ( ' ' ,20 ( u n E l e v e . nom ) ) ,
StringOfChar
u n E l e v e . prenom , − length ( ' ' ,20 ( u n E l e v e . prenom ) ) ,
unEleve . sexe , StringOfChar − length ( ' ' ,2 ( unEleve . s e x e ) ) ,
unEleve . nat , StringOfChar − length ( ' ' ,5 ( unEleve . nat ) ) ,
StringOfChar
unEleve . c l a s s e , − length ( ' ' ,5 ( unEleve . c l a s s e ) ) ,
StringOfChar
unEleve . l o c a l i t e , − length ( ' ' ,25 ( unEleve . l o c a l i t e ) ) ,
unEleve . p o i n t s , ' ' );
end ;
close ( fich );

readln ;
end ;

248
Les fichiers d’enregistrements Tableaux | Sous-programmes | Fichiers

( * **************** Recherche les é l èves connaissant un nom **************** * )


procedure string
searchName ( chemin : string ; nom : );
var unEleve : TEleve ;
fich : fichierEleves ;
begin
// Quitte la procédure si le chier n'existe pas
i f not f i l e E x i s t s then
( chemin )
begin
write ( ' Fichier inexistant ! ' );
readln ;
exit ;
end ;

clrscr ;
assign ( f i c h , chemin ) ;
reset ( fich );

while not eof do


( fich )
begin
read ( f i c h , unEleve ) ;
if then
u n E l e v e . nom = nom
begin
writeln ( u n E l e v e . numero , ' ' ,
StringOfChar
u n E l e v e . nom , − length ( ' ' ,20 ( u n E l e v e . nom ) ) ,
StringOfChar
u n E l e v e . prenom , − length ( ' ' ,20 ( u n E l e v e . prenom ) ) ,
StringOfChar
unEleve . sexe , − length ( ' ' ,2 ( unEleve . s e x e ) ) ,
StringOfChar
unEleve . nat , − length ( ' ' ,5 ( unEleve . nat ) ) ,
StringOfChar
unEleve . c l a s s e , − length ( ' ' ,5 ( unEleve . c l a s s e ) ) ,
StringOfChar
unEleve . l o c a l i t e , − length ( ' ' ,25 ( unEleve . l o c a l i t e ) ) ,
unEleve . po i n t s , ' ' );
end ;
end ;
close ( fich );

readln ;
end ;

( * **************** Recherche l ' é l ève connaissant s o n numé r o **************** * )


procedure string
searchNum ( c h e m i n : ; num : i n t e g e r ) ;
var unEleve : TEleve ;
fich : fichierEleves ;
begin
// Quitte la procédure si le chier n'existe pas
i f not f i l e E x i s t s then
( chemin )
begin
write ( ' Fichier inexistant ! ' );
readln ;
exit ;
end ;

clrscr ;
assign ( f i c h , chemin ) ;
reset ( fich );

249
Les fichiers d’enregistrements Tableaux | Sous-programmes | Fichiers

while not eof ( fich ) do


begin
read ( f i c h , unEleve ) ;
if u n E l e v e . numero = num then
begin
writeln ( u n E l e v e . numero , ' ' ,
u n E l e v e . nom , StringOfChar − length
( ' ' ,20 ( u n E l e v e . nom ) ) ,
u n E l e v e . prenom , StringOfChar − length( ' ' ,20 ( u n E l e v e . prenom ) ) ,
unEleve . sexe , StringOfChar − length
( ' ' ,2 ( unEleve . s e x e ) ) ,
unEleve . nat , StringOfChar − length
( ' ' ,5 ( unEleve . nat ) ) ,
unEleve . c l a s s e , StringOfChar − length ( ' ' ,5 ( unEleve . c l a s s e ) ) ,
unEleve . l o c a l i t e , StringOfChar − length ( ' ' ,25 ( unEleve . l o c a l i t e ) ) ,
unEleve . po i n t s , ' ' );
end ;
end ;
close ( fich );

readln ;
end ;

( * *************** Fonction pour compter le nombre de filles *************** * )


function n b r f i l l e s ( chemin : string ) : integer ;
var compteur : i n t e g e r ;
unEleve : TEleve ;
fich : fichierEleves ;
begin
// Quitte la procédure si le chier n'existe pas
i f not f i l e E x i s t s then
( chemin )
begin
write ( ' Fichier inexistant ! ' );
readln ;
exit ;
end ;

clrscr ;
assign ( f i c h , chemin ) ;
reset ( fich );

compteur : = 0 ;
while not eof ( fich ) do
begin
read ( f i c h , unEleve ) ;
if unEleve . s e x e = 'F ' then
c o m p t e u r := c o m p t e u r +1;
end ;
close ( fich );
Result := compteur ;
end ;

250
Les fichiers d’enregistrements Tableaux | Sous-programmes | Fichiers

( * ** Afficher les renseignements de l ' é l ève qui a le plus de points ** * )


procedure pointsMax ( chemin : string );
var unEleve : TEleve ;
unEleveMax : T E l e v e ; // Elève qui a le plus de points
fich : fichierEleves ;
maxPoints : i n t e g e r ;
begin
// Quitte la procédure si le chier n'existe pas
i f not f i l e E x i s t s then
( chemin )
begin
write ( ' Fichier inexistant ! ' );
readln ;
exit ;
end ;

assign ( f i c h , chemin ) ;
reset ( fich );

// Trouver l'élève qui a le plus de points


maxPoints := 0;
while not eof ( fich ) do
begin
read ( f i c h , unEleve ) ;
if unEleve . p o i n t s > maxPoints then
begin
maxPoints := unEleve . p o i n t s ;
unEleveMax := unEleve ; // Retenir l'élève
end ;
end ;

// Acher tous les renseignements de l'élève trouvé précédemment


clrscr ;
writeln ( unEleveMax . numero , ' ' ,
unEleveMax . nom , StringOfChar − length
( ' ' ,20 ( unEleveMax . nom ) ) ,
unEleveMax . prenom , StringOfChar − length
( ' ' ,20 ( unEleveMax . prenom ) ) ,
unEleveMax . s e x e , StringOfChar − length
( ' ' ,2 ( unEleveMax . s e x e ) ) ,
unEleveMax . n a t , StringOfChar − length
( ' ' ,5 ( unEleveMax . n a t ) ) ,
unEleveMax . c l a s s e , StringOfChar − length
( ' ' ,5 ( unEleveMax . c l a s s e ) ) ,
unEleveMax . l o c a l i t e , StringOfChar − length
( ' ' ,25 ( unEleveMax . l o c a l i t e ) ) ,
unEleveMax . p o i n t s , ' ' );
close ( fich );

readln ;
end ;

251
Les fichiers d’enregistrements Tableaux | Sous-programmes | Fichiers

( * ************ Suppression d ' un é l è v e connaissant s o n numé r o ************** * )


procedure s u p E l e v e ( chemin : string ; num : i n t e g e r ) ;
var unEleve : TEleve ;
fich , fich2 : fichierEleves ;
num : i n t e g e r ;
begin
// Quitte la procédure si le chier n'existe pas
i f not f i l e E x i s t s then
( chemin )
begin
write ( ' Fichier inexistant ! ' );
readln ;
exit ;
end ;

clrscr ;
assign ( f i c h , chemin ) ;
reset ( fich );
assign ( fich2 , ' c :/ t e s t / Eleves2 . rec ' ) ;
rewrite ( fich2 ) ;

while not eof do


( fich )
begin
read ( f i c h , unEleve ) ;
if then
u n E l e v e . numero <> num
begin
write ( f i c h 2 , unEleve ) ;
end ;
end ;

close ( fich );
close ( fich2 );

deletefile ( chemin ) ;
renamefile ( ' c : / t e s t / E l e v e s 2 . r e c ' , chemin ) ;
end ;

252
Les fichiers d’enregistrements Tableaux | Sous-programmes | Fichiers

( * ********************** Tri par ordre alphabétique ********************** * )


procedure t r i A l p h a b e t ( chemin : string ; cheminTrie : string );
var array
t : [1..1000] of TEleve ;
f i l e of
fich : TEleve ;
f i l e of
fichTri : TEleve ;
i : integer ;
memoire : T E l e v e ;
echange : boolean ;
begin
// Quitte la procédure si le chier n'existe pas
i f not f i l e E x i s t s then ( chemin )
begin
write ( ' Fichier inexistant ! ' );
readln ;
exit ;
end ;

clrscr ;
assign ( f i c h , chemin ) ;
reset ( fich );

// Copier le chier dans le tableau


i :=1;
while not eof ( fich ) do
begin
read ( fich , t [ i ] ) ;
i := i +1;
end ;
close ( fich );

// Tri du tableau (bulle)


// leSize(ch) est le nombre d'éléments "intéressants" du tableau
repeat
false
echange := ;
for to f i l e S i z e
i :=1 ( fich ) do
begin
if t [ i ] . nom > t [ i + 1 ] . nom then
begin
true
echange := ;
memoire := t [ i ];
t [ i ] := t [ i +1];
t [ i +1] := memoire ;
end ;
end ;
until echange = false ;

// Copier le tableau dans le chier trié


assign ( f i c h T r i , cheminTrie ) ;
rewrite ( fichTri );
for to f i l e S i z e
i :=1 ( fich ) do
write ( fichTri , t [ i ] ) ;

close ( fichTri );
end ;

253
Les fichiers d’enregistrements Tableaux | Sous-programmes | Fichiers

( * ************************ Programme principal ************************ * )


var choix : char ;
chemin : string ;
cheminTrie : string ;
nom : string ;
num : i n t e g e r ;
begin
c h e m i n := ' c : / t e s t / E l e v e s . r e c ' ;
Repeat
clrscr ;
writeln ( ' Entrez a pour afficher tous les eleves ' );
writeln ( ' Entrer r pour rechercher un eleves avec le nom ' );
writeln ( ' Entrer n pour rechercher un eleves avec le numero ' );
writeln ( ' Entrez f pour compter le nombres de filles ' );
writeln ( ' Entrez m pour voir les eleves qui ont eu le max ' );
writeln ( ' Entrez s pour supprimer un eleves avec son numero ' ) ;
writeln ( ' Entrez t pour trier par ordre alphabé t i q u e ' );
writeln ( ' Entrez q pour quitter le programme ' );
readln ( choix ) ;
case choix of
'a ' : s h o w A l l ( chemin ) ;
'r ' : begin
write ( ' Entrez le nom a rechercher ' );
readln ( nom ) ;
nom := upcase ( nom ) ;
s e a r c h N a m e ( chemin , nom ) ;
end ;
'n ' : begin
write ( ' Entrez le numero de l ' ' eleve a rechercher ' );
readln ( num ) ;
searchNum ( chemin , num ) ;
end ;
'f ' : begin
write ( ' Le nombre de filles vaut ' , n b r f i l l e s ( chemin ) ) ;
readln ;
end ;
'm ' : pointsMax ( chemin ) ;
's ' : begin
write ( ' Entrez le numero de l ' ' eleve a supprimer ' );
readln ( num ) ;
s u p E l e v e ( chemin , num ) ;
end ;
't ' : begin
cheminTrie := ' c :/ test / ElevesTrie . rec ' ;
t r i A l p h a b e t ( chemin , c h e m i n T r i e ) ;
end ;
end ;
until c h o i x= ' q ' ;
end .

254

Vous aimerez peut-être aussi