Home

Télécharger au format docx, pdf ou txt
Télécharger au format docx, pdf ou txt
Vous êtes sur la page 1sur 163

 --- Home ---

 Contact

 --- Home ---


 Contact

 --- Home ---


 Contact

 --- Home ---


 Contact
 --- Home ---
 Contact

 --- Home ---


 Contact

 --- Home ---


 Contact

 --- Home ---


 Contact
 --- Home ---
 Contact

Introduction à l'Informatique

1- Définition
Le mot Informatique est formé de 2 parties: infor qui découle du mot
information et atique qui découle du mot automatique.
Une définition de l'informatique est la suivante: traitement
automatique de l'information.

2- Structure et Fonctionnement d'un Ordinateur


2.1 Ordinateur - Définition
Ordinateur: machine utilisée dans le traitement de l'information.
Un ordinateur est composée de 2 parties:
- une partie matériel (hardware) : les éléments physiques (écran,
clavier, disque dur, ...) qui composent l'ordinateur.
- une partie logiciel (software) : système d'exploitation(operating
system): ensemble de programmes qui gèrent l'ordinateur.

2.2 Catégories d'ordinateurs


Un peu d'histoire:
En 1945 est apparu le premier ordinateur: l'ENIAC
Années 50 a 70: les gros ordinateurs tels que IBM 360/370
Années 70 - 80: les mini ordinateurs tels que Vax, PDP11 (Digital)
Les années 90 à ce jour les PC (Personal Computer)
On peut citer comme catégories d'ordinateurs:
- Mainframe: gros ordinateurs
- PC
- Tablette
- PDA: Personal Digital Assistant

2.3- Organisation d'un Ordinateur


Le schema ci-dessous montre l'organisation d'un ordinateur.

2.3.1 Unites d'Entrée/Sortie


Ces unités permettent de communiquer avec l'exterieur (utilisateur).
Exemples d'unité d'entrée/sortie: clavier, ecran, imprimante,...

2.3.2 Mémoire Centrale


Elle permet la sauvegarde des données et instructions à éxecuter sous
forme binaire (BIT: Binary digIT).
Un bit prend 2 valeurs 0 et 1.
La mémoire centrale est constituée de mémoire RAM (Random
Access Memory) mémoire à accés aléatoire.
La RAM est une mémoire volatile, c'est a dire que le contenu est
perdu dés qu'il n' y a plus de courant electrique.
La capacité de la mémoire est le nombre d'octets que la mémoire
occupe. Un octet (byte) est 8 bits.
La mémoire centrale contient de la DRAM (Dynamic RAM). Le
temps d'accés (temps de lecture) est de 50 a 150 ns.
Un octet est 8 bits.
1 Kilo octet (KO ou Kilo Byte KB) est 210 octets = 1024 octets
1 Mega octet (MO ou MB) est 210 KO = 1024 KB
1 Giga octet (GO ou GB) est 210 MO = 1024 MB
1 Tera octet (TO ou TB) est 210 GO = 1024 GB

Un mot mémoire (word) est 4 octets (32 bits) ou bien 8 octets (64
bits).
Un mot mémoire est le nombre de bits que le processeur traite à la fois
(addition, soustraction, ...).
Dans une machine 32 bits le mot mémoire est de 32 bits. Dans une
machine 64 bits le mot mémoire est de 64 bits.
Chaque octet de la MC a une adresse spécifique. Si un octet est à
l'adresse n l'octet juste à cote est à l'adresse (n + 1).
La figure ci-dessous montre un exemple d'une MC où le mot mémoire
est de 4 octets.
A gauche sont montrées les adresses des mots mémoire: le premier
mot mémoire est à l'adresse 0, le deuxieme mot mémoire est à
l'adresse 4 (vu qu'il y'a 4 octets par mot), le troisième mot mémoire est
à l'adresse 8, et ainsi de suite...

Une autre forme de mémoire est la ROM (Read Only Memory):


mémoire non volatile. Cette mémoire contient les informations
nécessaires lors du démarrage de l’ordinateur comme le programme
pour booter l’ordinateur.
Temps d'accés à la mémoire est le temps de lecture.

2.3.3 Unité Centrale (UC ou CPU Central Processing Unit)


Contient l'unité de contrôle (ou bien unité de commande) et l'unité
arithmetique et logique (UAL).
L'unité de commande intreprète le langage machine (langage binaire
spécifique à cet ordinateur) et éxecute les instructions qui sont en MC.
L'UAL éxecute les operations arithmetiques et logiques.
L'UC utilise un certain nombre d'unités de stockage appelés registres
qui sont de la mémoire dont l'accés est rapide. Les registres sont de la
SRAM (Static RAM), le temps d'accés est de 1 a 10 ns.

2.3.4 Bus System


Permet le transfert d'informations entre les différents composants de
l'ordinateur.

2.4 Codage de l'information


Numérotation décimale
On utilise les chiffres 0, 1, 2, .., 9 (base 10)
3271 = 3 x 103 + 2 x 102 + 7 x 101 + 1 x 100

Système Binaire (base 2).


On utilise les chiffres 0 et 1
1101 = 1 x 23 + 1 x 22 + 0 x 21 + 1 x 20

(1101)(2) = 13(10)

Système Octale (base 8).


On utilise les chiffres 0, 1, 2, 3, 4, 5, 6 et 7.
237 = 2 x 82 + 3 x 81 + 7 x 80
237(8) = 159(10)
Système Hexadecimale (base 16).
On utilise les chiffres 0, 1, …, 9, A(10), B(11), C(12), D(13), E(14) et
F(15)
3AE = 3 x 162 + 10 x 161 + 14 x 160
3AE(16) = 942(10)

Transcodage (Conversion de Base)


Conversion de base b vers decimale
Règle : Multiplier chaque facteur par la puissance corréspondate de la
base b et faire la somme (voir Systeme Binaire, Systeme Octale et
Systeme Hexadecimale précédemment).
Exemples:
(1101)(2) = 1 x 23 + 1 x 22 + 0 x 21 + 1 x 20 = 13
237(8) = 2 x 82 + 3 x 81 + 7 x 80 = 159
3AE(16) = 3 x 162 + 10 x 161 + 14 x 160 = 942

Conversion Decimale vers base b (binaire, octale ou


hexadecimale)
Règle : on divise le nombre par la base b, puis le quotient par la base b
et ainsi de suite jusqu’a l’obtention d’un quotient nul. La suite des
restes corréspond aux symboles de la base visée. On obtient en
premier le chiffre de poids faible et en dernier le chiffre de poids fort.
Exemple : N = 74
Convertir N=74 en binaire, en octale et en hexadecimale.

Ainsi on obtient:
74(10) = 1001010(2)
74(10) = 112(8)
74(10) = 4A(16)

Correspondance Octale - Binaire


Valeur Octale - Valeur Binaire
0 - 000
1 - 001
2 - 010
3 - 011
4 - 100
5 - 101
6 - 110
7 - 111

Correspondance Hexadecimale - Binaire


Valeur Hexadecimaleale - Valeur Binaire
0 - 0000
1 - 0001
2 - 0010
3 - 0011
4 - 0100
5 - 0101
6 - 0110
7 - 0111
8 - 1000
9 - 1001
10 - 1010
11 - 1011
12 - 1100
13 - 1101
14 - 1110
15 - 1111
Conversion binaire vers decimale, octale et hexadecimale
Binaire vers decimale : Déja vu
Binaire vers octale : regrouper tous les 3 bits à partir de la droite
(ajouter des 0 à gauche si le nombre totale de bits n’est pas un
multiple de 3).
Exemple :
1011101 en binaire a convertir en octale
(001)(011)(101) = 135(8)

Binaire vers héxadecimale : regrouper tous les 4 bits à partir de la


droite (ajouter des 0 à gauche si le nombre totale de bits n’est pas un
multiple de 4).
Exemple :
1011101 en binaire a convertir en hexadecimale
(0101)(1101) = 5D(16)

Exercice
Convertir 29, 37, 43 et 79 vers binaire, octale et hexadecimale.
Convertir vers decimale, octale et hexadecimale les nombres en
binaire: 10110110 et 1001110

3. Logiciels et Programmes
Système d’exploitation (operating system) : logiciel qui gère
l’ordinateur
Drivers (pilote) : ils permettent de communiquer avec les unités
d’entrée/sortie.
Applications : browser google chrome, windows Excel, word , …

IDE : Integrated Development Environment : permet de développer


des applications dans un ou plusieurs langages (contient éditeur,
compilateur, linker et debugger).

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Etapes de Résolution d'un Problème en Informatique

1- Exemples Introductifs
Exemple 1:
Comment assister (la veille) à un cours qui commence a 8:00 h
- Mettre l'alarme a 6:00 h matun
- S'endormir
- Si alarme sonne:
- Se réveiller
- Se laver
- Prendre son café
- Marcher vers le bus
- Arrivée du bus - Marcher vers l'amphi
- Assister au cours

Exemple 2:
Supposons que l'on veut calculer avec une calculatrice le périmètre
d'un réctangle connaissant sa longueur et sa largeur. Voit ci ce qu'il
faut faire:
- Allumer la calculatrice
- Taper le premier nombre pour la longueur
- Appuyer sur la touche '+'
- Taper le deuxième nombre pour la largeur
- Appuyer sur la touche '='
- Appuyer sur la touche '*'
- Appuyer sur la touche '2'
- Appuyer sur la touche '=' (et le resultat est affiche)

Pour arriver au résultat il fallait éxecuter une suite ordonnée d'actions.


Ces actions manipulent des données (premier nombre, deuxième
nombre, touche '+', touche '=', touche '*', touche '2').
Mais avant d'entamer ces actions il fallait faire une réflexion pour
identifier la démarche à suivre.

2- Résolution d'un Problème Informatique


2.1 Notion de Problème
Un problème a un enoncé qui donne des informations sur les données initiales et
des informations sur les résultats qu'on veut obtenir.

2.2 Notion d'Action


Une action est quelque chose qui doit être fait. Une action peut être élémentaire
comme elle peut être composée. Une action élémentaire est une action qui peut être
éxécutée immédiatement par la machine. Une action composée comporte plusieurs
actions élémentaires.
Exemple: taper sur la touche '+' est une action élémentaire alors que taper le
premier nombre est une action composée si le nombre est par exemple égale à 35
(première action élémentaire appuyer sur la touche '3', deuxième action élémentaire
taper sur la touche '5').

Une action peut être une action de calcul, de lecture ou d'écriture, ou bien de
contrôle (on verra les actions de contrôle plus tard dans ce chapitre).

2.3 Notion de Donnée


Une donnée est l'entité manipulée par une action.
Une donnée est identifiée par son nom. Elle est aussi décrite par son type et sa
valeur.
Le type décrit l'ensemble des valeurs que peut prendre la donnée et la valeur est une
instance de cet ensemble.
Par exemple on peut avoir comme donnée l'âge d'une personne à qui on donne
comme nom âge, son type est entier et on peut avoir comme valeur 22 (pour
quelqu'un qui a 22 ans).
Nom: age
Type: Entier
Valeur (variable): 22
Une donnée peut être une variable comme elle peut être une constante. Une
variable est une donnée dont la valeur peut changer. Une constante est une donnée
dont la valeur ne peut pas changer.
Un exemple de constante est le nombre 3.14 (pi) utilisé dans le calcul par exemple
du périmetre d'un cercle (égale à (2pi * R) où R est le rayon du cercle).
Nom: pi
Type: Reel
Valeur (constante): 3.14

2.4 Etapes de Résolution d'un Problème


Pour résoudre un problème informatique on suit les étapes suivantes:
1- Définition
2- Analyse
3- Structuration
4- Traduction
5- Compilation
6- Test et Correction d'erreurs (Debugging)

2.4.1 Définition
Dans cette étape il faut comprendre à partir de l'énonce du problème exactement ce
qu'on a comme données initiales et ce qu'on veut avoir comme résultats. Si l'enoncé
n'est pas trés clair il faut que ce dernier soit clarifié.

2.4.2 Analyse
Dans cette etape il faut:
1)- Identifier ce qu'on a comme données initiales (données en entrée)
2)- Déterminer les données qu'on désire avoir comme résultats (données en sortie).
3)- Déterminer le traitement nécessaire pour obtenir les données en sortie à partir
des données en entrée.

En 1) généralement chaque donnée en entrée est décrite par une variable qui doit
être utilisée par une action de lecture au début.
De meme en 2) généralement pour chaque résultat on utilise une variable qui doit
être utilisée par une action d'ecriture à la fin.
En 3) on doit trouver une démarche qui permet d'arriver au résultat en partant des
données initiales. Cette demarche va identfier les actions et les données dont ces
actions ont besoin pour arriver au résultat. Il se peut qu'il faudra introduire des
données intermediares qui seront manipulées par les actions nécessaires dans le
traitement.

Remarque:
Lorsqu'on a affaire à un problème plutôt complexe, on divise dans la phase de
traitement le problème en sous-problèmes et si les sous-problèmes restent encore
complexes à résoudre on les divise encore en d'autres sous-problèmes et ainsi de
suite jusqu'à arriver à des problèmes plutôt simples. A la fin on intègrera les
solutions des différents sous-problèmes pour avoir la solution finale. Essayer de
résoudre un problème complexe en entier est beaucoup plus difficile que de
résoudre sous-problème par sous-problème.

Exemple:
Etant donné la longueur d'un réctangle et le rapport de la largeur par rapport à la
longueur on veut calculer le périmetre de ce réctangle.
Par exemple l'utilisateur donne la longueur égale à 15 et donne un rapport égale à
0.5, c'est à dire que la largeur est égale 0.5 * longueur (soit la moitié de la longueur
dans ce cas).

1) En entrée on aura besoin d'une variable pour la longueur et d'une variable pour le
rapport
2) En sortie on aura besoin d'une variable pour le périmetre
3) On sait que perimetre = 2 * (longueur + largeur)
La longueur on l'a en entrée donc on aura besoin d'une donnée intermediare pour
la largeur.
largeur = longueur * rapport

Donc les actions qui doivent être faites:


- L'utilisateur donne la longueur (opération de lecture)
- L'utilisateur donne le rapport (opération de lecture)
- Calcul de la largeur à partir de la longueur et du rapport largeur = longueur *
rapport
- Calcul du perimetre = 2 * (longueur + largeur)
- Donner le résultat à l'utilisateur (opération d'écriture)

2.4.3 Structuration
Dans cette étape on traduit les données et les actions faites dans l'analyse sous
forme de pseudo-code (algorithme) ou sous forme d'organigramme.
Un algorithme peut être définie comme une suite finie d'opérations permettant de
résoudre un problème (ou une classe de problèmes).
Un organigramme est une représentation graphique d'un algorithme. Il est composé
par des symboles graphiques comme montrée par la figure suivante:

Application
La figure suivante montre l'organigramme du calcul du périmetre d'un rectangle
connaissant sa longueur et le rapport de sa largeur par rapport à sa longueur.

Il faut noter que dans cet organigramme le symbole "<---" montre une affectation,
c'est à dire on prend le contenu de ce qui est à droite de la flèche et on met ça dans
la variable dont le nom est situé à gauche de la flèche. Ainsi dans l'instruction:
"Larg <--- Long * Rapp" on multiplie le contenu de Long par le contenu de Rapp et
le résultat on le met dans la variable Larg.
2.4.4 Traduction
Dans cette étape le pseudo-code est traduit dans un langage de programmation. Un
langage de programmation est un langage formel permettant d'implementer un
algorithme.
Il y'a plusieurs langages de programmation: C, C++, Pascal, Java, Python, ....

2.4.5 Compilation
Dans cette phase un compilateur est utilisé. Un compilateur est un programme qui
traduit un programme source écrit dans un langage de programmation (comme par
exemple en C) en langage machine compris par l'ordinateur. Avant de faire cela le
compilateur fait 3 types de verification: vérification lexicographique (vérification
du vocabulaire), vérification syntaxique (vérification de la grammaire) et
vérification semantique (vérification du sens).

2.4.6 Test et Correction d'Erreurs


Le programme éxecutable généré par le compilateur est utilisé dans cette étape pour
tester le fonctionnement du programme. On devra effectuer plusieurs tests
corréspondant à plusieurs scénarios et vérifier la validité des résultats. Si jamais il
y'a des erreurs (bugs) des corrections doivent être apportés au programme source
qui doit être recompilé et le test doit être lui aussi refait.

3 Applications
3.1 Application qui calcule la somme de 2 Nombres
L'utilisateur donne 2 nombres, on calcule la somme de ces 2 nombres et on
l'affiche.
Entrée: 2 Nombres Nbr1 et Nbr2
Sortie: la somme S
Traitement:
Lire les 2 nombres Nbr1 et Nbr2
Calculer la somme S <--- Nbr1 + Nbr2
Afficher S

Organigramme:

3.2 Application qui calcule la moyenne de 3 Nombres.


Entree: 3 Nombres Nbr1, Nbr2 et Nbr3
Sortie: Moyenne Moy
Traitement
Lire les Nombres Nbr1, Nbr2 et Nbr3
Calculer la moyenne Moy <--- (Nbr1 + Nbr2 + Nbr3)/3
Afficher la moyenne Moy

Organigramme:
3.3 Application qui lit 2 nombres et affiche le maximum
Entree: 2 Nombres Nbr1 et Nbr2
Sortie: le maximum max
Traitement
Lire les 2 nombres Nbr1 et Nbr2
Calculer le maximum max (comparer Nbr1 et Nbr2 et mettre le plus grand dans
max)
Afficher max

Organigramme:

3.4 Application où l'utilisateur donne une suite de nombres réels l'un après l'autre.
Chaque fois qu'il donne un nombre si ce nombre n'est pas égale à 0 on l'affiche. Si
le nombre est égale a 0 on s'arrête, on n'affiche pas le 0. Et on fait la même chose
pour le prochain nombre, c'est à dire si le nombre n'est pas égale à 0 on l'affiche
sinon on s'arrête.

Exemple:
L'utilisateur donne 2.5 on doit afficher 2.5
Il donne -3.4 on doit afficher -3.4
Il donne 11.7 on doit afficher 11.7
Il donne -19.3 on doit afficher -19.3
Il donne 15.3 on doit afficher 15.3
Il donne 0 on s'arrête.

Remarquons d'abord que lorsqu'on lit la première valeur on l'affiche


immédiatement et ensuite on lit la seconde valeur et on l'affiche immédiatement;
donc chaque fois qu'on lit une valeur on l'affiche immédiatement et on n'a plus
besoin de cette valeur donc on peut utiliser une seule variable en entrée (on vas
l'appeler Nbr) pour lire chacune des valeurs et l'afficher immediatement après avoir
lu cette valeur.
Donc l'exemple ci-dessus devient:
On lit Nbr=2.5, on afficher Nbr=2.5
On lit Nbr=-3.4, on afficher Nbr=-3.4
On lit Nbr=11.7, on afficher Nbr=11.7
On lit Nbr=-19.3, on afficher Nbr=-19.3
On lit Nbr=15.3, on afficher Nbr=15.3
On lit Nbr=0 on s'arrête.

Remarqu'on aussi qu'on fait la même chose pour tous les nombres, c'est à dire on lit
le nombre on teste si le nombre est égale à 0 (on a une répétition). Si c'est le cas on
s'arrête. Sinon on affiche le nombre et on refait exactement la même chose avec le
prochain nombre.

Traitement:
1- Lire Nbr
2- Tester si Nbr est = 0 et si c'est le cas s'arrêter
3- Si Nbr n'est pas égale a 0
- Afficher Nbr
- Revenir à 1 pour faire la même chose avec le prochain nombre

Remarquons ici on ne sait pas combien de nombres réels l'utilisateur va donner,


tout ce qu'on sait c'est que dés qu'il donne un 0 on s'arrête (on a des répétitions mais
on ne connait pas le nombre de répétitions)..

Organigramme:

3.5 Application où l'utilisateur donne un entier N, ensuite donne N nombres réels et


à chaque fois que l'utilisateur rentre un des N nombres réels on doit afficher ce
nombre.
Exemple:
L'utilisateur donne N=4 (donc il doit donner par la suite 4 nombres réels)
Il donne 2.5 on doit afficher 2.5
Il donne -3.4 on doit afficher -3.4
Il donne 11.7 on doit afficher 11.7
Il donne 15.3 on doit afficher 15.3 et on s'arrête car c'est le 4eme nombre (le
dernier).
Remarquons qu'on fait la même chose pour chacun des N nombres réels, c'est à dire
on lit le nombre et on l'affiche (on a une répétition) donc on va utiliser une seule
variable Nbr pour lire chaque fois un de ces nombres et l'afficher. Aussi après avoir
lu le Nème nombre et après l'avoir affiché on s'arrête, donc on a besoin de compter
combien de nombres on a lu et afficher et après le Nème on s'arrête. Donc on a
besoin d'une variable comme compteur pour cela. On va initialiser cette variable à
1 et on ajoute 1 (on l'incrémente) après avoir lu et afficher un nombre et dés que
cette variable dépasse N on s'arrête. Donc le traitement est le suivant:
1- Lire N
2- Initialiser le compteur i à 1
3- Voir si i est plus petit ou égale à N et dans ce cas
3.1 Lire Nbr
3.2 Afficher le Nbr
3.3 Ajouter 1 à i
3.4 Revenir à 3 pour traiter le prochain nombre (ou bien s'arrèter)
4- Dés que i devient supèrieur à N on s'arrête

Remarquons que ajouter 1 à i revient à prendre l'ancienne valeur de i, lui ajouter 1


et mettre ça dans i, c'est à dire qu'on ecrit: i <--- i + 1.

Contrairement à l'application précédente ici on sait combien de nombres réels


l'utilisateur va donner (N nombres réels), on a des répétitions et on connait le
nombre de répétitions (N).

Organigramme:

Exercices
Ecrire les organigrammes des applications suivantes:
- Lit 2 nombres a et b et résout l'equation ax + b = 0
- Lit 3 Nombres et affiche le maximum.
- Lit un entier N, puis lit N nombres réels, calcule la somme de ces N nombres réels
et affiche cette somme.
- Lit une suite de nombres réels, calcule la somme des nombres strictement
supèrieur à 0, calcule la somme des nombres strictement inférieur à 0, s'arrête
lorsque le nombre donné est égale à 0 et affiche les 2 sommes.

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Le Langage Algorithmique

1- Les expressions
1.1 Les Expressions Arithmétiques
Une Expression arithmétique est une combinaison d'opérandes de type arithmétique
et d’opérateurs arithmétiques.
Un opérande peut être une valeur, une constante ou une variable.

Opérations Utilisées:
Operation Symbole
Addition +
Soustraction -
Multiplication *
Division Réelle /
Division Entière Div
Modulo (reste de la division entière) Mod

La division entière donne comme résultat le quotient entier de la division entière


tandis que la division réelle donne le quotient réel de la division réelle.
Par exemple:
10 Div 4 = 2 alors que 10 / 4 = 2.5
20 Div 6 = 3 alors que 20 / 6 = 3.33
6 Div 8 = 0 alors que 6 / 8 = 0.75
Le Mod est le modulo, c.a.d le reste de la division entière.
Exemples: 10 Mod 4 = 2, 20 Mod 6 = 2, 6 Mod 8 = 6

Remarque
On ne peut utiliser Div et Mod qu'avec des entiers. On ne peut pas écrire par
exemple 2.3 Div 1.2 ou bien 6.4 Mod 2.

Il faut noter qu'en algorithmique les expressions s’écrivent sous forme linéaire (sur
une ligne).
Exemple:

s’ecrit en algorithmique: (X + Z) / (2 * Y)

B2 - 4 AC s’ecrit en algorithmique (B * B) – (4 * A * C)

Priorité des Opérations Arithmétiques


La table ci-dessous montre la priorité des opérations arithmétiques par ordre
décroissant. Les parenthèses sont les plus prioritaires, ensuite viennent les
opérations *, /, Div et Mod et enfin les opérations + et -.
Symbole
()
* / Div Mod
+ -

Evaluation des expressions arithmétiques


L’evaluation d’une expression arithmétique consiste à calculer au fur et à mesure
les résultats des calculs jusqu’a obtenir le résultat finale. Cela se fait en plusieurs
étapes. La première étape est d’ajouter les parenthèses (si l’expression ne comporte
pas de parenthèse) pour qu’il n y’ait aucune ambiguité. Ensuite il faut remplacer les
identifiants (c'est à dire les noms) des variables et des constantes de type
arithmétique par leur valeur. Enfin il faut evaluer étape par étape chacune des sous-
expression en commençant par les sous-expressions qui sont dans les parenthèses
les plus internes.

Remarque
Lorqu’on ajoute des parenthèses on fait cela en tenant compte de la priorité des
opérateurs. Si les opérateurs ont même priorité on évalue de gauche à droite.

Exemples d’evaluation
Soit l’expression:

pour X = 1, Y = 2 et Z = 3

1) Transformer l’expression sous-forme linéaire: (X + (2 * Y)) / (Y + Z)


2) Remplacer les identificateurs par leur valeur, l’expression devient: (1 + ( 2 *
2)) / (2 + 3)
2) Evaluer (2 * 2), l’expression devient: (1 + 4) / (2 + 3)
3) Evaluer (1 + 4), l’expression devient: 5 / (2 + 3)
4) Evaluer (2+ 3), l’expression devient: 5 / 5
5) Evaluer (5 / 5), l’expression devient: 1

Soit l’expression:
B2 – 4 AC pour A=2, B=8 et C=4

1) Transformer l’expression sous-forme linéaire: (B * B) – ( (4 * A) * C)


2) Remplacer les identificateurs par leur valeur, l’expression devient: (8 * 8) – ((4 *
2) * 4)
2) Evaluer (4 * 2), l’expression devient: (8 * 8) – (8 * 4)
3) Evaluer (8 * 8), l’expression devient: 64 – (8 * 4)
4) Evaluer (8 * 4), l’expression devient: 64 – 32
5) Evaluer (64 – 32), l’expression devient: 32

Remarque
Dans un algorithme et pour éviter toute ambiguité utiliser des parenthèses lorsqu'on
a des expressions complexes.

1.2 Les Expressions Logiques (Booléennes)


Une expression logique est une combinaison de variables de type booléen et
d’opérateurs booléens (NOT, AND , OR). Une variable de type booléen ne peut
prendre que 2 valeurs: True (Vrai) ou False (Faux)

Table de Verite
X Y X OR Y X AND Y NOT X NOT Y
True True True True False False
True False True False False True
False True True False True False
False False False False True True

Priorité des Opérateurs


La table ci-dessous montre la priorité des opérations aritmétiques par ordre
décroissant.
()
NOT
AND
OR

Evaluation des Expressions Logiques


Comme pour les expressions arithmétiques, il faut d’abord ajouter les parenthèses
(s’il n’y a pas de parenthèses) en tenant compte de la priorité des opérateurs.
Ensuite remplacer les identificateurs par leur valeur et évaluer les sous-expressions
étape par étape.

Exemples:
Soit l’expression: A AND NOT B avec A = True et B = False
1) Ajouter des parenthèses, l’expression devient: A AND (NOT B)
2) Remplacer les identificateurs par leur valeur, l’expression devient: True AND
( NOT False)
3) Evaluer (NOT False), l’expression devient: True AND True
4) Evaluer Vrai AND Vrai, l’expression devient: True

Soit l’expression: A AND B OR C AND D avec A = True , B = False, C = True et


D = True
1) Ajouter des parenthèses, l’expression devient: (A AND B) OR (C AND D)
2) Remplacer les identificateurs par leur valeur: (True AND False) OR (True AND
True)
3) Evaluer (True AND False), l’expression devient: False OR (True AND True)
4) Evaluer True AND True, l’expression devient: False OR True
5) Evaluer False OR True, l’expression devient: True

1.3 Les Opérateurs de Comparaison


On utilisera les symboles suivants comme opérateurs de comparaison.
Egalité: =
Inférieur: <
Inférieur ou égale: <=
Supèrieur: >
Supèrieur ou égale: >=
Différent: <>

Remarque:
Si on a 2 nombres A et B alors:
NOT(A < B) = (A >= B)
NOT(A > B) = (A <= B)
NOT(A <= B) = (A > B)
NOT(A >= B) = (A < B)
Si on a 2 conditions C1 et C2 alors:
NOT(C1 AND C2) = NOT(C1) OR NOT(C2)
NOT(C1 OR C2) = NOT(C1) AND NOT(C2)

2- Structure Générale d’un Algorithme

2.1 Syntaxe
Algorithm <idf_algo>;
Const
<declaration_constantes>
Var
<declaration_variables>
Begin
<partie_instructions>
End.

<idf_algo> est l’identficateur (le nom) de l’algorithme. Un identificateur est une


suite de caractères alphanumériques qui comporte au moins un caractère, dont le
premier caractère est une lettre et les caractères qui suivent (s'il y'en a) sont soit une
lettre, soit un chiffre, soit le caractère souligné (_). Un identificateur ne doit pas
contenir de caractère blanc (espace), ça doit être un seul mot.

Remarques
1) Algorithme, Const, Var, ... sont des mots réservés. Ne Pas utiliser ces mots
comme identificateurs.
2) Contrairement au langage C, on considère que les lettres minuscules et les lettres
majuscules representent le même identificateur (exemple: I et i est le même
identificateur).

2.2 Déclaration des Constantes


Une constante est une entité dont la valeur ne change pas lors du déroulement de
l’algorithme.
Syntaxe
<idf_constante> = <valeur>;

Exemple:
Const
PI = 3.14;

Avantages d’utilisation d’une constante


-- Si pour une raison donnée on veut modifier la constante on n’a qu’a modifier
la valeur de la constante une seule fois.
-- Lisibilité de l'algorithme: le nom de la constante permet une meilleure
lisibilité de l'algorithme.

2.3 Déclaration des Variables


Une variable est une entité dont la valeur peut changer au cours de l'éxecution de
l’algorithme.
Une variable a un type. Le type définie l'ensemble des valeurs que la variable peut
prendre.
Les types de base que l'on va utiliser sont:

Integer La valeur appartient à l’ensemble des entiers relatifs Z. Syntaxe :


[+/-]<nombre> Exemple : +25, -12, 89….
Real La valeur appartient à l’ensemble des réels R Syntaxe :
[+/-]<partie entière>.<partie fractionnaire>
Exemple : +123.5, -21.14, 11.2
Boolean La valeur prend True (Vrai) ou False (Faux)
Character La valeur prend un caractère de l’ensemble alphabétique {'A', 'B',
'C', ..'Z', 'a',…'z'} ou numérique {'0','1','2','3','4','5','6','7','8','9'} ou
caractère spécial {'*','+','/', '?','<','>'…} Exemple : ‘A’, ‘c’, ‘3’,’ ?’

Pour les caractères on considère que ces derniers sont codés en code ASCII (sur 8
bits) (ASCII: American Standard Code for Information Interchange).
Le caractère ‘0’ est codé comme 0x30 (0x veut dire héxadécimale), ‘1’ est codé
comme 0x31, .... le caractère ‘9’ est codé comme 0x39, le caractère ‘A’ est codé
comme 0x41, ‘B’ est codé comme 0x42,..., ‘a’ est codé comme 0x61, ‘b’ est codé
comme 0x62, ...
Noter que l’on peut ainsi comparer les caractères entre eux on a:
‘0’<’1’<...<’9’<’A’<’B’<...<'Z'<’a’<’b’<...<’z’

Syntaxe
<idf_variable> : <type>;

<idf_variable> est l'identificateur (le nom) de la variable.


<type>: Integer, Real, Boolean ou Character.

Exemple:
Age: Integer
Moyenne: Real;
Section: Character;

Remarques
1) Il est trés important de bien choisir les noms des variables (dépendemment à
quoi servent ces variables). Cela permet une meilleur lisibilité de l'algorithme (il en
est de même pour les noms des constantes et du nom de l'algorithme).
2) Si on a plusieurs variables de même type on peut les déclarer sur une seule ligne:
Exemple: X, Y, Z: Integer;
3) Il faut déclarer dans la partie déclaration des variables (<declaration_variables>)
toutes les variables utilisées dans la partie instructions (<partie_instructions>).

2.4 Partie Instructions


Dans la partie instructions les instructions s'éxecutent en séquence (l'une après
l'autre) dans l'ordre où elles sont écrites.

Si la partie instruction contient:


Debut
<inst 1>
<inst 2>
<inst 3>
...
<inst n>
Fin

alors lorsque l'algorithme s'éxecute il commence par <inst 1>. A la fin de


l'instruction <inst 1>, on éxecute <inst 2>, ensuite <inst 3> et ainsi de suite jusqu'à
<inst n>.

2.4.1 L'Instruction d'Affectation


Syntaxe:
<idf_variable> <-- <expression>;

<idf_variable> est l'identificateur (nom) de la variable.


L'instruction d'affectation consiste à affecter (mettre) la valeur d'une expression
dans une variable.
Physiquement cela consiste à mettre la valeur de l'expression dans l'emplacement
mémoire de la variable.
<expression> peut être:
- une valeur (entier, reelle, caractère ou booléenne)
- le nom d'une constante
- le nom d'une variable
- une expression arithmétique ou logique

Remarques
1) Il faut que la valeur affectée soit du même type que la variable à laquelle
l'instruction d'affectation est effectuée.
Exemples:
Soit: Var
Age: Integer;
Age <-- 15; correct
Age <-- 2.5; erreur
Age <-- 'A'; erreur
Soit Var
X, Y: Integer;
car: Character;

X <-- Y; correct
X <-- car; erreur
car <-- X; erreur

Le seul cas où les types ne sont pas les même est: var_reelle <-- entier;
2) Le membre à gauche d'une affectation ne peut pas être une constante ou une
valeur.
Const
X = 100;

X <-- 200; erreur


12 <-- 25; erreur
3) Lorsqu'on affecte une expression qui a une valeur val à une variable v la variable
v prend la valeur val et on perd ce que v contenait auparavant.
Exemple:
v <--- 2;
v <--- 27; /* v prend la valeur 27 et perd la valeur 2 (on écrase v avec la valeur
27) */
4) Il faut toujours penser à initialiser une variable. Au début de l'éxecution de
l'algorithme les variables contiennent n'importe quoi.

2.4.2 Les Instructions d'Entrées/Sorties (E/S)


Lecture:
Read(var); lit une variable
Read(var1, var2, ..., varn);
Cette instruction récupere la valeur rentrée au clavier et l'affecte à la variable.
Physiquement la valeur rentrée au clavier est mise dans l'emplacement mémoire de
la variable.

Ecriture:
Write(<expression>);
Affiche la valeur de l'expression sur écran.

Exemples:
Write(12); affiche sur écran la valeur 12
Write("Entrer un Entier"); affiche sur écran le message: Entrer un Entier

si X variable entière contient par exemple 15 et Y variable entière contient par


exemple 25.
Write(X); affiche sur écran la valeur de X qui est dans ce cas 15
Write(Y + 3) ; affiche dans ce cas la valeur 28
Write("La Valeur de X = ", X, " et la Valeur de Y = ", Y);
affiche sur écran: La Valeur de X = 15 et la Valeur de Y = 25

2.4.3 Les Instructions de Contrôle


Ces instructions testent une condition et éxecutent des actions suivant le résultat du
test.
Il y'a 3 types d'instruction de contrôle:
(if ... then ... eif)
(if ... then ... else ... eif)
(case ... of ... ecase)
2.4.3.1 Instruction (if ... then ... eif)
Syntaxe
If <condition> then
<bloc_instructions_then>
EIf

Si <condition> est vrai alors le <bloc_instruction_then> est éxecuté. Après


éxecution de la dernière instruction du <bloc_instruction_then> on passe à la
première instruction après le EIf.
Si <condition> est fausse alors <bloc_instruction_then> n'est pas éxecuté et on
passe immédiatement à la première instruction après le EIf.
L'organigramme corréspondant est montré ci-dessous:

Exemple
Ecrire un algorithme qui étant donné un nombre réel X met dans X la valeur
absolue de X et l'affiche.

Algorithm ValAbsReel;
Var
X : Real;
Begin
Write("Donner un Nombre Reel X");
Read(X)
If (X < 0) then
X <-- - X ;
EIf
Write("Valeur Absolue de X: ", X);
End.

2.4.3.2 Instruction (if ... then ... else ... eif)


Syntaxe
If <condition> then
<bloc_instructions_then>
Else
<bloc_instructions_else>
EIf
Si <condition> est vrai alors le <bloc_instruction_then> est éxecuté. Apres
éxécution de la dernière instruction du <bloc_instruction_then> on passe à la
première instruction après le EIf (le <bloc_instruction_else> n'est pas éxecuté).
Si <condition> est fausse alors <bloc_instruction_else> est éxecuté. Après
éxecution de la dernière instruction du <bloc_instruction_else> on passe à la
première instruction après le EIf (le <bloc_instruction_then> n'est pas éxecuté).
L'organigramme corréspondant est montré ici-bas.

Exemple
Ecrire un algorithme qui étant donné 2 nombres entiers N1 et N2 nous indique le
maximum de ces 2 nombres.
Algorithm MaxN1N2;
Var
N1, N2, max: Integer;
Begin
Write("Donner 2 Nombres Entiers N1 et N2");
Read(N1, N2)
If (N1 > N2) then
max <--- N1;
Else
max <--- N2;
EIf
Write("Maximum de ", N1, "et ", N2, " est: ", max);
End.

Remarque:
On peut dans certains cas (cas où les instructions entre alors et sinon ne modifient
pas la condition) écrire l'ínstruction:
If (condition) then ... else ... EIf
comme deux If indépendants en séquence:
If (condition) then ... EIf
If (NOT(condition)) then ... EIf
mais l'execution prendra plus de temps car la condition sera evaluée 2 fois et le
programme ne sera pas trés performant; donc toujours utiliser un If avec un Else
(plutôt que des If indépendants) dans le cas où on doit traiter le cas où la condition
est Vrai et le cas où la condition est fausse). De même utliser des If imbriqués dans
le cas où on a une imbrication des conditions plutôt que des If indëpendants (Voir
If Imbriqués).

Comme par exemple l'algorithme précédent peut être écrit comme:


Algorithm MaxN1N2;
Var
N1, N2, max: Integer;
Begin
Write("Donner 2 Nombres Entiers N1 et N2");
Read(N1, N2)
If (N1 > N2) then
max <--- N1;
EIf
If (N1 <= N2) then
max <--- N2;
EIf
Write("Maximum de ", N1, "et ", N2, " est: ", max);
End.

If Imbriqués
On a des If imbriqués lorsqu'on a des If à l'intérieur d'autres If.

Exemples
1) Ecrire un algorithme qui étant donné 2 nombres entiers N1 et N2 , si N2 est
égale à 0 affiche un message d'erreur sinon indique si N1 est un multiple de N2 ou
non. Utiliser l'opération Modulo Mod.

Algorithm MultipleOuNon;
Var
N1, N2, Reste: Integer;
Begin
Write("Donner 2 Nombres Entiers N1 et N2");
Read(N1, N2)
If (N2 = 0) then
Write(" N2 est egale a 0");
Else
Reste <-- N1 Mod N2;
If (Reste = 0) then
Write(N1, " est un multiple de ", N2);
Else
Write(N1, " N'est PAS un multiple de ", N2);
EIf
EIf
End.

2) Ecrire un algorithme qui éant donné 3 nombres entiers a, b et c les ordonne par
ordre croissant.
Algorithm OrdreCroissant1;
Var
a, b, c: Integer;
Begin
Write("Donner 3 Nombres Entiers a, b, c");
Read(a, b, c)
If (a < b) then
If (c < a) then
Write(c, a, b);
Else
If (c > b) the
Write(a, b, c)
Else
Write(a, c, b)
EIf
EIf
Else
If (c < b) the
Write(c, b, a);
Else
If (c > a) then
Write(b, a, c);
Else
Write(b, c, a);
EIf
EIf
EIf
End.
Une solution plus simple est d'utiliser 2 autres variables Nb1 et Nb2, de mettre dans
Nb1 le plus petit par exemple de a et b et de mettre dans Nb2 le plus grand de a et b
de façon à avoir toujours Nb1 < Nb2; et ensuite de voir où se situe c par rapport à
Nb1 et Nb2 (plus petit que Nb1, entre Nb1 et Nb2 ou plus grand que Nb2).
Algorithm OrdreCroissant2;
Var
a, b, c, Nb1, Nb2: Integer;
Begin
Write("Donner 3 Nombres Entiers a, b, c");
Read(a, b, c)
If (a < b) then
Nb1 <--- a;
Nb2 <--- b;
Else
Nb1 <--- b;
Nb2 <--- a;
EIf
If (c < Nb1) then
Write(c, Nb1, Nb2);
Else
If (c < Nb2) then
Write(Nb1, c, Nb2)
Else
Write(Nb1, Nb2, c)
EIf
EIf
End.

3) Ecrire un algorithme qui étant donné 3 nombres nombres entiers a, b, c trouve le


maximum de ces 3 nombres entiers et l'affiche.

On peut écrire une solution un peu similaire à la solution 1 faite dans l'exemple 1
en distinguant tous les cas possible, mais si on réflechit un peu plus il y'a des
solutions plus simples.

Solution 1: pour trouver le max de 3 nombres, on peut checher le max de 2 de ces 3


nombres ensuite comparer ce max avec le 3ème nombre.
Algorithm Max3Nombres1;
Var
a, b, c, max: Integer;
Begin
Write("Donner 3 Nombres Entiers a, b et c");
Read(a, b, c);

If ( a > b) then
max <--- a;
Else
max <--- b;
EIf

If (c > max) then


max <--- c;
EIf
Write("Le maximum de ", a, " , ", b, " et ", c, " est: ", max);
End.

Solution 2: le max de a, b et c est soit a , soit b soit c. Le max est a si ((a >= b) et (a
>= c)). Si ce n'est pas a alors ça ne peut être que b ou c. C'est b si (b >= c). Si ce
n'est pas a et ce n'est pas b alors ça ne peut être que c.
Algorithm Max3Nombres2;
Var
a, b, c, max: Integer;
Begin
Write("Donner 3 Nombres Entiers a, b et c");
Read(a, b, c);

If ( (a >= b) and (a >= c)) then


max <--- a;
Else
If (b >= c) then
max <--- b;
Else
max <--- c;
EIf
EIf

Write("Le maximum de ", a, " , ", b, " et ", c, " est: ", max);
End.

Remarque: Lorsqu'on ecrit écrit un algorithme il faut toujours essayer d'adopter


une solution qui est simple.

2.4.3.3 Instruction (Case ... Of ... ECase)


Syntaxe
Case <var> Of
val1: <bloc_inst_Val1>
val2: <bloc_inst_Val2>
...
valN: <bloc_inst_ValN>
[Else <bloc_inst_else>]
ECase

Etant donné une variable ayant comme nom var et plusieurs valeurs val1, val2, ....,
valN que peut prendre cette variable, cette instruction permet d'éxecuter un bloc
d'instructions correspondant à une valeur donnée si la variable est égale à cette
valeur. L'ordre des tests si la variable est égale à une valeur est l'ordre dans lequel
les valeurs sont écrites. Noter que la clause sinon n'est pas obligatoire (optionnelle).
Si la variable est différente de toutes les valeurs specifiées et que la clause sinon est
présente le bloc <bloc_instruction_else> est éxecuté; si la clause sinon n'est pas
présente aucun bloc d'instructions n'est executé dans ce cas et on passe directement
à la première instruction après le FinCas.
Noter que la variable peut être de type Entier ou de type Caractère uniquement. Le
valeurs doivent être du même type que la variable, c'est à dire si la variable est de
type Entier les valeurs citées doivent être entières et si la variable est de type
caractère les valeurs citées doivent être des caractères.

L'organigramme correspondant est montre ici-bas.


Remarque
A partir de l'organigramme on peut voir que l'instruction (case ... of) équivaut à des
If imbriqués dans lesquels les conditions utilisées sont les conditions d'égalité.
On ne peut pas utiliser un (case ... of) à la place des If imbriques lorsque ces If
imbriqués n'utilisent pas la condition d'égalité (par exemple on a des If imbriqués
avec des < ou bien <=). .

Exemple
Ecrire un algorithme qui étant donné 2 nombres réels a et b et un caractère opr
calcule et affiche a+b si opr est '+', a-b si opr est '-', a*b si opr est '*', a/b si opr est '/'
(avec b#0) sinon affiche un message d'erreur comme opération inconnue.

Algorithm Calculatrice;
Var
a, b: Real;
opr: Character;

Begin
Write("Entrer 2 Nombres Reels a et b");
Read(a, b)
Write("Entrer votre operation");
Read(opr);
Case opr Of
'+': Write(a, "+", b, " = ", a + b);
'-': Write(a, "-", b, " = ", a - b);
'*': Write(a, "*", b, " = ", a * b);
'/': If (b = 0) then
Write("Erreur b est egale a 0");
Else
Write(a, "/", b, " = ", a / b);
EIf
Else
Write("Erreur dans le choix de l'operation");
ECase
End.

Ici-bas est l'algorithme équivalent en utilisant des If imbriqués.

Algorithm Calculatrice;
Var
a, b: Real;
opr: Character;
Begin
Write("Donner 2 Nombres Reels");
Read(a, b)
Write("Entrer votre operation");
Read(opr);
If (opr = '+') then
Write(a, "+", b, " = ", a + b);
Else
If (opr = '-':) then
Write(a, "-", b, " = ", a - b);
Else
If (opr = '*') then
Write(a, "*", b, " = ", a * b);
Else
If (opr = '/') then
If (b = 0) then
Write("Erreur b est egale a 0");
Else
Write(a, "/", b, " = ", a / b);
EIf
Else
Ecrire("Erreur dans le choix de l'operation");
EIf
EIf
EIf
EIf
End.

Remarque
On peut voir à travers l'exemple ci-dessus qu'un algorithme écrit avec un (case ...
of) est beaucoup plus lisible qu'un algorithme écrit avec des If imbriqués.

Case ... Of pour exprimer un OU


Lorsqu'on a un ou plusieurs cas où on éxecute le même bloc d'instructions lorsque
l'expression est égale à plus d'une constante, on exprime le OU avec une ","
virgule.
Exemple
Ecrire un algorithme qui étant donné le numero du mois donne la saison
corréspondante. Si par exemple le numéro du mois est 6, 7 ou 8 (juin, juillet ou
aout) l'algorithme affiche été.
Algorithm Saison;
Var
mois: Integer;
Begin
Write("Donner le Numero du mois");
Read(mois);
Case mois Of
3, 4, 5: Write("Printemps");
6, 7, 8: Write("Eté");
9, 10, 11: Write("Automne");
12, 1, 2: Write("Hiver");
Else: Write("Erreur: Numero du Mois doit etre compris entre 1 et 12");
ECase
End.

2.4.4 Les Instructions Itératives (Répétitives)


Souvent un programme doit faire le même traitement plusieurs fois. Un éxemple
serait de calculer le salaire des employés d'une même compagnie. Pour cela on
utilise une structure itérative. Il existe 3 types de repétitions: boucle Pour, boucle
Tant Que et boucle Repeter.

2.4.4.1 Boucle For


Permet d'éxecuter de manière repetée des actions un nombre de fois prédeterminé.
On connait le nombre de repétitions.

Syntaxe
For <compteur> <-- <exp_debut> to <exp_fin> Do
<bloc_inst_for>
Done

<compteur> est une variable qui compte le nombre de répétitions.


La structure Pour fonctionne comme suit:
1- la variable compteur est initialisée à <exp_debut>
2- Si compteur<=exp_fin alors
le <bloc_inst_for> est éxécuté,
est automatiquement ajouté 1 au compteur
et on retourne à l'instruction 2
Sinon (c'est à dire compteur > exp_fin)
on sort de la boucle For (et on vas à la première instruction après le
Done).
L'organigramme corréspondant est montré ici-bas.
Remarques
1) On execute <bloc_inst_for> un nombre égale à (<exp_fin> - <exp_debut> + 1).
2) La variable compteur est automatiquement incrementée. Ne jamais modifier la
variable compteur à l'intérieur d'une boucle Pour.
3) Si dés le début on a exp_debut > exp_fin on n'éxécute aucune itération. Donc
pour rentrer la première fois dans la boucle il faut avoir exp_debut <= exp_fin.

Exemples
1) Algorithme qui étant donné un entier N > 0 donné par l'utilisateur affiche le mot
"Bonjour" N fois.

Algorithm NBonjour;
Var
i, N: Integer;
Begin
Write("Donner un Entier N > 0");
Read(N);
For i <-- 1 to N Do
Write("Bonjour");
Done
End.
2) Algorithme qui étant donné un entier N > 0 donné par l'utilisateur et N nombres
réels donnés aussi par l'utilisateur calcule et affiche la valeur absolue de chacun
des nombres réels.

Algorithm ValAbsolueNReels;
Var
i, N: Integer;
Nbr, ValAbs: Real;
Begin
Write("Donner un Entier N > 0");
Read(N);
For i <-- 1 to N Do
Write("Donner le ", i, " eme nombre reel");
Read(Nbr);
If (Nbr >= 0) then
ValAbs <--- Nbr;
Else
ValAbs <--- - Nbr;
EIf
Write("La Valeur Absolue de ", Nbr , " est egale a ", ValAbs);
Done
End.

3) Algorithme qui étant donné un entier N > 0 donné par l'utilisateur calcule et
affiche la somme des N premiers nombres entiers (1+2+3+...+N).

Algorithm SommeNPremNbr;
Var
i, N, Somme: Integer;
Begin
Write("Donner un Entier N > 0");
Read(N);
Somme <-- 0;
For i <-- 1 to N Do
Somme <-- Somme + i;
Done
Write("La Somme des ", N, " premiers entiers = ", Somme);
End.

4) Algorithme qui étant donné un entier N >= 0 donné par l'utilisateur calcule et
affiche factoriel de N.

Algorithm Factoriel;
Var
i, N, fact: Integer;
Begin
Write("Donner un Entier N >= 0");
Read(N);
fact <-- 1;
For i <-- 1 to N Do
fact <-- fact * i;
Done
Write(N, "! = ", fact);
End.

2.4.4.2 Boucle While


Il y'a des situations où on ne connait pas le nombre de fois qu'on veut répéter
certaines actions. On éxécute et on repète ces actions tant qu'une condition est vrai.
Dés que la condition devient fausse on arrête les répétitions et on sort de la boucle
While.

Syntaxe
While (<condition>) Do
<bloc_inst_while>
Done

L'organigramme corréspondant est montré ici-bas.

Remarques:
1) Il faut que la condition soit mise à faux à l'intérieur de la boucle à un moment
donné pour pouvoir sortir de la boucle While (si au début la condition est vrai). Si
la condition est toujours Vrai on a une boucle infinie (erreur de logique).
2) Si dés le debut la condition est fausse les instructions à l'intérieur de la boucle
While ne sont jamais éxecutées.
3) On peut toujours transformer une boucle For en une boucle While. L'inverse
n'est pas toujours vrai.

Exemples
1) Soit un utilisateur qui rentre des caractères au clavier. Ecrire un algorithme qui
compte le nombre de lettres rentrés par l'utilisateur. Arrêter le comptage lorsque
l'utilisateur rentre le caractère '#'.

Solution 1: en utilisant une variable booléenne


Remarque
Dans cette solution on initialise la variable booléene (dernierCar) à False et dans ce
cas la condition qu'on teste dans le While doit être (dernierCar = False) pour rentrer
dans la boucle la premiere foix et ainsi lire le premier caractère. Dés que la
condition pour laquelle on veut s'arrêter et sortir de la boucle devient True à
l'interieur du While (condition Car = '#') on met le booléen à True pour que à la
prochaine itération lorsqu'on revient au While on trouve la condition (dernierCar =
False) false et ainsi on sort du While. Aussi on veut compter le nombre de
caractères qui sont des lettres de l'alphabet on utilise une variable qu'on vas appeler
nbrLettres qui vas servir de compteur de nombre de lettres. Cette variable sera
initialisée à 0 et chaque fois qu'on lit un caractère qui est une lettre, cette variable
sera incrementée.

Algorithm NbrCarLettres;
Var
car: Character;
nbrLettres: Integer;
dernierCar: Boolean;
Begin
nbrLettres <-- 0;
dernierCar <--- False;
While (dernierCar = False) Do
Write("Donner un Caractere");
Read(car);
If (car = '#') then
dernierCar <--- True;
Else
If ( ((car >= 'a') and (car <= 'z')) or ((car >= 'A') and (car <= 'Z')))
then
nbrLettres <-- nbrLettres + 1;
EIf
EIf
Done
Write("Le Nombre de Lettres = ", nbrLettres);
End.

Solution 2: sans utiliser de variable booléene


Remarque
Dans ce cas on utilise directement la condition (car <> '#') comme condition dans le
While. Bien sûr il faut dans ce cas que la variable car aie une valeur la première
fois et ainsi on lit le premièr caractère avant le While. Après avoir traiter chaque
caractère dans la boucle on lit le caractère suivant. Une troisième solution serait
d'affecter à la variable car une valeur différente de '#' avant le While pour rentrer
dans la boucle la première fois et faire un Read(car) au début du While.

Algorithm NbrCarLettres;
Var
car: Character;
nbrLettres: Integer;
Begin
nbrLettres <-- 0;
Write("Donner le Premier Caractere");
Read(car);
While (car <> '#') Do
If ( ((car >= 'a') and (car <= 'z')) or ((car >= 'A') and (car <= 'Z'))) then
nbrLettres <-- nbrLettres + 1;
EIf
Write("Donner le Caractere Suivant");
Read(car);
Done
Write("Le Nombre de Lettres = ", nbrLettres);
End.

2) Ecrire un algorithme qui étant donné un entier N donné par l'utilisateur calcule et
affiche la somme des N premiers nombres entiers (1+2+3+...+N) en utilisant la
boucle While.
Cet éxemple montre comment utiliser un While à la place d'un For.

Algorithm SommeNPremNbr;
Var
i, N, Somme: Integer;
Begin
Write("Donner un Entier N");
Read(N);
Somme <-- 0;
i <-- 1;
While (i <= N) Do
Somme <-- Somme + i;
i <-- i + 1;
Done
Write("La Somme des ", N, " premiers entiers = ", Somme);
End.

3) Ecrire un algorithme qui lit au maximum N caractères et qui compte le nombre


de voyelles minuscules. On s'arrête lorsque l'utilisateur rentre N caractères ou
lorsque l'utilisateur rentre le caractère 'Z'.

Algorithm NbrVoyelles;
Var
car : Character;
i, nbrV : Integer;
carZ: Boolean;
Begin
Write("Donner un Entier N > 0");
Read(N);
nbrV <-- 0;
i <-- 1;
carZ <-- False;
While ( (i <= N) and (carZ = False) ) Do
Write("Entrer un Caractere");
Read(car);
Case car Of
'a', 'o', 'e', 'i', 'u', 'y':
nbrV <--- nbrV + 1;
'Z' : carZ <--- True;
ECase
i <-- i + 1;
Done
Write("Le Nombre de Voyelles = ", nbrV);
End.

2.4.4.3 Boucle Repeat


Dans l'instruction While la condition est testée avant d'éxecuter les actions à
l'interieur du While. Dans ce cas si la condition dés le début est fausse ces actions
ne sont jamais executées.
L'instruction Repeat permet au contraire d'executer d'abord ces actions avant de
tester la condition. Les actions à l'interieur de la boucle Repeat sont repetées jusqua'
ce que la condition devienne vrai; c'est à dire qu'on repète ces actions tant que la
condition est fausse et on s'arrête lorsque la condition devient vrai.
Syntaxe
Repeat
<bloc_inst_repeat>
Until (<condition>);

L'organigramme corréspondant est montré ici-bas.

Remarques
1) Dans une boucle Repeat les actions à l'interieur du Repeat sont executées au
moins une fois.
2) On peut toujours transformer un Repeat comme un While. L'inverse n'est pas
toujours vrai. La condition d'un While est le contraire de la condition du Repeat.
3) Dans une boucle Repeat le nombre de répétitions n'est pas forcément connu.

Exemples
1) Ecrire un algorithme qui lit un entier N d'un utilisateur mais accepte uniquement
un N >= 1. Si l'utilisateur rentre un N < 1, l'algorithme demande à l'utilisateur de
donner une autre valeur pour N. Par la suite l'algorithme affiche le N donné.

Algorithm NSupEgale1;
Var
N: Integer;
Begin
Repeat
Write("Donner un Entier N>=1");
Read(N);
Until (N>=1);
Write("Valeur de N Donnee ", N);
End.

2) Ecrire un algorithme qui lit un nombre inconnu de caractères et qui compte le


nombre d'occurrences (d'apparitions) de chacun des caractères 'a', 'b' et 'c'. On
s'arrête lorsqu'on lit le caractère '#'.

Algorithm nbrOccABC;
Var
nba, nbb, nbc: Integer;
car : Character;
Begin
nba <-- 0;
nbb <-- 0;
nbc <-- 0;
Repeat
Write("Donner un Caractere");
Read(car);
Case car Of
'a': nba <-- nba + 1;
'b': nbb <-- nbb + 1;
'c': nbc <-- nbc + 1;
End
Until (car = '#');
Write("Nombre de 'a' = ", nba);
Write("Nombre de 'b' = ", nbb);
Write("Nombre de 'c' = ", nbc);
End.

2.4.4.3 Boucles Imbriquées


Comme on a des If imbriqués on a aussi des boucles imbriquées.
Exemples
1) 2 Boucles For Imbriquées
Soit un utilisateur qui donne un entier N>0 ensuite donne N entiers (supposés >=
0). Ecrire un algorithme qui calcule et affiche le factoriel de chacun des N entiers.
La premiere boucle For lit les N entiers l'un à la suite de l'autre. La deuxieme
boucle For est pour calculer le factoriel de Nbr après avoir lu Nbr.

Algorithm FactorielNEntiers;
Var
i, J, N, Nbr, fact: Integer;
Begin
Write("Donner un Entier N>0");
Read(N);
For i<-- 1 to N Do
Write("Donner le ", i, " eme Nombre Entier Nbr >= 0");
Read(Nbr);
fact <-- 1;
For J<-- 1 to Nbr Do
fact <-- fact * J;
Done
Write("Factoriel de ", Nbr, " = ", fact);
Done
End.

2) Boucle For à l'intérieur d'une boucle While


Soit un utilisateur qui donne une suite de nombres entiers >= 0 qui se termine par
un entier < 0. Ecrire un algorithme qui calcule et affiche le factoriel de chacun des
entiers >= 0 et se termine lorsqu'on rencontre un entier < 0.
La premiere boucle While lit les entiers l'un à la suite de l'autre et qui se termine
lorsqu'on lit un entier < 0. La deuxième boucle For est pour calculer le factoriel de
Nbr après avoir lu Nbr.

Algorithm FactorielSuiteEntiers;
Var
i, Nbr, fact: Integer;
Begin
Write("Donner le premier Entier Nbr");
Read(Nbr);
While (Nbr >= 0) Do
fact <-- 1;
For i <-- 1 to Nbr Do
fact <-- fact * i;
Done
Write("Factoriel de ", Nbr, " = ", fact);
Write("Donner le Nombre Entier Suivant");
Read(Nbr);
Done
End.

3. Commentaires
Un commentaire est du texte qu'on utilise pour rendre un algorithme plus lisible.
On ajoute les commentaires surtout dans les portions du code qui peuvent être
difficiles à comprendre. Les commentaires ne sont pas pris en compte lors de la
compilation.
On utilisera la forme:
/* texte du commentaire */
ou bien la forme:
// tout ce qui suit jusqu'à la fin de la ligne courante est commentaire

Remarquons en utilisant la forme /* ... */ un commentaire peut être écrit sur


plusieurs lignes tandis qu'avec la forme // un commentaire est limité à la ligne
courante.

4. Lisibilité des algorithmes


Comme déja mentionné la lisibilité d'un algorithme est trés importante. Il y'a 3
choses qui rendent un algorithme plus lisible.
1) Le bon choix des noms de l'algorithme, des constantes et des variables (les
actions parametrées subroutines qu'on verra au chapitre 5) utilisés dans
l'algorithme.
2) L'ajout de commentaires.
3) La bonne indentation de l'algorithme. Les instructions qui viennent à l'interieur
d'un (If.. then), d'un For ou d'un While doivent être decalées à droite, de même pour
les instructions qui viennent après un Else. Les instructions qui s'éxecutent en
séquence doivent débuter sur la même colonne. Aussi écrire une instruction par
ligne.

5. Déroulement d'un algorithme (Trace d'un algorithme)


Dérouler un algorithme c'est éxecuter manuellement l'algorithme. Pour pouvoir
faire cela il faut donner des valeurs aux variables d'entrée. On donne à chaque
instruction un numéro et dans un tableau on met comme colonnes chacunes des
variables de l'algorithme (ainsi que l'ecran pour visualiser ce qui est affiché) et on
éxecute manuellement l'algorithme avec les données d'entrée choisies en mettant
sur chaque ligne le numéro de l'instruction qui s'éxecute et le contenu des variables
après éxecution de l'instruction (voir éxemples ici-bas).

Exemples
1) Dérouler l'algorithme suivant qui calcule la somme des N premiers nombres
entiers (l'algorithme utilise une boucle While) avec comme valeur de N = 4. On
devra trouver comme résultat (1+2+3+4) soit 10.

Algorithm SommeNPremNbr;
Var
i, N, Somme: Integer;
Begin
1) Write("Donner un Entier N");
2) Read(N);
3) Somme <-- 0;
4) i <-- 1;
5) While (i <= N) Do
6) Somme <-- Somme + i;
7) i <-- i + 1;
Done
8) Write("La Somme des ", N, " premiers entiers = ", Somme);
End.

Instruction i N Somme Ecran


1) ? ? ? Donner un Entier >=0
2) ? 4 ? Donner un Entier >=0
4
3) ? 4 0 Donner un Entier >=0
4
4) 1 4 0 Donner un Entier >=0
4
5) 1<=4 Vrai 1 4 0 Donner un Entier >=0
4
6) 1 4 1 Donner un Entier >=0
4
7) 2 4 1 Donner un Entier >=0
4
5)2<=4 Vrai 2 4 1 Donner un Entier >=0
4
6) 2 4 3 (1+2) Donner un Entier >=0
4
7) 3 4 3 (1+2) Donner un Entier >=0
4
5)3<=4 Vrai 3 4 3 (1+2) Donner un Entier >=0
4
6) 3 4 6 (1+2+3) Donner un Entier >=0
4
7) 4 4 6 (1+2+3) Donner un Entier >=0
4
5)4<=4Vrai 4 4 6(1+2+3) Donner un Entier >=0
4
6) 4 4 10(1+2+3+4) Donner un Entier >=0
4
7) 5 4 10(1+2+3+4) Donner un Entier >=0
4
5)5<=4Faux 5 4 10(1+2+3+4) Donner un Entier >=0
4
8) 5 4 10(1+2+3+4) Donner un Entier >=0
4
La Somme des 4 Premiers Entiers
= 10

2) Dérouler l'algorithme suivant qui calcule le factoriel de N avec N ayant la valeur


4. On devrait trouver comme résultat factoriel de 4=1*2*3*4 soit 24.

Algorithm Factoriel;
Var
i, N, fact: Integer;
Begin
1) Write(“Donner N Entier >= 0”);
2) Read(N);
3) fact <--- 1;
4) For i <--- 1 to N Do
5) fact <--- fact * i;
Done
6) Write(“Factoriel “, N, “ = “, fact);
End.

Instruction i N fact Ecran


1) ? ? ? Donner N Entier >= 0
2) ? 4 ? Donner N Entier >= 0
4
3) ? 4 1 Donner N Entier >= 0
4
4) Condition 1 4 1 Donner N Entier >= 0
I<=N (1<=4) Vrai 4
5) 1 4 1 (1*1) Donner N Entier >= 0
4
4) Condition 2 4 1 (1*1) Donner N Entier >= 0
I<=N (2<=4) Vrai 4
5) 2 4 2 (1*2) Donner N Entier >= 0
4
4) Condition 3 4 2 (1*2) Donner N Entier >= 0
I<=N (3<=4) Vrai 4
5) 3 4 6 (1*2*3) Donner N Entier >= 0
4
4) Condition 4 4 6 (1*2*3) Donner N Entier >= 0
I<=N (4<=4) Vrai 4
5) 4 4 24 (1 * 2 * 3 * Donner N Entier >= 0
4) 4
4) Condition 5 4 24 (1 * 2 * 3 * Donner N Entier >= 0
I<=N (5<=4) 4) 4
Fausse
6) 5 4 24 (1 * 2 * 3 * Donner N Entier >= 0
4) 4
Factoriel 4 = 24

3) Dérouler l'algorithme suivant qui calcule le quotient et le reste de la division


euclidienne de 2 entiers naturels A et B (B suppose different de 0). Prendre A=30 et
B=7.

Algorithm DivisionEuclidienne;
Var
A, B, Reste, Quot: Integer;
Begin
1) Write(“Donner 2 Entiers A et B, A>=0 et B>0”);
2) Read(A, B);
3) Reste <--- A;
4) Quot <---- 0;
5) While (Reste >= B) Do
6) Reste <--- Reste – B;
7) Quot <--- Quot + 1;
Done
8) Write(A, “ Divise par “, B, “ Quotient = “, Quot, “ et Reste = “, Reste);
End.

Instruction A B Reste Quot Ecran


1) ? ? ? ? Donner 2 Entiers A et B, A>=0 et
B>0
2) 30 7 ? ? Donner 2 Entiers A et B, A>=0 et
B>0
30 7
3) 30 7 30 ? Donner 2 Entiers A et B, A>=0 et
B>0
30 7
4) 30 7 30 0 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
5) 30>=7 Vrai 30 7 30 0 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
6) 30 7 23 0 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
7) 30 7 23 1 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
5)23>=7Vrai 30 7 23 1 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
6) 30 7 16 1 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
7) 30 7 16 2 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
5)16>=7Vrai 30 7 16 2 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
6) 30 7 9 2 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
7) 30 7 9 3 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
5)9>=7Vrai 30 7 9 3 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
6) 30 7 2 3 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
7) 30 7 2 4 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
5)2>=7Faux 30 7 2 4 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
8) 30 7 2 4 Donner 2 Entiers A et B, A>=0 et
B>0
30 7
30 Divise par 7 Quotient = 4 et
Reste = 2
Add Element
Add Element
Add Element

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Chapitre 4 - Les Tableaux (Arrays)

1 - Introduction
Jusqu'a présent nous avons vu uniquement les types simples: Integer, Real,
Character et Boolean.
Il existe d'autres types de données qui permettent de regrouper des données de
même type (par exemple des Integer avec des Integer).
Cette structure qui permet de regrouper des données de même type s'appelle Array
ou Tableau.
On va voir dans ce qui suit 2 types de tableau: les tableaux à une dimension
(Vecteur) et les tableau à 2 dimensions (Matrice).

2- Tableau à Une Dimension


2.1 Définition
Un tableau à une dimension ou Vecteur permet de rassembler des valeurs de même
type sous un même nom selon une structure linéaire. Chaque valeur est un élément
du vecteur et est accessible selon un indice qui est la position de l'élément dans le
vecteur.
Physiquement les éléments d'un tableau sont stockés de manière contigues (l'un
après l'autre) en mémoire centrale.
Schématiquement on peut représenter un tableau comme une structure linéaire
horizontale ou bien verticale.
1 2 3 4 5 6 7
-15 -3 15 9 6 23 11

-15
-3
15
9
6
23
11

Dans tout ce qui suit on utilisera la représentation horizontale .

Exemple:
un tableau de 7 entiers
1 2 3 4 5 6 7
-15 -3 17 23 11 22 91

un tableau de 4 caracteres
1 2 3 4
'a' 'B' 's' 'Z'

2.2 Déclaration d'un Vecteur


Un vecteur est définie par:
- un nom (identificateur)
- type qui est le type des éléments
- taille (ou bien dimension) qui est le nombre d'éléments que le vecteur contient

La taille d'un vecteur est fixe et doit être connu à la déclaration du tableau. On
déclare cette taille entre crochets. Le premier élément du tableau en algorithmique
est toujours à l'indice 1.

Syntaxe:

Var
<idf_tab> : Array[taille] of <type_elt>;

<idf_tab>: nom du tableau


taille: taille du tableau
<type_elt>: Integer, Real, Character ou Boolean

taille doit être une constante.

Exemple:
Var
TabEnt : Array[10] of Integer;
TabCar : Array[6] of Character;

TabEnt:
1 2 3 4 5 6 7 8 9 10
25 11 -9 12 81 13 21 -12 7 24

TabCar:
1 2 3 4 5 6
'x' 'f' '$' 'Y' 'v' 'N'

Si on a plus d'un tableau qui ont le même taille et le même type on peut les déclarer
ensemble comme par exemple TabEnt1 et TabEnt2 qui sont tous les deux des
tableaux de 5 entiers.

Var
TabEnt1, TabEnt2 : Array[5] of Integer;

Remarque:
La taille d'un tableau est une constante et ne peut pas être une variable.
Donc on ne peut pas écrire:
Var
N:Integer;
Tab:Array[N] of Integer; <--- Erreur la taille d'un tableau ne peut pas être une
variable

2.3 Accés aux Eléments d'un Vecteur


On accède directement à un élément d'un vecteur. On utilise pour cela la
désignation: <nom_tab>[indice] où indice est soit une constante soit une variable
dont la valeur doit être comprise entre 1 et taille (où taille est une constante), si le
vecteur est déclaré comme Array[taille].

Exemple:
Var
V : Array[6] of Integer;

V[1] est le premier élément du tableau


V[2] est le 2ème élément du tableau
V[3] est le 3ème élément du tableau
V[4] est le 4ème élément du tableau
V[5] est le 5ème élément du tableau
V[6] est le 6ème élément du tableau

2.4 Affectation, Lecture/Ecriture des Elements d'un Vecteur


V[indice] <--- val; affecte à l'élément d'indice indice la valeur val.
Read(V[indice]); lit du clavier la valeur rentrée par l'utilisateur et l'affecte à
l'élément d'indice indice
Write(V[indice]); affiche sur ecran la valeur de l'élément d'indice indice
Exemple
Var
V : Array[6] of Integer;

V[2] <--- 4; met dans le 2eme élément du tableau la valeur 4


Read(V[3]); lit du clavier la valeur rentrée par l'utilisateur et l'affecte au 3eme
élément du vecteur
Write(V[5]); affichesur ecran la valeur du 5eme élément du vecteur

2.5 Parcours d'un Vecteur


Parcourir un vecteur signifie accéder aux éléments du vecteur l'un après l'autre,
généralement en commençant par le premier élément.
Exemple
Soit
Var
V : Array[6] of Integer;

On veut afficher tous les éléments du tableau.


On peut le faire avec:
Write(V[1]);
Write(V[2]);
Write(V[3]);
Write(V[4]);
Write(V[5]);
Write(V[6]);

ou tout simplement en utilisant une boucle Pour:


For i <--- 1 to 6 Do
Write(V[i]);
Done

2.6 Initialisation d'un Vecteur


Initialiser un vecteur c'est affecter des valeur initiales aux éléments du vecteur.

Exemple
Soit
Var
V : Array[6] of Integer;

Initialiser tous les éléments d'un vecteur à 0


For i <--- 1 to 6 Do
V[i] <--- 0;
Done

ou bien Initialiser le vecteur à partir des valeurs données par l'utilisateur


For i <--- 1 to 6 Do
Read(V[i]);
Done

2.7 Applications sur les Vecteurs


Dans les applications suivantes on considère un vecteur de dimension 100 mais on
utilise les N premiers éléments du vecteur avec N un entier donné par l'utilisateur
avec 1<=N<=100.

1) Ecrire un algorithme qui calcule la somme des N premiers éléments d'un


vecteur.

Algorithm SommeVecteur;
Var
V:Array[100] of Integer;
i, N, Som:Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done

Som <--- 0;
For i <-- 1 to N Do
Som <--- Som + V[i];
Done

Write("La Somme des ", N, " elements du Vecteur = ", Som);


End.

2) Ecrire un algorithme qui fait l'affichage dans l'ordre inverse (commençant par le
dernier élément) des éléments d'un vecteur.
Algorithm AffInvVecteur;
Var
V:Array[100] of Integer;
i,N:Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done

i <---- N;
While (i >= 1) Do
Write(V[i]);
i <--- i - 1;
Done

End.

3) Ecrire un algorithme qui fait la recherche du plus petit et du plus grand élément
d'un vecteur.
Algorithm MinMaxVecteur;
Var
V:Array[100] of Integer;
i, N, Min, Max:Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done

Min <--- V[1];


Max <--- V[1];
For i <-- 2 to N Do
If (V[i] > Max) then
Max <--- V[i];
Else
If (V[i] < Min) then
Min <--- V[i];
EIf
EIf
Done

Write("Le Minimum du Vecteur est ", Min, " Le Maximum du Vecteur est ",
Max);
End.

4) Ecrire un algorithme qui calcule le produit des valeurs positives, ainsi que la
moyenne des valeurs négatives d'un vecteur.
Algorithm ProdPosMoyNegVecteur;
Var
V:Array[100] of Integer;
i, N, ProdPos, NbrPos, NbrNeg, SomNeg: Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done

NbrPos <--- 0;
NbrNeg <--- 0;
ProdPos <--- 1;
SomNeg <--- 0;
For i <-- 1 to N Do
If (V[i] > 0) then
NbrPos <--- NbrPos + 1;
ProdPos <--- ProdPos * V[i];
Else
If (V[i] < 0) then
NbrNeg <--- NbrNeg + 1;
SomNeg <--- SomNeg + V[i];
EIf
EIf
Done

If (NbrPos = 0) then
Write("Le Nombre de Valeurs Positives est 0");
Else
Write("Le produit des Valeurs Positives est :", ProdPos);
EIf
If (NbrNeg = 0) then
Write("Le Nombre de Valeurs Negatives est 0");
Else
Write("La Moyenne des Valeurs Negatives est :", SomNeg / NbrNeg);
EIf
End.

5) Ecrire un algorithme qui fait la recherche d'une valeur val dans un vecteur et
l'affichage de toutes les positions de val si val existe dans le vecteur.

Algorithm RechValEtPosVecteur;
Var
V:Array[100] of Integer;
i, N, Val: Integer;
Trouve : Boolean;

Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done

Write("Donner la valeur Val a Rechercher les positions");


Read(Val);

Trouve <--- False;


For i <-- 1 to N Do
If (V[i] = Val) then
Trouve <--- True;
Write(val, "existe a la position ", i);
EIf
Done

If (Trouve = False) then


Write(Val, " NE se trouve PAS dans le vecteur");
EIf
End.

6) Ecrire un algorithme qui fait la lecture et l’éclatement d'un vecteur en deux


vecteurs pair et impair contenant réspectivement les nombres pairs et les nombres
impairs.
Algorithm PairImpairVecteur;
Var
V, VPair, VImpair:Array[100] of Integer;
i, N, iPair, iImpair: Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done

iPair <--- 0;
iImpair <--- 0;
For i <-- 1 to N Do
If ((V[i] Mod 2) = 0) then
iPair <--- iPair + 1;
VPair[iPair] <--- V[i];
Else
iImpair <--- iImpair + 1;
VImpair[iImpair] <--- V[i];
EIf
Done

If (iPair = 0) then
Write("Vecteurs des Elements Pairs est Vide");
Else
Write("Vecteurs des Elements Pairs:");
For i <--- 1 to iPair Do
Write(VPair[i]);
Done
EIf

If (iImpair = 0) then
Write("Vecteurs des Elements Impairs est Vide");
Else
Write("Vecteurs des Elements Impairs:");
For i <--- 1 to iImpair Do
Write(VImpair[i]);
Done
EIf
End.

2.8 Algorithmes de Recherche dans un Vecteur


2.8.1 Recherche Séquentielle dans un Vecteur Non Trié
Principe: L’algorithme consiste à parcourir un à un les éléments du tableau pour
trouver la valeur Val . La recherche s’arrête si Val est trouvée, on doit dans ce cas
dire que la valeur Val a été trouvé ou bien lorsqu'on a comparé Val à tous les
éléments du Vecteur et que Val est différente de tous ces éléments, dans ce cas on
doit dire que Val n'a pas été trouvé dans le vecteur.

Exemple: Soit le vecteur V avec N = 8


1 2 3 4 5 6 7 8
15 -7 18 12 -21 18 29 13

Si l'utilisateur donne la valeur Val égale à 35 (qui n'existe pas dans le tableau),
alors on commence par comparer 35 avec V[1] qui est 15 et 35 est différent de 15,
donc on compare ensuite 35 avec V[2] qui est -7 et aussi 35 est différent de -7 donc
on compare 35 a V[3] qui est 18 et aussi 35 est différent de 18 et ainsi de suite
jusqu'a comparer 35 avec le dernier élément du tableau V[N=8] qui est 13 et là
aussi 35 est différent de 13 et dans ce cas on conclu que 35 ne se trouve pas dans le
tableau.
Si l'utilisateur donne la valeur Val égale à 18, alors on commence par comparer 18
avec V[1] qui est 15 et 18 est différent de 15, donc on compare ensuite 18 avec
V[2] qui est -7 et aussi 18 est différent de -7 donc on compare 18 à V[3] qui est 18
et là on a trouvé 18 et bien sûr on arrête la recherche et on conclu que 18 se trouve
dans le tableau.

Donc ce qu'on est en train de faire est comparer Val avec les éléments du tableau
un à un en commençant par le premier élément du tableau et dés qu'on trouve Val
on s'arrête mais si on n'a pas encore trouvé Val on va comparer encore avec le
prochain et cela jusqu'au dernier élément du tableau.
Donc on remarque qu'il y'a une répétition (c'est le faite de comparer Val avec un
élément du tableau) mais on ne sait pas combien de fois on va répéter cela (car dés
qu'on trouve Val on s'arrête) donc on ne peut pas utiliser une boucle Pour et on va
utiliser pour cela une boucle Tant Que.

On peut écrire l'algorithme correspondant soit en utilisant une variable booléenne


soit sans utiliser de variable booléenne.

Solution 1: Utilisation d'une variable booléenne


Principe: La variable booléenne Trouve est initialisée à False pour indiquer qu'au
debut on suppose que la valeur Val ne se trouve pas dans le tableau et la condition
qu'on utilise dans le Tant Que pour cette variable est (Trouve = False) pour pouvoir
rentrer la première fois dans le Tant Que. A l'intérieur du Tant Que dés qu'on
trouve que V[i]=Val alors on met le booleen à True pour que à la prochaine
itération on sort du Tant Que. L'autre condition à ajouter au Tant Que est (i <= N)
car i ne doit pas dépasser N (le nombre d'éléments qu'il y'a dans le tableau)
lorsqu'on accède à V[i] car V[N] est le dernier élément.

Algorithm RechSeqVecteurNonTrie;
Var
V:Array[100] of Integer;
i, N, Val:Integer;
Trouve : Boolean;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done
Write("Donner la valeur Val a Rechercher");
Read(Val);

Trouve <--- False;


i <--- 1;
While ((i <= N) and (Trouve = False)) Do
If (V[i] = Val) then
Trouve <--- True;
Else
i <--- i + 1;
EIf
Done

If (Trouve = True) then


Write(Val, "se Trouve dans le Vecteur");
Else
Write(Val, "NE se Trouve PAS dans le Vecteur");
EIf
End.

Solution 2: Sans Utiliser de variable booléenne


Principe: La condition (V[i] <> Val) est mise directement dans le Tant Que. Tant
qu'on n'a pas depassé la position du dernier élément (c.a.d i <= N) et tant que (V[i]
<> Val) il faut comparer avec le prochain élément de V(c.a.d incrémenter le i). Dés
que i dépasse le N (dans le cas où Val ne se trouve pas dans V) ou bien dés qu'on
trouve V[i] = Val (dans le cas où Val se trouve dans V) on s'arrête. Lorsqu'on sort
du tant que, Val ne se trouve pas dans le tableau s'il est différent de tous les
éléments du tableau et en particulier est différent de V[N] donc on rentre à
l'interieur du Tant Que dans le cas où i=N et dans ce cas i devient N+1. Dans le cas
contraire (c.a.d i<=N) cela veut dire que Val se trouve dans le tableau.

Algorithm RechSeqVecteurNonTrie;
Var
V:Array[100] of Integer;
i, N, Val:Integer;

Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur");
Read(V[i]);
Done

Write("Donner la valeur Val a Rechercher");


Read(Val);

i <--- 1;
While ((i <= N) and (V[i] <> Val)) Do
i <--- i + 1;
Done

If (i <= N) then
Write(Val, "se Trouve dans le Vecteur");
Else
Write(Val, "NE se Trouve PAS dans le Vecteur");
EIf
End.

Remarque:
Il faut remarquer qu'il faut écrire la condition du Tant Que comme: While((i <= N)
and (V[i] <> Val))
et ne pas écrire la condition comme: While ( (V[i] <> Val) and (i <= N)).
La raison est que si on écrit la condition du While comme While ( (V[i] <> Val)
and (i <= N)) dans le cas où Val n'existe pas la condition (V[i] <> Val) est vrai pour
tous les i (de 1 à N) donc en particulier cette condition est vrai pour i=N donc on
vas rentrer dans le Tant Que lorsque i arrive à la valeur N et i sera incrementé (donc
i devient égale à N + 1) et lorsqu'on revient au Tant Que on vas évaluer la condition
(V[i] <> Val) avec i=N+1 en supposant que l'utilisateur a donné N la taille
maximale de V, V[N+1] n'existe pas.
Tandis que si on écrit la condition du While comme: While ((i <= N) and (V[i] <>
Val)) lorsque Val ne se trouve pas dans V et que i arrive à la valeur N on rentre
dans le While i sera incrementé et devient égale à N+1 et lorsqu'on revient au
While on évalue d'abord la condition (i <= N), or i = N+1 donc cette condition est
fause et par conséquent toute la condition du While est fausse (car c'est un AND) et
la condition (V[i] <> Val) n'est pas évaluée (Dans un AND les conditions sont
évaluées dans l'ordre où elles sont écrites).

2.8.2 Recherche Séquentielle dans un Vecteur Trié


On supposera que le vecteur est trié par ordre croissant (du plus petit au plus grand)
dans ce qui suit.
Principe: Si le vecteur est trié par ordre croissant, la recherche s’arrêtera dés que
l’on trouve un élément plus grand ou égale à la la valeur recherchée.
Exemple: Soit le vecteur V avec N = 8 trié par ordre croissant
1 2 3 4 5 6 7 8
-15 -7 8 10 14 18 29 33

Dés le debut on peut conclure que si Val est plus petite que V[1] Val ne se trouve
pas dans le tableau (car Val<V[1] et comme V est trié par ordre croissant Val<V[i]
pour i de 1 a N).
De même si Val>V[N] Val ne se trouve pas dans le tableau (car Val>V[N] et
comme V est trié par ordre croissant Val>V[i] pour i de 1 a N).

Si l'utilisateur donne la valeur Val égale à 9 (qui n'existe pas dans le tableau), alors
on commence par comparer 9 avec V[1] qui est -15 et 9 est différent de -15, donc
on compare ensuite 9 avec V[2] qui est -7 et aussi 9 est différent de -7 donc on
compare 9 à V[3] qui est 8 et aussi 9 est different de 8 ensuite on compare 9 avec
V[4]=10 et 9 est bien sûr 9 est différent de 10 mais aussi 9 est inferieur à 10 donc 9
sera infërieur à tous les éléments qui se trouvent après V[4] car le tableau est trié
par ordre croissant donc 9 ne peut pas se trouver après V[4] et ainsi on peut arrêter
les comparaisons et conclure que 9 ne se trouve pas dans le tableau.
Par conséquent lorsqu'on compare Val avec les éléments du tableau en
commençant à partir du premier élément on arrête la recherche dés qu'on trouve
V[i]=Val (Val se trouve dans ce cas dans le tableau) ou bien dés qu'on a V[i] > Val
car dans ce dernier cas Val sera inférieur à tous les éléments qui se trouvent après
V[i] et on peut conclure que Val ne se trouve pas dans le tableau.

On peut écrire l'algorithme correspondant soit en utilisant une variable booléenne,


soit sans utiliser de variable booléenne.

Solution 1: Utilisation d'une variable booléenne


Principe: Si dés le debut Val<V[1] alors Val sera inférieur à tous les elements de V
puisque V est trié par ordre croissant et par consequent Val ne se trouve pas dans
V. De même si Val>V[N] alors Val sera supèrieur à tous les éléments de V puisque
V est trié par ordre croissant et par consequent Val ne se trouve pas dans V.
On s'arrêtera lorsqu'on trouve Val c.a.d Val=V[i] et dans ce cas on met Trouve à
True ou bien dés qu'on a Val<V[i] ou bien dés que i depasse N.

Algorithm RechSeqVecteurTrie;
Var
V:Array[100] of Integer ;
i, N, Val: Integer;
Trouve : Boolean;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));

/* On suppose dans ce qui suit que l'utilisateur donne un Vecteur Trie par ordre
croissant */
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur (Vecteur TRIE par ordre
croissant)");
Read(V[i]);
Done

Write("Donner la valeur Val a Rechercher");


Read(Val);

Trouve <--- False;


If ((Val >= V[1]) and (Val <= V[N])) then
i <--- 1;
While ((i <= N) and (Trouve = False) and (Val>=V[i])) Do
If (V[i] = Val) then
Trouve <--- True;
Else
i <--- i + 1;
EIf
Done
EIf
If (Trouve = True) then
Write(Val, "se Trouve dans le Vecteur");
Else
Write(Val, "NE se Trouve PAS dans le Vecteur");
EIf
End.

Solution 2: Sans Utiliser de variable booléenne


Principe: Si dés le debut Val<V[1] alors Val sera < à tous les éléments de V
puisque V est trié par ordre croissant et par conséquent Val ne se trouve pas dans
V. De même si Val>V[N] alors Val sera > à tous les éléments de V puisque V est
trié par ordre croissant et par consequent Val ne se trouve pas dans V.
Sinon if faut comparer avec le prochain tant que i<N et tant que Val>V[i]. On
s'arrêtera lorsqu'on trouve Val=V[i] ou bien des qu'on a Val<V[i] car Val sera < à
tous les ëlëments restant apres le ième élément puisque le vecteur est trié par ordre
croissant.

Algorithm RechSeqVecteurTrie;
Var
V:Array[100] of Integer;
i, N, Val: Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));

/* On suppose dans ce qui suit que l'utilisateur donne un Vecteur Trie par ordre
croissant */
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur (Vecteur TRIE par ordre
croissant) ");
Read(V[i]);
Done

Write("Donner la valeur Val a Rechercher");


Read(Val);

If ((Val < V[1]) or (Val > V[N])) then


Write(Val, "NE se Trouve PAS dans le Vecteur");
Else
i <--- 1;
While ((i < N) ET (V[i] < Val)) Do
i <--- i + 1;
Done

If (V[i] = Val) then


Write(Val, "se Trouve dans le Vecteur");
Else
Write(Val, "NE se Trouve PAS dans le Vecteur");
EIf
EIf
End.

2.8.3 Recherche Dichotomique (Binaire) dans un Vecteur Trié (Binary Search)


Principe: Le principe de la recherche dichotomique (binaire) est le suivant: soit V
un Array[N] d’entiers trié par ordre croissant et un entier val à rechercher si il
existe dans V ou non. Au départ on considère l’intervalle [1..N] du tableau, pour
cela on prend l’élément situé au milieu du tableau soit d’indice mi = ((1 + N)/2) et
on compare Val à T[mi]. Trois situations se présentent:
1) val = T[mi] et la recherche est terminée.
2) val < T[mi] il faut poursuivre la recherche dans la moitié gauche du
tableau
3) val > T[mi] il faut poursuivre la recherche dans la moitié droite du
tableau.

Dans les 2 derniers cas on continue la recherché avec le même procédé en divisant
l’intervalle l en 2 moitiés jusqu’a trouver val ou bien jusqu’a ce que l’intervalle de
recherche soit réduit à un seul element.

Exemple: Soit le vecteur V avec N = 8 trie par ordre croissant


1 2 3 4 5 6 7 8
-15 -7 8 10 14 18 29 33

On considere au debut l'intervalle [1..8]


Donc mi=(1 + 8) Div 2 = 4
Donc au début on compare Val avec V[4].
Si l'utilisateur donne Val=10 alors Val=V[4] et on arrête la recherche.
Si l'utilisateur donne Val tels que Val est > V[4] alors Val ne peut se trouver que
après V[4] et dans ce cas on va considérer l'intervalle [5..8] et on calcule mid=(5 +
8) Div 2 et on refait la même chose.
Si l'utilisateur donne Val tels que Val est < V[4] alors Val ne peut se trouver que
avant V[4] et dans ce cas on va considérer l'intervalle [1..3] et on calcule mid=(1 +
3) Div 2 et on refait la même chose.

On a besoin d'un indice i initialisé à 1 et d'un indice J initialisé à N=8.

On peut écrire l'algorithme correspondant soit en utilisant une variable booléenne


soit sans utiliser de variable booléenne.

Solution 1: Utilisation de Variable Booléenne


Algorithm RechercheDichotomique;
Var
V: Array[100] of Integer ; /*trie par ordre croissant*/
N, val, i, J, mi : Integer;
Trouve :Boolean ;
Begin
Repeat
Read(N);
Until ((N>=1) and (N<=100]));

/* On suppose dans ce qui suit que l'utilisateur donne un Vecteur Trie par ordre
croissant */
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur (Vecteur TRIE par ordre croissant)
");
Read(V[i]) ;
Done

Write("Donner la valeur Val a Rechercher");


Read (val);

Trouve <--- False;


If ((val >= V[1]) and (val <= V[N])) then
i <--- 1;
J <--- N;
Trouve <--- False;
While ((i <= J) and (Trouve = False)) Do
mi <--- (i + J) Div 2 ;
If (V[mi] = val) then
Trouve <--- True ;
Else
If (V[mi] < val) then
i <--- mi + 1 ;
Else
J <--- mi - 1 ;
EIf
EIf
Done
EIf
If (Trouve = True) then
Write(val , " Trouvee") ;
Else
Write(val , "NON Trouvee") ;
EIf
End.

Solution 2: Sans Utiliser de Variable Booléenne


Algorithm RechercheDichotomique;
Var
V: Array[100] of Integer ; /*trie par ordre croissant*/
N, val, i, J, mi : Integer;
Begin
Repeat
Read(N);
Until ((N>=1) and (N<=100]));

/* On suppose dans ce qui suit que l'utilisateur donne un Vecteur Trie par ordre
croissant */
For i <--- 1 to N Do
Write("Donner ", i ," eme element du Vecteur (Vecteur TRIE par ordre croissant)
");
Read(V[i]) ;
Done

Write("Donner la valeur Val a Rechercher");


Read(val);

If ((val < V[1]) OU (val > V[N])) then


Write(Val, "NE se Trouve PAS dans le Vecteur");
Else
i <--- 1;
J <--- N;
mi <--- (i + J) Div 2 ;
While ((i <= J) and (V[mi] <> val)) Do
If (V[mi] < val) then
i <--- mi + 1 ;
Else
J <--- mi - 1 ;
EIf
mi <--- (i + J) Div 2 ;
Done
If (i <= J) then
Write(val , " Trouvee") ;
Else
Write(val , "NON Trouvee") ;
EIf
EIf
End.
2.9 Algorithmes de Tri d'un Vecteur
Etant donné un vecteur V[1..N] NON trié, on va trier V par ordre croissant.
Il y'a plusieurs manières pour trier un vecteur. On verra dans ce qui suit 3 manières
de tri d'un vecteur.

2.9.1 Tri par Selection (Selection Sort)


Le procédé est le suivant:
a) chercher l’indice du minimum dans V[1..N], soit iMin
b) ramener le minimum en position 1 en permutant V[1] avec V[iMin]
repeater a) et b) avec V[2..N], V[3..N], …, V[N-1..N] en permutant successivement
V[iMin] avec V[2], V[3], …,V[N-1]

Exemple Soit V le vecteur suivant:

V: 1 2 3 4 5 6
2 5 1 0 4 9

Itération 1:
iMin=4 car le Minum de V[1..6] est 0 situé à la position 4. Donc on va permuter V[4] avec
V[1].

V: 1 2 3 4 5 6
0 5 1 2 4 9

Itération 2:
iMin=3 car le Minimum de V[2..6] est 1 situé à la position 3. Donc on va permuter V[3] avec
V[2].

V: 1 2 3 4 5 6
0 1 5 2 4 9

Itération 3:
iMin=4 car le Minimum de V[3..6] est 2 situé à la position 4. Donc on va permuter V[4] avec
V[3].

V: 1 2 3 4 5 6
0 1 2 5 4 9
Itération 4:
iMin=5 car le Minimum de V[4..6] est 4 situé à la position 5. Donc on va permuter V[5] avec
V[4].

V: 1 2 3 4 5 6
0 1 2 4 5 9
Itération 5:
iMin=5 car le Minimum de V[5..6] est 5 situé à la position 5. Comme 5 est deja situé à la
position 5 on n'a rien à permuter.

V: 1 2 3 4 5 6
0 1 2 4 5 9

Algorithm TriSelection;
Var
V: Array[100] of Integer ;
N, i, J, iMin, temp : Integer;
Begin
Repeat
Read(N);
Until ((N>=1) and (N<=100]));

For i <--- 1 to N Do
Read(V[i]) ;
Done

For i<--- 1 to (N - 1) Do
/* Chercher l'indice du minimum iMin du Array[i..N] pour mettre le minimum
dans la position i */
iMin <--- i;
For J <--- (i + 1) to N Do
If (V[J] < V[iMin]) the
iMin <--- J;
EIf
Done

// Si iMin est egale à i il n'y a rien à permuter car le Min est deja dans la
position i
// Si iMin<>i permuter V[iMin] et V[i]
If (iMin <> i) then
temp <--- V[i]; // sauvegarder V[i] dans temp
V[i] <--- V[iMin]; // mettre V[iMin] dans V[i]
V[iMin] <--- temp; // mettre dans V[iMin] temp qui contien V[i] initial
EIf
Done
Write("Tableau Trie:");
For i <--- 1 to N Do
Write(V[i]) ;
Done
End.

2.9.2 Tri par Insertion (Insertion Sort)


Le procédé est le suivant:
a) ordonner les 2 premiers éléments.
b) insérer le 3-ème élément de façon à ce que les 3 premiers éléments soient triés
c) les 3 premiers éléments étant triés, insérer le 4-ème éléments de façon à ce que
les 4 premiers éléments soient triés, répéter b) avec le 5-eme, 6-eme,…,n-ème
élément

Exemple Soit V le vecteur suivant:

V: 1 2 3 4 5 6
5 2 4 6 1 3

Itération 1: Trier V[1..2]


V 1 2 3 4 5 6
5 2 4 6 1 3
V 1 2 3 4 5 6
2 5 4 6 1 3

Itération 2: Trier V[1..3] en insérant V[3] dans V[1..2] déja trié


V 1 2 3 4 5 6
2 5 4 6 1 3
V 1 2 3 4 5 6
2 4 5 6 1 3

Itération 3: Trier V[1..4] en insérant V[4] dans V[1..3] déja trié


V 1 2 3 4 5 6
2 4 5 6 1 3
V 1 2 3 4 5 6
2 4 5 6 1 3

Itération 4: Trier V[1..5] en insérant V[5] dans V[1..4] déja trié


V 1 2 3 4 5 6
2 4 5 6 1 3
V 1 2 3 4 5 6
1 2 4 5 6 3

Itération 5: Trier V[1..6] en insérant V[6] dans V[1..5] déja trié


V 1 2 3 4 5 6
1 2 4 5 6 3
V 1 2 3 4 5 6
1 2 3 4 5 6

Algorithm TriInsertion;
Var
V: Array[100] of Integer ;
N, i, J, Temp : Integer;
Begin
Repeat
Read(N);
Until ((N>=1) and (N<=100]));

For i <--- 1 to N Do
Read(V[i]) ;
Done

For i <--- 2 to N Do
Temp <--- V[i];
J <--- i - 1;
While ((J >= 1) and (V[J] > Temp)) Do
// Decaler les elements > Temp d'une position à droite
V[J + 1] <--- V[J];
J <--- J - 1;
Done
V[J + 1] <--- Temp;
Done

Write("Tableau Trie:");
For i <--- 1 to N Do
Write(V[i]) ;
Done
End.

2.9.3 Tri par Bulle (Buble Sort)


Le procédé est le suivant:
a) parcourir tous les éléments de V[1..N] et comparer toutes les 2 valeurs
adjacentes, si x est suivi de y et si x est plus grand que y alors inverser x et y. Ainsi
donc au 1er passage la valeur max de V[1..N] sera mise à la position N.
b) répéter a) successivement avec les sous-vecteurs [1..N-1], [1..N-2],…[1..2]
Exemple Soit V le vecteur suivant:

V: 1 2 3 4 5 6
6 1 3 5 0 4

Seront montrés dans ce qui suit uniquement les 2 premières itérations.

Itération 1:
V: 1 2 3 4 5 6
6 1 3 5 0 4
Comparons 6 et 1: on inverse:
V: 1 2 3 4 5 6
1 6 3 5 0 4
Comparons 6 et 3: on inverse:
V: 1 2 3 4 5 6
1 3 6 5 0 4
Comparons 6 et 5: on inverse:
V: 1 2 3 4 5 6
1 3 5 6 0 4
Comparons 6 et 0: on inverse:
V: 1 2 3 4 5 6
1 3 5 0 6 4
Comparons 6 et 4: on inverse:
V: 1 2 3 4 5 6
1 3 5 0 4 6
Fin de l’itération 1.

Itération 2:
V: 1 2 3 4 5 6
1 3 5 0 4 6

Comparons 1 et 3: on laisse:
V: 1 2 3 4 5 6
1 3 5 0 4 6
Comparons 3 et 5: on laisse:
V: 1 2 3 4 5 6
1 3 5 0 4 6
Comparons 5 et 0: on inverse:
V: 1 2 3 4 5 6
1 3 0 5 4 6

Comparons 5 et 4: on inverse:
V: 1 2 3 4
5 6
1 3 0 4 5 6

Fin de l’itération 2.

Algorithm TriBulle;
Var
V: Array[100] of Integer ;
N, i, J, Temp : Integer;
Begin
Repeat
Read(N);
Until ((N>=1) and (N<=100]));

For i <--- 1 to N Do
Read(V[i]) ;
Done

For i <--- 1 to (N - 1) Do
For J <--- 1 to (N - i) Do
If (V[J] > V[J+1]) then
Temp <--- V[J];
V[J] <--- V[J + 1];
V[J + 1] <--- Temp;
EIf
Done
Done

Write("Tableau Trie:");
For i <--- 1 to N Do
Write(V[i]) ;
Done
End.

Tri par Bulle Amelioré (Improved Bubble Sort)


b)Ameliorer cet algorithme en remarquant que si à un moment donné en traversant
un des sous-vecteurs aucune permutation n’est effectuée c’est que le vecteur V est
déja trié et que c’est inutile de traverser les sous-vecteurs suivants et de comparer
les éléments adjacents.

Algorithm TriBulleAmeliore;
Var
V: Array[100] of Integer ;
N, i, J, Temp : Integer;
Permuter : Boolean;
Begin
Repeat
Read(N);
Until ((N>=1) and (N<=100]));

For i <--- 1 to N Do
Read(V[i]) ;
Done

Permuter <--- True;

i <--- 1;
While ((i < N) and (Permuter = True)) Do
Permuter <--- False;
For J <--- 1 to (N - i) Do
If (V[J] > V[J+1]) then
Temp <--- V[J];
V[J] <--- V[J + 1];
V[J + 1] <--- Temp;
Permuter <--- True;
EIf
Done
i <--- i + 1;
Done

Write("Tableau Trie:");
For i <--- 1 to N Do
Write(V[i]) ;
Done
End.

3 - Les Tableaux à 2 Dimensions - Les Matrices


3.1 Définition
Un tableau à 2 dimensions ou matrice est un vecteur dont les éléments sont aussi
des vecteurs. Une matrice est définie par son nom, le type de ses éléments et sa
taille exprimée sous forme de nombre de lignes et de nombre de colonnes.
Exemple:
Matrice de 4 lignes et 3 colonnes d'entiers
12 5 -3
27 -17 11
29 31 19
-9 22 14

3.2 Déclaration
Syntaxe:
<idf_matrice> : Array[TL, TC] of <type>;
<idf_matrice> : identificateur (nom) de la matrice
TL: Taille lignes (nombre de lignes)
TC: Taille colonnes (nombre de colonnes)
<type>: Integer, Real, Character ou Boolean

Exemple:
Var
matEnt: Array[20, 30] of Integer;
matCar: Array[10, 5] of Character;

matEnt est une matrice de 20 lignes et 30 colonnes d'entiers


matCar est une matrice de 10 lignes et 5 colonnes de caractères

Remarques:
1) TL et TC doivent être des constantes entières.
2) Si 2 ou plusieurs matrices ont même nombre de lignes et même nombre de
colonnes et même type alors on peut les déclarer sur la même ligne.
Exemple: M1, M2:Array[10, 5] of Integer;

3.3 Les Opérations sur les Matrices


3.3.1 Accés à un élément de la matrice
L'accés à un élément de la matrice se fait en donnant de nom de la matrice et entre
crochets l'indice de la ligne suivi de l'indice de la colonne.
<idf_matrice>[indice_ligne, indice_colonne]

3.3.2 Affectation, Lecture et Ecriture des Eléments de la matrice

M[2, 3] <--- 21; affecte la valeur 21 à l'élément situé dans la 2eme ligne et la 3eme
colonne.

Read(M[3, 2]); Met dans l'élément situé dans la 3eme ligne et la 2eme colonne la
valeur tapée au clavier par l'utilisateur

Write(M[2, 1]); Affiche sur écran l'élément situé dans la 2eme ligne et la 1ere
colonne

3.3.3 Parcours d'une matrice


Parcourir une matrice veut dire accéder à tous les éléments de la matrice l'un après
l'autre. On peut parcourir une matrice ligne par ligne ou bien colonne par colonne.

On parcourt une matrice ligne par ligne en parcourant ligne par ligne et pour
chaque ligne on parcourt colonne par colonne.
On parcourt une matrice colonne par colonne en parcourant colonne par colonne et
pour chaque colonne on parcourt ligne par ligne.

Exemple:
Soit la matrice M d'entiers de 4 lignes et 3 colonnes declarée comme:
M:Array[4, 3] of Integer;

Parcours (en lecture) ligne par ligne:


For i <--- 1 to 4 Do
For J <--- 1 to 3 Do
Read(M[i, J]);
Done
Done

Parcours (en ecriture) colonne par colonne:


For J <--- 1 to 3 Do
For i <--- 1 to 4 Do
Write(M[i, J]);
Done
Done
Généralement on utilise le parcours ligne par ligne.

Exemple
Affichage des elements de la matrice M declarée comme:
M:Array[3, 4] of Integer;

For i <--- 1 to 3 Do
For J <--- 1 to 4 Do
Write(M[i, J]);
Done
Done

3.3.4 Initialisation d'une matrice


Initialiser une matrice signifie affecter des valeurs initiales à la matrice.

Exemple:
Soit la matrice M declarée comme:
M:Array[3, 4] of Integer;

For i <--- 1 to 3 Do
For J <--- 1 to 4 Do
Read(M[i, J]);
Done
Done

3.3.5 Applications
1) Soit A(N, M) une matrice de NxM entiers (N<=20 et M<=30), écrire un
algorithme permettant de faire la recherche d'un élément dans cette matrice.

Algorithm rechercheValMatrice;
Var
A: Array [20, 30] of Integer ;
N, M, i, J, val : Integer;
Trouve : Boolean;
Begin
Repeat
Write("Donner N compris entre 1 et 20");
Read(N);
Until ((N>=1) and (N<=20));

Repeat
Write("Donner M compris entre 1 et 30");
Read(M);
Until ((M>=1) and (M<=30));

For i <--- 1 to N Do
For J <--- 1 to M Do
Write("Donner l'entier d'indices ", i, J);
Read(A[i, J]) ;
Done
Done

Write("Donner un entier val a Rechercher");


Read(val);

Trouve <--- False;


i <--- 1;

While ((i <= N) and (Trouve = False)) Do


J <--- 1;
While ((J <= M) and (Trouve = False)) Do
If (A[i, J] = val) then
Trouve <--- True;
Else
J <--- J + 1;
EIf
Done
i <--- i + 1;
Done

If (Trouve = True) then


Write(val, "Trouve dans la Matrice");
Else
Write(val, "NON Trouve dans la Matrice");
EIf
End.

2) Soit A(N, M) une matrice de NxM caracteres (N<=20 et M<=30), écrire un


algorithme permettant de calculer le nombre de voyelles minuscules appartenant à
la matrice A. .

Algorithme nbrVoyellesMatrice;
Var
A: Array [20, 30] of Character ;
N, M, i, J, nbrVoy : Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 20");
Read(N);
Until ((N>=1) and (N<=20));

Repeat
Write("Donner M compris entre 1 et 30");
Read(M);
Until ((M>=1) and (M<=30));

For i <--- 1 to N Do
For J <--- 1 to M Do
Write("Donner le caractere d'indices ", i, J);
Read(A[i, J]) ;
Done
Done

nbrVoy <--- 0;

For i <--- 1 to N Do
For J <--- 1 to M Do
Case (A[i, J]) of
'a', 'e', 'i', 'u', 'o', 'y': nbrVoy <--- nbrVoy + 1;
ECase
Done
Done

Write("Nombre de Voyelles Minuscules dans la Matrice:", nbrVoy);


End.

3) Ecrire un algorithme qui calcule la trace de la matrice A(N, N) N<=25 de Entier.


(La trace est la somme des éléments de la diagonale principale).

Algorithm traceMatrice;
Var
A: Array [25, 25] of Integer ;
N, i, J, trace : Integer;

Begin
Repeat
Write("Donner N compris entre 1 et 25");
Read(N);
Until ((N>=1) and (N<=25));

For i <--- 1 to N Do
For J <--- 1 to N Do
Write("Donner l'entier d'indices ", i, J);
Read(A[i, J]) ;
Done
Done

trace <--- 0

/* les elements dans la diagonale principale sont situes dans la case A[i, i] */
For i <--- 1 to N Do
trace <--- trace + A[i, i];
Done

Write("Trace de la Matrice = ", trace);


End.

4) La recherche du minimum et du maximum des deux diagonales (principale et


secondaire) de la matrice A(N, N) N<=25 de Entier.

Algorithm minMaxMatrice;
Var
A: Array [25, 25] of Integer ;
N, i, J, Min, Max : Integer;
Begin
Repeat
Write("Donner N compris entre 1 et 25");
Read(N);
Until ((N>=1) and (N<=25));

For i <--- 1 to N Do
For J <--- 1 to N Do
Write("Donner l'entier d'indices ", i, J);
Read(A[i, J]) ;
Done
Done

Max <--- A[1,1];


Min <--- A[1,1];

/* les elements dans la diagonale principale sont situes dans la case A[i, i] et les
elements dans la diagonale secondaire sont situes dans la case A[i, N-i+1]
*/
For i <--- 1 to N Do
If (Max < A[i,i]) then
Max <--- A[i,i];
EIf
If (Max < A[i, N-i+1]) then
Max <--- A[i,N-i+1];
EIf
If (Min > A[i,i]) then
Min <--- A[i,i];
EIf
If (Min > A[i, N-i+1]) then
Min <--- A[i,N-i+1];
EIf
Done

Write("Maximum des 2 diagonales de la Matrice = ", Max);


Write("Minimum des 2 diagonales de la Matrice = ", Min);
End.

4. Les Chaines de Caractères (Strings)


4.1 Définition
Les chaines de caractères servent à representer des informations non numériques,
comme des nom, prenom, addresses ...
Une chaine de caractères est representée comme un tableau dont les éléments sont
des caractères.

Exemple: La chaine de caractères "bellil" est representée comme le tableau suivant


contenant 6 caractères:
1 2 3 4 5 6
'b' 'e' 'l' 'l' 'i' 'l'

4.2 Déclaration
Syntaxe:
<idf_chaine> : String[lg];
<idf_chaine> : identificateur (nom) de la chaine de caractères
lg: le nombre maximum de caractères (taille maximale) que la chaine de caractères
peut contenir.

Exemple
Var
ch: String[30];
ch est une chaine de caractères qui peut contenir au maximum 30 caractères.

Remarques:
1) Si lg n'est pas specifiée alors par defaut lg est égale à 255.
Var
ch : String;
taille maximale de ch est 255 caractères.

2) Si 2 chaines ou plus ont la même taille maximale on peut les déclarer sur la
même ligne.
Var
ch1, ch2 : String[30];

3) On utilise les symboles "" pour dëlimiter la valeur d'une constante chaine de
caractères.
"Mohamed"

4) On peut avoir un tableau de chaines caractères.


Exemple:
Var
TabChaine:Array[1..100] de String;

TabChaine est un tableau de 100 éléments et dont chaque élément est une chaine.

4.3 Les Opérations sur les Chaines


4.3.1 Affectation, Lecture et Ecriture d'une chaine
Contrairement aux tableaux on peut affecter à une chaine une valeur chaine de
caractères, on peut aussi lire et écrire directement une chaine.
Var
nom : String[50];

nom <--- "Benali";

Read(nom); Met dans la variable nom la chaine de caractères tapée au clavier par
l'utilisateur.
Write(nom); Affiche sur écran la chaine de caractères contenu par la variable nom

4.3.2 La Taille d'une chaine de Caractères


4.3.2.1 Taille Courante d'une Chaine de Caractères
On a une fonction prédefinie Length() qui étant donnée une chaine ch, nous donne
la taille courante (le nombre de caractères courant de la chaine:
Length(ch)
ch: variable comtenant la chaine de caractères dont on veut avoir la taille courante
Cette fonction retourne un entier.

Var
nom : String[50];
T : Integer;

nom <--- "Benali";


T <--- Length(nom); /* Dans ce cas T va contenir 6 le nombre de caracteres de
"Benali"* /

nom <--- "Omar";


T <--- Length(nom); /* Dans ce cas T va contenir 4 le nombre de caracteres de
"Omar" */

nom <--- ""; /* nom contient la chaine vide */


T <--- Length(nom); /*Dans ce cas T va contenir 0 le nombre de caracteres de ""
la chaine vide */

4.3.2.2 Changer la Taille Courante d'une Chaine de Caractères


La fonction prédéfinie SetLength(ch, nouvelleTaille) change la taille courante de la
chaine de caractères ch comme étant nouvelleTaille:
SetLength(ch, nouvelleTaille)
ch: variable contenant la chaine de caractères dont on veut changer la taille
nouvelleTaille: variable de type entier (ou constante entière) contenant la nouvelle
taille de la chaine.

La taille nouvelleTaille fournie comme paramètre à cette fonction ne doit pas être
plus grande que la taille maximale de la chaine donnée lors de la déclaration de la
chaine.
Si la taille fournie comme paramètre à la fonction ChangerTaille() est plus grande
que la taille maximale de la chaine cela constitue une erreur et la taille courante de
la chaine n'est pas modifiée.
Si la taille fournie comme paramètre à la fonction ChangerTaille() est inferieur à la
taille maximale alors la taille courante est modifiée comme étant la nouvelle taille.
On utilisera cette fonction surtout lorsqu'on fait un décalage d'une chaine de
caractères en vue de supprimer certains caractères.

On supposera que la taille courante d'une chaine de caractères est sauvegardée


quelque part en Mémoire Centrale.

nom : String[50];
T : Integer;

nom <--- "Benali";


T <--- Length(nom); /* Dans ce cas T va contenir la valeur 6 le nombre de
caracteres de "Benali"* /
Write(nom); // La chaine "Benali" est affichee

SetLength(nom, 4);
T <--- Length(nom); /* Dans ce cas T va contenir la valeur 4 le nombre de
caracteres de "Bena"* /
Write(nom); // La chaine "Bena" est affichee

4.3.3 Accés à un élément de la chaine


On peut acceder à un élément de la chaine qui est un caractère en indiquant l'indice
de l'élément.
<idf_chaine>[indice]

Exemple:
Var
nom : String[50];
Car : Character;

nom <--- "Benali";


Car <--- nom[1]; Dans ce cas Car = 'B' le premier Caractere de nom
Car <--- nom[3]; Dans ce cas Car = 'n' le troisieme Caractere de nom

Car <--- 'e';


nom[3] <--- Car; Dans ce cas nom va contenir "Benali"

4.3.4 Comparaison des chaines


Contrairement aux tableaux on peut comparer directement 2 chaines de caractères
en utilisant les operateurs:
= (egalite), <> (different), < (inferieur) et > (superieur).
2 chaines de caractères S1 et S2 sont égales si elles ont le même nombre de
caractères (la fonction Taille() retourne la même valeur pour S1 et S2 et si S1 et S2
contiennent les même caractères dans le même ordre.

Remarques:
1) Pour les caractères on a suivant le code ASCII (ordre léxicographique):
...< '0' < '1' < '2' < ... <'9'< . . . <'A' < 'B' < 'C' < ... <'Z'< . . . <'a' < 'b' < 'c' ... <'z' <
...

Le caractère '0' a le code ascii 48 (en decimale), le caractère '1' a le code ascii
49, ..., le caractere '9' a le code ascii 57
Le caractère 'A' a le code ascii 65, le caractère 'B' a le code ascii 66, ..., le caractère
'Z' a le code ascii 90
Le caractère 'a' a le code ascii 97, le caractère 'b' a le code ascii 98, ..., le caractère
'z' a le code ascii 122

2) Les chaines de caractères sont comparées selon l'ordre léxicographique.


La chaine vide "" est < à toutes les autres chaines.
Si on a 2 chaines A et B tels que: A = "a1a2a ... am" (m caractères) et B = "b1b2 ...
bn" (n caractères) alors:
A<B si: 'a1' < 'b1' ou ('a1' = 'b1' et "a2a3 ... am" < "b2b3 ... bn")
A>B si: 'a1' > 'b1' ou ('a1' = 'b1' et "a2a3 ... am" > "b2b3 ... bn")
A=B si: 'a1' = 'b1' et "a2a3 ... am" = "b2b3 ... bn" (c'est a dire
exactement le meme nombre de caractères (m=n) et exactement les même
caractères dans le même ordre).

3) Les caractères minuscules et majuscules n'ont pas le même code ASCII.


Si:
S1 contient la chaine "Benali"
S2 contient la chaine "benali"
S3 contient la chaine "Benali"
alors on a (S1 = S3) (ont le même nombre de caractères et ont exactement les
même caractères dans le même ordre) mais on a (S1 <> S2) (ont le même nombre
de caractères mais le caractère 'B' n'est pas égale au caractère 'b').

4.3.5 Applications
Soit ch une chaine de caractères quelconque, écrire un algorithme qui permet de
résoudre chacun des problèmes suivants :
1) La recherche d'un caractère C donné dans une chaine de caractères.

Algorithm rechercheCarChaine;
Var
ch : String;
C : Character;
i, T : Integer;
Trouve : Boolean;
Begin
Write("Donner une chaine de caracteres");
Read(ch);
Write("Donner le caractere a rechercher dans la chaine");
Read(C);

T <--- Length(ch);
i <--- 1;
Trouve <--- False;
While ((i <= T) and (Trouve = False)) Do
If (ch[i] = C) then
Trouve <--- True;
Else
i <--- i + 1;
EIf
Done

If (Trouve = True) then


Write(C, " Trouve");
Else
Write(C, " NON Trouve");
EIf
End.

2) Le calcul du nombre de voyelles contenues dans une chaîne.


Algorithm nbrVoyelles;
Var
ch : String ;
i, nbrVoy, T : Integer;
Begin
Write("Donner une chaine de caracteres");
Read(ch);

nbrVoy <--- 0;
T <--- Length(ch);
For i <--- 1 to T Do
Case (ch[i]) of
'a', 'e', 'i', 'y', 'u', 'o', 'A', 'E', 'I', 'Y', 'U', 'O': nbrVoy <--- nbrVoy + 1;
ECase
Done

Write("Nombre de Voyelles : ", nbrVoy);


End.

3) Le calcul de la fréquence (nombre d'apparitions) de chaque lettre alphabétique


On utilisera un tableau de 26 entiers TabOcc comme compteur de fréquences pour
chacune des lettres de l'alphabet.
TabOcc[1] correspond a freq de 'a'/'A', TabOcc[2] correspond a freq de 'b'/'B',
TabOcc[3] correspond a freq de 'c'/'C', ..., TabOcc[26] correspond a freq de 'z'/'Z'.
Si on a une lettre alphabétique minuscule car (entre 'a' et 'z') pour accéder à son
compteur correspondant on utilise le faite que les caractères sont codés en code
Ascii et ainsi l'indice dans le tableau du compteur est (car - 'a' + 1). Ainsi si car='a'
l'indice est 1, si car='b' l'indice est 2, si car='c' l'indice est 3, si car='d' l'indice est
4 ... si car='z' l'indice est 26.
De même si on a une lettre alphabétique majuscule car (entre 'A' et 'Z') l'indice du
compteur dans le tableau est donné par l'expression (car - 'A' + 1).

Algorithm freqAlphabet;
Var
TabOcc : Array[26] of Integer;
ch : String ;
i, T : Integer;

Begin
Write("Donner une chaine de caracteres");
Read(ch);

/* Initialiser le tableau des frequences a 0.


TabOcc[1] correspond a freq de 'a'/'A',
TabOcc[2] correspond a freq de 'b'/'B',
TabOcc[3] correspond a freq de 'c'/'C',
...
TabOcc[26] correspond a freq de 'z'/'Z'
*/
For i <--- 1 to 26 Do
TabOcc[i] <--- 0;
Done
T <--- Length(ch);
For i <--- 1 to T Do
If ((ch[i] >= 'a' and (ch[i] <= 'z')) then
TabOcc[ch[i] - 'a' + 1] <--- TabOcc[ch[i] - 'a' + 1] + 1;
Else
If ((ch[i] >= 'A' and (ch[i] <= 'Z')) then
TabOcc[ch[i] - 'A' + 1] <--- TabOcc[ch[i] - 'A' + 1] + 1;
ElseIf
EIf
Done

For i <--- 1 to 26 Do
Write("Frequence : ", TabOcc[i]);
Done
End.

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Chapitre 5 - Les Actions Paramétrées

1- Introduction
Lorsqu'on affaire à un problème en informatique il est plus simple de décomposer
le problème initiale en sous-problèmes et de résoudre chacun des sous problèmes
plutot que d'essayer de résoudre le problème initiale en entier.
Exemple
Ecrire un algorithme qui lit 3 vecteurs d'entiers V1, V2 et V3 de tailles réspectives
N1, N2 et N3, puis détermine le minimum de chacun des 3 vecteurs et enfin
effectue la somme des 3 minimum.

Ce probleme peut être decomposé comme::


1) Lire V1 de taille N1
2) Lire V2 de taille N2
3) Lire V3 de taille N3
4) Calculer le Min de V1
5) Calculer le Min de V2
6) Calculer le Min de V3
7) Faire la somme des 3 Min

On remarque que les actions:


1), 2) et 3) sont similaires
4), 5) et 6) sont similaires aussi

On peut écrire l'algorithme comme:


Algorithm SomMin3Vect;
Var
V1, V2, V3: Array[50] of Integer;
N1, N2, N3, min1, min2, min3, SomMin: Integer;

Begin
Repeat
Read(N1);
Until ((N1>=1) and (N1<=50));

Repeat
Read(N2);
Until ((N2>=1) and (N2<=50));

Repeat
Read(N3);
Until ((N3>=1) and (N3<=50));

LireVect(V1, N1);
LireVect(V2, N2);
LireVect(V3, N3);
min1 <--- MinVect(V1, N1);
min2 <--- MinVect(V2, N2);
min3 <--- MinVect(V3, N3);
SomMin <--- min1 + min2 + min3;
Write("Somme des 3 Minimum =", SomMin);
End.

L'algorithme obtenu est modulaire, lisible et simple.

On dit que LireVect() et MinVect() sont des Actions Paramétrées (AP).


LireVect() est une procedure tandis que MinVect() est une fonction. V1, N1, V2,
N2, V3, N3 sont appelés paramètres réels aux actions parametrées LireVect() et
MinVect().

Il faut définir maintenant ces 2 AP. On les définie avec les paramètres génériques
Tab et N appelés paramètres formels.

Procedure LireVect(Tab: Aray[50] of Integer, N: Integer)


var
i: Integer;
Begin
For i <--- 1 to N Do
Read(Tab[i]);
Done
End;

Function MinVect(Tab: Array[50] of Integer, N: Integer): Integer


Var
i, Min: Integer;
Begin
Min <--- Tab[1];
For i <--- 2 to N Do
If (Tab[I] < Min) then
Min <--- Tab[i];
Eif
Done
Return Min;
Fnd;

Lorsqu'on écrit le nom de l'AP dans l'algorithme il y'a appel de l'AP. L'AP est
executé avec les paramètres formels remplacés par les paramètres réels (appelés
aussi arguments). Lorsque l'AP se termine il y'a retour au programme
principale à l'instruction qui suit l'appel de l'AP.

L'utilisation d'AP offre plusieurs avantages:


- Algorithme plus lisible : facilite la compréhension de l'algorithme.
- Mise au point plus simple: facilite la correction des erreurs et l'amélioration de
l'algorithme.
- Possibilté de réeutiliser les APs.
- Algorithme de taille plus réduite.

2- Définition
Une AP est un sous-algorithme auquel on donne un nom et qui contient un certain
nombre d'instructions et à qui à partir de certaines données fournit un certain
nombre de résultats.
Ces données et ces résultats sont appelés Paramètres.
Les données sont les paramètres en Entrée et les résultats sont les paramètres en
sortie.
L'AP est déclarée à l'intèrieur de l'algorithme. L'AP est appelée autant de fois que
nécessaire par l'algorithme principale. Lors de l'appel de l'AP il y'a passation des
paramètres à l'AP, c'est à dire les paramètres réels (arguments) de l'algorithme sont
passés aux paramètres formels de l'AP. Ensuite l'AP s'éxecute et après éxecution
de la dernière instruction de l'AP, il y'a retour à l'algorithme à l'instruction qui suit
l'appel de l'AP (voir figure c-dessous).

3- Structure d'un Algorithme avec Actions Parametrees


Syntaxe

Algorithm <idf_algo>;
Const
<declaration_constantes>
Var
<declaration_variables>

<Declaration des Actions Parametrees>

Begin
<partie_instructions>
End.

La déclaration des actions paramétrées se fait dans la partie des déclarations de


l’algorithme.
L’appel à une action paramétrée se fait dans le corps de l’algorithme (entre Début
et Fin).
Selon le type de résultat que nous voulons avoir, les actions paramétrées sont
divisées en deux catégories: les procédures et les fonctions. Les procédures sont des
actions paramétrées qui fournissent zéro ou plusieurs résultats tandis que les
fonctions sont des actions paramétrées qui fournissent exactement un seul résultat.

4- Les Procédures
4.1 Déclaration d'une Procédure
Syntaxe
Procedure <idf_procedure>(parametre1, parametre2, ...,parametreN)
Var
<decl_Vars_Locales>
Begin

<partie_inst_proc>

End;

<idf_procedure>: Identificateur/Nom de la procedure


Les paramètres parametre1, parametre2, ..., parametreN sont appelés Parametres
Formels. Chaque paramètre formel est définie par un identificateur, un type et un
mode de transmission.
mode de transmission/ identificateur_paramètre :type_paramètre
Le nom et le type du paramètre est définie de la même façon que pour les
variables.
Le mode de transmission spécifie si le paramètre est un paramètre d’entrée, de
sortie ou d’entrée/sortie.
On appelle aussi le mode de transmission Entrée, un passage par valeur et le mode
de transmission Sortie ou Entrée/Sortie un passage par adresse (ou bien par
référence).

Mode de Transmission Symbole


Entrée (Input) I/
Sortie (Output) O/
Entrée/Sortie (Input-Output) I-O/

Remarques:
1) Il est possible de regrouper plusieurs paramètres (séparés par des virgules) quand
ces derniers ont le même type et le même mode de transmission
2) L’ordre des paramètres dans une action paramétrée est important.
3) La partie <partie_inst_proc> est appelee corps de la procedure.
4) Dans <decl_Vars_Locales> on déclare les variables locales à la procedure.

4.2 Appel de la Procédure


Lorsqu'un algorithme veut utiliser une procédure (c.a.d éxecuter les instructions de
la procédure en utilisant les paramètres réels de l'algorithme) il appele (ou il
invoke) cette procédure à travers l'instruction d'appel de la procédure et en donnant
les paramètres réels.

Syntaxe:
<idf_procedure>(param1, param2, ...,paramN);

param1, param2, ...,paramN: sont les paramètres réels (appelés aussi paramètres
effectifs ou bien arguments).

Remarques:
1)Lors de l'appel d'une procédure le nombre de paramètres réels doit être le même
que le nombre de paramètres formels dans la déclaration de la procédure.
2)Chaque paramètre réel correspond au paramètre formel de même rang. Donc
chaque paramètre réel doit avoir le même type que le paramètre formel de même
rang. Chaque paramètre formel est remplacé par le paramètre réel correspondant
lors de l'appel de la procédure.
3) Voici les étapes lors de l'appel de la procédure.
1- Passation de Paramètres Réels à la procédure. Chaque paramètre formel est
remplacé par le paramètre réel du même rang.
2- Execution des instructions de la procédure
3- Après éxecution de la dernière instruction de la procédure,
retour à l'algorithme principale à l'instruction qui est juste après l'appel de la
procédure dans l'algorithme principale.
4) La passation de parametres dépend si c'est une passation par valeur (Entrée) ou
une passation par adresse (Entrée/Sortie ou Sortie). Lors d'une passation de
paramètre par valeur, le paramètre formel est une copie du paramètre réel. Donc si
le paramètre formel est modifié, le paramètre réel n'est pas modifié (c'est la copie
qui est modifié). Lors d'une passation de paramètre par adresse, le paramètre
formel est l'adresse du paramètre réel. Donc si le paramètre formel est modifié, le
paramètre réel est lui aussi modifié. Lorsqu'on déclare une procédure si on veut
que le paramètre réel soit modifié au cas où le paramètre formel correspondant est
modifié lors de l'execution de la procédure on déclare le paramètre formel
correspondant en I-O/ ou en O/; si on ne veut pas que le paramètre réel soit
modifié au cas où le paramètre formel correspondant est modifié on déclare le
paramètre formel en I/.
5) La difference entre un paramètre en I-O/ et un paramètre en O/ est que dans les 2
cas le paramètre réel est modifiable mais dans le cas d'un paramètre en I-O/ la
valeur initiale du paramètre est utilisée en entrée alors que dans le cas d'un
paramètre en O/ la valeur initiale du paramètre n'est pas utilisée. Dans l'exemple ci-
dessous X est en I-O/ car la valeur de X est utilisée en entrée dans l'expression (X +
1) ensuite X est en sortie apres affectation de (X + 1) dans X. Y est en O/ car on
modifie directement Y en mettant 0 dans Y et Y n'est pas utilisee en entrée.
Procedure ExempleSetES(I-O/ X: Entier, O/ Y: Entier)
Begin
X <--- X + 1 ;
Y <--- 0;
End;

4.3 Applications
1) Ecrire une procédure qui calcule le reste et le quotient de la division entière de 2
entiers naturels X et Y.
Procedure CalculRestQuot(I/ X, Y: Integer, O/ Rest, Quot: Integer)
Begin
Rest <--- X ;
Quot <--- 0;
While (Rest >= Y) Do
Quot <--- Quot + 1;
Rest <--- Rest - Y;
Done
End;

2) Ecrire une procedure qui affiche tous les nombres impairs inférieurs à 𝑵 (𝑵 >
𝟎).
Procedure AfficheImpairInfN(I/ N: Integer)
Var
i : Integer;
Begin
i <--- 1;
While (i < N) Do
Write(i);
i <--- i + 2;
Done
End;

5- Les Fonctions
5.1 Déclaration d'une Fonction
Syntaxe
Function <idf_fonction>(parametre1; parametre2; ...;parametreN):
<type_resultat_retourne>
Var
<decl_Vars_Locales>
Begin

<partie_inst_fct>

End;
<idf_fonction>: identificateur (nom) de la fonction
parametre1; parametre2; ...;parametreN: Paramètres formels de la fonction
<type_resultat_retourne>: type du résultat retourne(Entier, Reel, Caractere,
Booleen)
<partie_inst_fct> est le corps de la fonction

5.2 Appel de la Fonction


Syntaxe :
var <--- <idf_fct> (parm1,parm2, ..., paramN) ;

var est une variable qui a le même type que le type du résultat retourné par la
fonction <type_resultat_retourne>

Remarques:
1) Une fonction ne contient que des paramètres d’entrée. Le résultat en sortie est
renvoyé par la fonction elle-même. C’est pour cela qu’il faut spécifier le type de
retour.
2) On utilisera le mot clé retourner pour retourner un résulat dans la
<partie_inst_fct>. Certains en algorithmique mettent le résultat dans le nom de la
fonction pour retourner le résultat (comme dans le langage Pascal).
3) L’appel d’une fonction renvoie directement un résultat et elle est semblable à
une expression. Nous pouvons l’utiliser d’ailleurs, dans une expression.
4) On utilisera une AP comme fonction lorsque l'AP a exactement un seul résultat
et que le type de ce résultat est simple (Integer, Real, Character ou Boolean), ou un
enregistrement ou bien un pointeur (on verra dans les prochains chapitres les
enregistrements et les pointeurs). Dans tous les autres cas on utilisera une
procédure (c'est à dire soit l'AP a 0 ou plus qu'un résultat ou bien elle a un seul
résultat et que ce résultat est un tableau ou bien une chaine de caractères).

5.3 Applications
1) Fonction qui calcule X puissance N pour X réel et N entier.
Function Puissance(X:Real, N:Integer):Real
Var
i: Integer;
p : Real;
Begin
p <-- 1;
For i <--1 to N Do
p <-- p * X;
Done
Return p;
End;
2) Fonction qui calcule factoriel N entier.
Function Factoriel(N:Integer):Integer
Var
i, fact: Integer;
Begin
fact <-- 1;
For i <--1 to N Do
fact <-- fact * i;
Done
Return fact;
Ed;

3) Fonction qui indique si un caractère donné est une voyelle minuscule ou non.
Function Voyelle(C:Character):Boolean
Var
voy: Boolean;
Begin
Case (C) of
'a', 'i', 'e', 'u', 'y', 'o':
voy <--- True;
Else
voy <--- False;
ECase
Return voy;
End;

6 - Les Variables Locales et les Variables Globales


6.1 Les Variables Locales
Les variables locales à une AP sont les variables declarées à l'interieur de l'AP.
Elles sont utilisables uniquement à l'interieur de l'AP et ne peuvent pas etre
utilisées à l'exterieur de l'AP. Elles existent uniquement lors de l'execution de l'AP
et elles cessent d'exister après le retour de l'AP.

Exemple
Algorithm AlgorithmeDePermutation;
Var
X, Y : Integer;

Procedure Permuter (I-O/ a, b : Integer)


Var
temp : Integer;
/*La variable temp est une variable locale, elle n’est visible que dans la
procédure Permuter */
Begin
temp <--- a;
a <--- b;
b <--- temp;
End;

Begin
Read (X, Y);
Permuter (X, Y);
Write (X, Y);
End.

6.2 Les Variables Globales


Les variables globales sont les variables declarées dans la partie déclaration des
variables dans l'algorithme principale. Elles sont utilisables dans l'algorithme
principale comme elles peuvent être utilisées dans les APs. Les variables globales
existent durant tout le temps d'execution du programme principale.

Exemple
Algorithm AlgorithmeDePermutation;
Var
X, Y : Integer;
temp : Integer;
/*La variable temp est une variable globale, elle peut etre utilise dans l'algorithme
principale
comme elle peut etre utilise dans la procédure Permuter */

Procedure Permuter (I-O/ a, b : Integer)


Begin
temp <--- a;
a <--- b;
b <--- temp;
End;

Begin
Read (X, Y);
Permuter (X, Y);
Write(X, Y);
End.
Remarque:
1) On peut avoir une variable globale et une variable locale qui ont le même nom.
La variable utilisée dans l'AP est toujours la variable locale.
2) Il faut autant que possible éviter d'utiliser des variables globales car cela peut
produire des erreurs de logique due aux effets de bord (side effect).

Exemple
Derouler l'algorithme suivant:
Algorithm VarGlobLoc;
Var
N, M: Integer;
Procedure ProcAfficher()
Var
N:Integer;
Begin
P1) N <-- 1;
P2) Write(N, M);
P3) M <--- 122;
P4) Write(N, M);
End;

Begin
1) N <--- 99;
2) M <--- 199;
3) ProcAfficher();
4) Write(N, M);
End.

Variables Globales Variable Locale Ecran


Instruction N M N
1) 99 ?
2) 99 199
3) - P1) 99 199 1
P2) 99 199 1 1 199
P3) 99 122 1 1 199
P4) 99 122 1 1 199
1 122
4) 99 122 1 199
1 122
99 122
7 - Appel d'une AP par une autre AP
Une AP AP1 peut appeler une autre AP AP2. Dans ce cas on écrira AP2 avant AP1
dans l'algorithme.
Exemple.
Ecrire une fonction qui vérifie si deux entiers naturels sont frères (càd ont la même
somme des chiffres qui les composent). On utilisera pour cela la fonction ci-
dessous SomChfr() qui retourne la somme des chiffres d'un nombre.

Function SomChfr(N:Integer):Integer
Var
Som: Integer;
Begin
Som <--- 0;
While (N <> 0) Do
Som <--- Som + (N mod 10);
N <--- N Div 10;
Done

Return Som;
Fin;

Function EntFreres(X, Y:Integer):Boolean


Var
S1, S2: Integer;
Begin
S1 <--- SomChfr(X);
S2 <--- SomChfr(Y);

If (S1 = S2) then


Return True;
Else
Return False;
Eif

End;

Remarques:
1) Une AP peut s'appeler elle même. On parle dans ce cas d'AP récursive.
2) Certains langages de programmation (comme le langage Pascal) permettent
l'imbrication d'APs, c'est à dire d'avoir des APs declarées à l'intérieur d'autres APs.
Dans ce cas ces APs sont connues uniquement à l'interieur de l'AP dans laquelle
elles sont declarées. D'autres langages (comme le langage C) ne le permettent pas.
Pour le langage algorithmique qu'on utilise on adopte la même chose que le langage
C, c'est à dire qu'on ne peut pas avoir des APs imbriquées.

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Les Enregistrements (Records)
1- Introduction
Jusqu'a présent on a vu les tableaux qui sont une structure de données qui permet de
regrouper ensemble des données de même type. Mais il arrive souvent qu'on a une
entité qui a plusieurs attributs qui ont des types qui peuvent être différents. Par
exemple on a une entité Etudiant représentant un étudiant qui a comme attributs
nom, prenom, matricule, section, groupe et moyenne. Il est plus simple de
regrouper ensemble ces attributs dans un nouveau type et de manipuler une seule
variable de ce nouveau type plutôt que d'avoir plusieurs variables, une variable
pour chaque attribut. Pour cela on utilise ce qu'on appelle des enregistrements.

2- Définition
Un enregistrement est un type de données qui permet de regrouper un certain
nombre d'éléments qui peuvent avoir des types différents. Ces éléments sont
appelés champs (ou attributs). Ces champs peuvent être de type simple (entier, réel,
caractère, booléen), de type composé (tableau, chaines de caractères) ou bien
d'autres enregistrements.

3- Déclaration

Algorithm nomAlgorithme;
<declaration_Types>
Const
<declaration_constantes>
Var
<declaration_variables>

<declaration_actions_parametrees>

Begin
<partie_instructions>
End.
Partie Déclaration des Types: <declaration_Types>
Type
nom_type = Record
<nom_champ1> : <type_champ1>;
<nom_champ2> : <type_champ2>;
...
<nom_champN> : <type_champN>;
End;

Déclaration d'une variable de type enregistrement


Var
nom_var : <nom_type>;

Exemple
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;

Remarque:
Si on a plusieurs enregistrements on les écrit l'un à la suite de l'autre mais on écrit
une seule fois le mot clé Type.

4- Accés aux champs d'un Enregistrement


Pour accéder à un champ d'un enregistrement on écrit: nom_var.nom_champ
Exemple:
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;
Var
etd : Etudiant;
Affectation à un champ
etd.matricule <--- 1267;
etd.section <--- 1;
etd.groupe <--- 3;
end.moy <--- 12.5;

Lecture d'un champ


Read(etd.nom);
Read(etd.prenom);
Read(etd.matricule, etd.section, etd.groupe, etd.moy);

Ecriture d'un champ


Write(etd.nom, etd.prenom, etd.matricule, etd.section, etd.groupe, etd.moy);

5- Opérations entre Enregistrements


5.1 Affectation
Contrairement aux tableaux, on peut affecter une variable de type enregistrement à
une autre variable du même type d'enregistrement. Cela revient à faire une
affectation champ par champ.
Exemple:
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;
Var
etd1, etd2 : Etudiant;

etd2 <--- etd1;


est equivalent a:
etd2.nom <--- etd1.nom;
etd2.prenom <--- etd1.prenom;
etd2.matricule <--- etd1.matricule;
etd2.section <--- etd1.section;
etd2.groupe <--- etd1.groupe;
etd2.moy <--- etd1.moy;

5.2 Comparaison
On ne peut pas comparer 2 enregistrements de même type il faut faire la
comparaison champ par champ.
Exemple:
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;
Var
etd1, etd2 : Etudiant;

L'ecriture:
If etd1=etd2 alors
...
Eif

est incorrecte

6- Tableaux d'Enregistrements
Exemple
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;

Var
TabEtd : Array[100] Of Etudiant;

Lecture des N premiers etudiants


Repeat
Read(N);
Until (N>0) et (N<=100);
For i <--- 1 to N Do
Read(TabEtd[i].nom, TabEtd[i].prenom, TabEtd[i].matricule, TabEtd[i].section,
TabEtd[i].groupe, TabEtd[i].moy);
Done

7- Imbrication d'Enregistrements
On peut avoir un enregistrement à l'intérieur d'un autre enregistrement.
Exemple
Type
Date = Record
jour, mois, annee : Integer;
End;
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
dateNaiss: Date;
moy : Real;
End;
Var
etd : Etudiant;

Read(etd.nom, etd.prenom, etd.matricule, etd.section, etd.groupe,


etd.dateNaiss.jour, etd.dateNaiss.mois, etd.dateNaiss.annee, etd.moy);

8- Enregistrements et Actions Paramétrées (AP)


8.1 Passation d'un Enregistrement comme Parametre à une AP
Un enregistrement peut être passé par valeur comme il peut être passé par adresse à
une AP.
Dans le cas où l'enregistrement est passé par valeur le paramètre formel est une
copie du paramètre réel. Donc si le paramètre formel est modifié le paramètre réel
n'est pas modifié. Dans le cas de passation par adresse le paramètre formel est
l'adresse du paramètre réel.
8.2 Fonction et Enregistrement comme Résultat
Comme dans le langage C on va considérer que en Algorithmique une fonction
peut retourner un enregistrement.

9- Utilisation de Type pour les Tableaux


On peut utiliser le Type pour définir des types pour les tableaux.
Exemple: Calculer la moyenne d'un tableau d'entiers en utilisant une fonction
Algorithm MoyTableau;
Type
Tab = Array[100] of Real;
Var
T : Tab;
N, i : Integer;

Function MoyTabl(V:Tab, N:Integer): Real


Var
moy : Real;
i : Integer;
Begin
moy <--- 0;
For i <--- 1 to N Do
moy <--- moy + V[i];
Done
moy <--- moy / N;
Return moy;
End;

Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
/* Remplir le Tableau T */
For i <--- 1 to N Do
Write("Donner ", i , " eme element du Tableau");
Read(T[i]);
Done
Write("La moyene du Tableau = ", MoyTab(T, N));
End.

11- Application
Soit le type enregistrement suivant :
Etudiant = Record
Matricule : chaîne[12];
Nom, Prenom: chaine[20];
Moyenne : real;
End;
Soit T un tableau d’au plus 100 étudiants. Ecrire un algorithme permettant de
recopier tous les étudiants admis appartenant à T dans un tableau ADMIS de type
étudiant. Un étudiant est admis si sa moyenne est supèrieure ou égale à 10.

Solution
Algorithm EtudiantsAdmis;
Type
Etudiant = Record
Matricule : string[12];
Nom, Prenom: string[20];
Moyenne : real;
End;
Var
T, Admis: Array[100] of Etudiant;
i, J, N: Integer;

Begin
Repeat
Write("Donner N Compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner Matricule, Nom, Prenom et Moyenne du ", i, " eme Etudiant");
Read(T[i].Matricule, T[i].Nom, T[i].Prenom, T[i].Moyenne);
Don
J <--- 0;
For i <--- 1 to N Do
If (T[i].Moyenne >= 10) Then
J <--- J + 1;
Admis[J] <--- T[i];
Eif
Done

If (J = 0) Then
Write("Il n'y a pas d'etudiants admis");
Else
Write("Liste des Etudiants Admis:");
For i <--- 1 to J Do
Write(Admis[i].Matricule, Admis[i].Nom, Admis[i].Prenom,
Admis[i].Moyenne);
Done
Eif
End.

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Les Enregistrements (Records)
1- Introduction
Jusqu'a présent on a vu les tableaux qui sont une structure de données qui permet de
regrouper ensemble des données de même type. Mais il arrive souvent qu'on a une
entité qui a plusieurs attributs qui ont des types qui peuvent être différents. Par
exemple on a une entité Etudiant représentant un étudiant qui a comme attributs
nom, prenom, matricule, section, groupe et moyenne. Il est plus simple de
regrouper ensemble ces attributs dans un nouveau type et de manipuler une seule
variable de ce nouveau type plutôt que d'avoir plusieurs variables, une variable
pour chaque attribut. Pour cela on utilise ce qu'on appelle des enregistrements.

2- Définition
Un enregistrement est un type de données qui permet de regrouper un certain
nombre d'éléments qui peuvent avoir des types différents. Ces éléments sont
appelés champs (ou attributs). Ces champs peuvent être de type simple (entier, réel,
caractère, booléen), de type composé (tableau, chaines de caractères) ou bien
d'autres enregistrements.

3- Déclaration

Algorithm nomAlgorithme;
<declaration_Types>
Const
<declaration_constantes>
Var
<declaration_variables>

<declaration_actions_parametrees>

Begin
<partie_instructions>
End.

Partie Déclaration des Types: <declaration_Types>


Type
nom_type = Record
<nom_champ1> : <type_champ1>;
<nom_champ2> : <type_champ2>;
...
<nom_champN> : <type_champN>;
End;

Déclaration d'une variable de type enregistrement


Var
nom_var : <nom_type>;

Exemple
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;

Remarque:
Si on a plusieurs enregistrements on les écrit l'un à la suite de l'autre mais on écrit
une seule fois le mot clé Type.

4- Accés aux champs d'un Enregistrement


Pour accéder à un champ d'un enregistrement on écrit: nom_var.nom_champ
Exemple:
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;
Var
etd : Etudiant;
Affectation à un champ
etd.matricule <--- 1267;
etd.section <--- 1;
etd.groupe <--- 3;
end.moy <--- 12.5;

Lecture d'un champ


Read(etd.nom);
Read(etd.prenom);
Read(etd.matricule, etd.section, etd.groupe, etd.moy);

Ecriture d'un champ


Write(etd.nom, etd.prenom, etd.matricule, etd.section, etd.groupe, etd.moy);

5- Opérations entre Enregistrements


5.1 Affectation
Contrairement aux tableaux, on peut affecter une variable de type enregistrement à
une autre variable du même type d'enregistrement. Cela revient à faire une
affectation champ par champ.
Exemple:
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;
Var
etd1, etd2 : Etudiant;

etd2 <--- etd1;


est equivalent a:
etd2.nom <--- etd1.nom;
etd2.prenom <--- etd1.prenom;
etd2.matricule <--- etd1.matricule;
etd2.section <--- etd1.section;
etd2.groupe <--- etd1.groupe;
etd2.moy <--- etd1.moy;

5.2 Comparaison
On ne peut pas comparer 2 enregistrements de même type il faut faire la
comparaison champ par champ.
Exemple:
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;
Var
etd1, etd2 : Etudiant;

L'ecriture:
If etd1=etd2 alors
...
Eif
est incorrecte

6- Tableaux d'Enregistrements
Exemple
Type
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
moy : Real;
End;

Var
TabEtd : Array[100] Of Etudiant;

Lecture des N premiers etudiants


Repeat
Read(N);
Until (N>0) et (N<=100);
For i <--- 1 to N Do
Read(TabEtd[i].nom, TabEtd[i].prenom, TabEtd[i].matricule, TabEtd[i].section,
TabEtd[i].groupe, TabEtd[i].moy);
Done

7- Imbrication d'Enregistrements
On peut avoir un enregistrement à l'intérieur d'un autre enregistrement.
Exemple
Type
Date = Record
jour, mois, annee : Integer;
End;
Etudiant=Record
nom, prenom : String;
matricule : Integer;
section : Integer;
groupe : Integer;
dateNaiss: Date;
moy : Real;
End;
Var
etd : Etudiant;

Read(etd.nom, etd.prenom, etd.matricule, etd.section, etd.groupe,


etd.dateNaiss.jour, etd.dateNaiss.mois, etd.dateNaiss.annee, etd.moy);

8- Enregistrements et Actions Paramétrées (AP)


8.1 Passation d'un Enregistrement comme Parametre à une AP
Un enregistrement peut être passé par valeur comme il peut être passé par adresse à
une AP.
Dans le cas où l'enregistrement est passé par valeur le paramètre formel est une
copie du paramètre réel. Donc si le paramètre formel est modifié le paramètre réel
n'est pas modifié. Dans le cas de passation par adresse le paramètre formel est
l'adresse du paramètre réel.
8.2 Fonction et Enregistrement comme Résultat
Comme dans le langage C on va considérer que en Algorithmique une fonction
peut retourner un enregistrement.

9- Utilisation de Type pour les Tableaux


On peut utiliser le Type pour définir des types pour les tableaux.
Exemple: Calculer la moyenne d'un tableau d'entiers en utilisant une fonction
Algorithm MoyTableau;
Type
Tab = Array[100] of Real;
Var
T : Tab;
N, i : Integer;

Function MoyTabl(V:Tab, N:Integer): Real


Var
moy : Real;
i : Integer;
Begin
moy <--- 0;
For i <--- 1 to N Do
moy <--- moy + V[i];
Done
moy <--- moy / N;
Return moy;
End;

Begin
Repeat
Write("Donner N compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
/* Remplir le Tableau T */
For i <--- 1 to N Do
Write("Donner ", i , " eme element du Tableau");
Read(T[i]);
Done
Write("La moyene du Tableau = ", MoyTab(T, N));
End.

11- Application
Soit le type enregistrement suivant :
Etudiant = Record
Matricule : chaîne[12];
Nom, Prenom: chaine[20];
Moyenne : real;
End;
Soit T un tableau d’au plus 100 étudiants. Ecrire un algorithme permettant de
recopier tous les étudiants admis appartenant à T dans un tableau ADMIS de type
étudiant. Un étudiant est admis si sa moyenne est supèrieure ou égale à 10.

Solution
Algorithm EtudiantsAdmis;
Type
Etudiant = Record
Matricule : string[12];
Nom, Prenom: string[20];
Moyenne : real;
End;
Var
T, Admis: Array[100] of Etudiant;
i, J, N: Integer;

Begin
Repeat
Write("Donner N Compris entre 1 et 100");
Read(N);
Until ((N>=1) and (N<=100));
For i <--- 1 to N Do
Write("Donner Matricule, Nom, Prenom et Moyenne du ", i, " eme Etudiant");
Read(T[i].Matricule, T[i].Nom, T[i].Prenom, T[i].Moyenne);
Don
J <--- 0;
For i <--- 1 to N Do
If (T[i].Moyenne >= 10) Then
J <--- J + 1;
Admis[J] <--- T[i];
Eif
Done

If (J = 0) Then
Write("Il n'y a pas d'etudiants admis");
Else
Write("Liste des Etudiants Admis:");
For i <--- 1 to J Do
Write(Admis[i].Matricule, Admis[i].Nom, Admis[i].Prenom,
Admis[i].Moyenne);
Done
Eif
End.

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Les Fichiers Séquentiels

1- Introduction
Jusqu'a présent on a écrit des programmes où on saisit des données à partir du
clavier, on fait un traitement puis on affiche les résultats de ce traitement sur écran.
Mais à la fin du programme on perd ces informations car la mémoire centrale est
volatile. Le but des fichiers est de conserver ces informations après l'arrêt du
programme pour pouvoir les utiliser plus tard. Cela amène à sauvegarder ces
informations sur une mémoire secondaire (disque dur, cle usb, ...).

2- Définition
Un fichier est un ensemble d'informations stockés sur un support physique non
volatile (disque dur, cle usb, ...). Un fichier a un nom physique. Le nom physique
utilisé est généralement sous la forme: "nom_physique.ext" où ext est l'extension
qui détermine le format de fichier.

Exemple d'extension de fichier:


.txt : fichier texte
.c : fichier source en C
.pdf : fichier pdf
.jpg ou .jpeg: fichier image format jpeg
.zip : fichier compresse sous forme zip
.doc ou .docx : fichier microsoft word

3- Types de Fichiers
Il existe 2 types de fichiers: Les fichiers texte et les fichiers binaires. Un fichier
texte est composé d'une suite de caractères formant une ou plusieurs lignes de texte.
Le code ASCII (American Standard Code for Information Interchange)
est généralement utilisé pour coder les caractères. Les fichiers textes peuvent etre
visualisés en utilisant un éditeur de texte (notepad, wordpad, ...).
Les fichiers binaires sont des fichiers contenant une suite de 0 et de 1 sous forme
d'octets dont le format est particulier à un type de fichier bien précis (fichier
jpg/jpeg pour image jpeg, fichier videos mpeg, fichier son mp3, ...). Ces fichiers ne
peuvent être ouvert qu'avec leur programme correspondant et ne peuvent être
visualisés avec un editeur de texte. Un fichier binaire peut être sauvegardé sous
forme d'une séquence d'enregistrements de même type; dans ce cas un élément du
fichier est un enregistrement. Les éléments d'un fichier ont tous le même type.

4- Accés à un Fichier
Il existe 2 types d'accés à un fichier: accés séquentiel et accés direct (aléatoire).
Dans un fichier on a une tête de Lecture/Ecriture qui permet d'accéder aux éléments
du fichier en lecture ou bien en écriture.
Dans le cas de l'accés séquentiel, le fichier est parcouru de manière séquentielle par
la tête de lecture/écriture dans l'ordre dans lequel se trouvent les éléments du début
jusqu'a l'élément souhaité ou bien jusqu'à la fin du fichier. On ne peut accéder à un
élément qu'après avoir accéder à l'élément précédent. L'élément sur lequel pointe la
tête de lecture/écriture est appelé l'élément courant.
Dans le cas d'un accés direct, on accède directement à un élément en precisant le
numéro de cet élément. On utilise l'accés directe principalement dans la mise à jour
des fichiers.

Dans un fichier à accés séquentiel les règles suivantes doivent être satisfaites:
- L'insertion d'un élément se fait à la fin du fichier.
- On ne peut pas modifer un élément directement sur le fichier existant.

En cours et en TD on va considerer uniquement les fichiers à acces séquentiel.


5- Memoire Tampon
Une mémoire tampon (buffer) est une région de la mémoire vive (RAM: Random
Access Memory) utilisée pour contenir de manière temporaire des données. Elle est
utilisée car la lecture/écriture en mémoire secondaire prend beaucoup plus de temps
que la lecture/écriture en mémoire vive. Accéder à une donnée sur le disque dur est
de l'ordre de millisecondes tandis que accéder à une donnée sur la RAM est de
l'ordre de nanosecondes. Donc l'utilisation de mémoire tampon permet de ne pas
ralentir l'execution des programmes en mémoire centrale.

6- Declaration d'un Fichier


En mémoire secondaire (support externe) un fichier a un nom physique. Dans un
programme un fichier a un nom logique.
La syntaxe pour déclarer un fichier dans un programme (nom logique) est:
Var
<nom_logique> : File of <type_element>;

<nom_logique> : Nom logique du fichier


<type_element> : Type des elements du fichier

Exemple:
Type
Etudiant=Record
nom: string;
prenom: string;
matricule: integer;
moyenne: real;
End;
Var
FEnt : File of integer;
FReel: File of Real;
FEtud: File of Etudiant;

7- Instructions de Manipulation des Fichiers


7.1 Assignation
L'assignation consiste à faire le lien entre le nom logique et le nom physique du
fichier.
Syntaxe:
Assign(<nom_logique> , <nom_physique>);

Exemple:
Type
Etudiant=Record
nom: string;
prenom: string;
matricule: integer;
moyenne: real;
End;
Var
FEtud: File of Etudiant;

Begin
Assign(FEtud, "FEtudiant.dat");
...

7.2 Ouverture
Dans un algorithme après avoir fait l'assignation d'un fichier il faut ouvrir le fichier
pour pouvoir l'utiliser. Un fichier peut être ouvert en lecture ou bien en écriture.

7.2.1 Ouverture en Lecture


On ouvre en lecture un fichier existant pour pouvoir lire ce fichier. L'ouverture d'un
fichier en lecture consiste à positionner la tête de lecture/écriture au début du
fichier. Il faut noter que la tête de lecture/écriture est associée au nom logique du
fichier (et non pas au nom physique du fichier).
Syntaxe:
ReRead(<nom_logique>);

Le fichier doit d'abord exister avant de faire une ouverture en lecture.

7.2.2 Ouverture en Ecriture


On ouvre un fichier en écriture lorsqu'on veut créer ce fichier. L'ouverture d'un
fichier en écriture consiste à créer un fichier vide et à positionner la tête de
lecture/écriture au début du fichier. Si le fichier existe déja son contenu sera ecrasé.
Syntaxe:
ReWrite(<nom_logique>);

7.3 Fermeture
Lorsqu'on a terminé la manipulation d'un fichier on ferme ce fichier.
Syntaxe:
Close(<nom_logique>);

7.4 Lecture
La lecture consiste à lire l'élément courant (généralement un enregistrement) du
fichier. L'élément courant est l'élément où la tête de lecture/écriture est positionnée.
Apres lecture de l'élément courant, la tête de lecture/écriture avance
automatiquement à l'élément suivant de manière sequentielle.
Syntaxe:
Lire(<nom_logique>, <var_elt>);
<var_elt> est une variable du même type qu'un élément du fichier.
Read(<nom_logique>, <var_elt>) met le contenu de l'élément courant du fichier
dans <var_elt>.

7.5 Ecriture
L'ecriture consiste à ecrire dans la position courante de la tête de lecture/écriture du
fichier un élément (généralement un enregistrement) dont le contenu est dans une
variable du même type qu'un élément du fichier. Après écriture dans la position
courante, la tête de lecture/écriture avance automatiquement d'une position de
manière séquentielle.
Syntaxe:
Write(<nom_logique>, <var_elt>);
<var_elt> est une variable du même type qu'un élément du fichier et qui contient
l'élément à écrire.
Ecrire(<nom_logique>, <var_elt>) écrit le contenu de <var_elt> dans la position
courante du fichier.

7.6 Fin de Fichier


Lorsqu'on lit un fichier existant il faut savoir détecter la fin de fichier. La fonction
EOF permet de faire cela. Après avoir lu le dernier élément du fichier, la fonction
EOF retourne True (Vrai) comme indication qu'on a atteint la fin de fichier.
Syntaxe:
EOF(<nom_logique>)

8- Type File Of
On peut declarer le type: File of <type>
Exemple
Type
Etudiant=Record
nom: string;
prenom: string;
matricule: integer;
moyenne: real;
End;
FichEtudiant = File of Etudiant;

Var
FEtud: FichEtudiant;

9- Applications
9.1- Creation d'un fichier
Soit l'enregistrement:
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;

Soit N un entier >= 1 donne par l'utilisateur.


Ecrire un algorithme permettant de créer un fichiers de N étudiants où les
informations de chaque étudiant (matricule, nom, prenom et moyenne) sont
données par l'utilisateur.

Algorithm CreerFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd : File of Etudiant;
etd: Etudiant;
i, N: integer;
Begin
Repeat
Write("Donner N Entier >= 1");
Read(N);
Until (N>0);

Assign(FEtd, "FichierEtudiants");
ReWrite(FEtd);
For i <--- 1 to N Do
Write ("Donner Matricule, Nom, Prenom et Moyenne du ", i, " eme etudiant");
Read(etd.matricule, etd.nom, etd.prenom, etd.moyenne);
Write(FEtd, etd);
Done
Close(FEtd);
End.

9.2- Consultation/Lecture d'un fichier


Ecrire un algorithme permettant de lire un fichier existant d'étudiants (fichier
"FichierEtudiants") et d'afficher les informations de chaque étudiant.

Algorithm LireFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd : File of Etudiant;
etd : Etudiant;
Begin
Assign(FEtd, "FichierEtudiants");
ReRead(FEtd);
While (NOT(EOF(FEtd))) Do
Read(FEtd, etd);
Write(etd.matricule, etd.nom, etd.prenom, etd.moyenne);
Done
Close(FEtd);
End.

9.3- Recopiage d'un fichier dans un autre Fichier


Ecrire un algorithme permettant de recopier un fichier existant d'étudiants (fichier
"FichierEtudiants") dans un autre fichier (fichier "FichierEtudiantsCopy").

Algorithm RecopyFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd, FEtdCopy : File of Etudiant;
etd : Etudiant;
Begin
Assign(FEtd, "FichierEtudiants");
Assign(FEtdCopy, "FichierEtudiantsCopy");
ReRead(FEtd);
ReWrite(FEtdCopy);
While (NOT(EOF(FEtd))) Do
Read(FEtd, etd);
Write(FEtdCopy, etd);
Done
Close(FEtd);
Close(FEtdCopy);
End.

9.4- Recherche d'un élément dans un Fichier


L'utilisateur donne un matricule et l'algorithme recherche l'étudiant ayant ce
matricule dans le fichier "FichierEtudiants". Si le matricule existe dans le fichier,
l'algorithme affiche le nom, le prénom et la moyenne de l'etudiant. Si le matricule
n'existe pas dans le fichier, l'algorithme affiche un message indiquant qu'il n'existe
pas d'étudiant ayant le matricule donné.

Algorithm RechercheEltDansFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd : File of Etudiant;
etd : Etudiant;
matricule: integer;
Trouve : Boolean;
Begin
Assign(FEtd, "FichierEtudiants");
ReRead(FEtd);
Write("Donner matricule de Etudiant a Rechercher dans FichierEtudiants");
Read(matricule);
Trouve <--- False;
While (NOT(EOF(FEtd)) and (Trouve = False)) Do
Read(FEtd, etd);
If (etd.matricule = matricule)) then
Trouve <--- True;
Eif
Done
Close(FEtd);
If (Trouve = False) then
Write("Matricule: ", matricule, " ne se trouve pas dans le fichier");
Else
Write("Etudiant Nom:", etd.nom, "Prenom: ", etd.prenom, "Matricule: ",
etd.matricule, " et Moyenne:", etd.moyenne);
Eif
End.

9.5- Mise à Jour d'un Fichier


9.5.1- Ajout au contenu d'un Fichier à la fin
L'utilisateur donne nom, prénom, matricule et moyenne d'un étudiant et
l'algorithme ajoute un enregistrement de cet etudiant à la fin du fichier. En
algorithmique on ne peut pas ajouter directement un contenu à un fichier.
Pour cela il faut utiliser un fichier temporaire. Après l'assignation des 2 fichiers,
ouvrir le fichier initiale en lecture et le fichier temporaire en écriture. Recopier le
fichier initiale au fichier temporaire, ajouter ce qu'on a à ajouter au fichier
temporaire et ensuite fermer les 2 fichiers. A la fin il faut ouvrir le fichier
temporaire en lecture et le fichier initiale en écriture et recopier le contenu du
fichier temporaire au fichier initiale et enfin fermer les 2 fichiers.
Remarque: on suppose que le champ matricule de l'enregistrement record Etudiant
est unique pour chaque etudiant. On suppose aussi que le matricule donné de
l'etudiant à ajouter au fichier n'existe pas deja dans le fichier (sinon il aurait fallu
indiquer une erreur dans le cas ou le matricule existe deja).

Algorithme AjoutFinFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd, FTemp : File of Etudiant;
etd : Etudiant;
Begin
Assign(FEtd, "FichierEtudiants");
Assign(FTemp, "FichTemp");
ReRead(FEtd);
ReWrite(FTemp);
While (NOT(EOF(FEtd))) Do
Read(FEtd, etd);
Write(FTemp, etd);
Done
Close(FEtd);
Write("Donner Nom, Prenom, Matricule et moyenne de Etudiant a ajouter au
Fichier Etudiant");
Read(etd.nom, etd.prenom, etd.matricule, etd.moyenne);
Write(FTemp, etd);
Close(FTemp);

/* Recopier maintenant FTemp dans FEtd */


ReRead(FTemp);
ReWrite(FEtd);
While (NOT(EOF(FTemp))) Do
Read(FTemp, etd);
Write(FEtd, etd);
Done
Close(FEtd);
Close(FTemp);
End.

9.5.2- Suppression d'un élément d'un Fichier


L'utilisateur donne un matricule et l'algorithme supprime l'enregistrement de cet
étudiant du fichier "FichierEtudiants" (en supposant que l'élément existe dans le
fichier). Comme on ne peut pas supprimer directement d'un fichier, on utilise un
fichier intermediare où on recopie tous les etudiants du fichier initiale sauf celui
qu'on veut supprimer. A la fin on recopie le fichier intermediare dans le fichier
initiale.

Algorithm SuppressionFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd, FTemp : File of Etudiant;
etd : Etudiant;
mat : integer;
Trouve : Boolean;
Begin
Assign(FEtd, "FichierEtudiants");
Assign(FTemp, "FichTemp");
ReRead(FEtd);
ReWrite(FTemp);
Write("Donner Matricule de Etudiant a supprimer du Fichier Etudiant");
Read(mat);
Trouve <--- False;
While (NOT(EOF(FEtd))) Do
Read(FEtd, etd);
If (etd.matricule <> mat) then
Write(FTemp, etd);
Else
Trouve <--- True;
Eif
Done
If (Trouve = False) // Le matricule a supprimer ne se trouve pas dans le fichier
Then
Write("Erreur Matricule:", mat, " Net se Trouve Pas dans le fichier");
Else
Write("Matricule:", mat, " a ete Supprime du fichier");
Close(FEtd);
Close(FTemp)'

/* Recopier maintenant FTemp dans FEtd */


ReRead(FTemp);
ReWrite(FEtd);
While (NOT(EOF(FTemp))) Do
Read(FTemp, etd);
Write(FEtd, etd);
Done
Eif
Close(FEtd);
Close(FTemp);
End.

9.5.3- Modification d'un élément d'un Fichier


L'utilisateur donne un matricule et une nouvelle moyenne et l'algorithme modifie la
moyenne de cet étudiant dans le fichier "FichierEtudiant" si le matricule de
l'étudiant existe. Comme on ne peut pas modifier directement le fichier on utilisera
un fichier intermediare.

Algorithm ModiferFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd, FTemp : File of Etudiant;
etd : Etudiant;
matricule : integer;
moyenne : Real;
Trouve : Boolean;
Begin
Assign(FEtd, "FichierEtudiants");
Assign(FTemp, "FichTemp");
ReRead(FEtd);
ReWrite(FTemp);
Write("Donner Matricule et Moyenne de Etudiant a modifier dans Fichier
Etudiant");
Read(matricule, moyenne);

Trouve <--- False;


While ( (NOT(EOF(FEtd)) and (Trouve = False)) Do
Read(FEtd, etd);
If (etd.matricule = matricule) then
Trouve <--- True;
Else
Write(FTemp, etd);
Eif
Done

If (Trouve = False) then


Write("Erreur Etudiant Matricule:", matricule, " n'existe pas dans le fichier
etudiant");
Else
etd.moyenne <--- moyenne;
Write(FTemp, etd);
/* Recopier reste de FEtd dans FTemp */
While (NOT(EOF(FEtd))) Do
Read(FEtd, etd);
Write(FTemp, etd);
Done
Close(FEtd);
Close(FTemp);

/* Recopier maintenant FTemp dans FEtd */


ReRead(FTemp);
ReWrite(FEtd);
While (NOT(EOF(FTemp))) Do
Read(FTemp, etd);
Write(FEtd, etd);
Done
Eif
Close(FEtd);
Close(FTemp);
End.

9.5.4- Ajout au contenu d'un Fichier selon un critère


En supposant que le fichier d'étudiant est trié par ordre croissant selon le champ
matricule, le critère ici est qu'on veut ajouter un étudiant au fichier à la bonne place
de manière à garder le fichier toujours trié par ordre croissant selon le champ
matricule. Comme les applications précédentes de mise à jour il faudra utiliser un
fichier intermediare.

Algorithm AjoutTriFichEtudiant;
Type
Etudiant=Record
nom,prenom: string[20];
matricule: integer;
moyenne: real;
End;
Var
FEtd, FTemp : File of Etudiant;
etd1, etd2 : Etudiant;
tri : Boolean;
Begin
Assign(FEtd, "FichierEtudiants");
Assign(FTemp, "FichTemp");
ReRead(FEtd);
ReWrite(FTemp);
Write("Donner Nom, Prenom, Matricule et moyenne de Etudiant a ajouter au
Fichier Etudiant");
Read(etd2.nom, etd2.prenom, etd2.matricule, etd2.moyenne);

tri <--- True;


While ( (NOT(EOF(FEtd)) and (tri = True)) Do
Read(FEtd, etd1);
If (etd1.matricule < etd2.matricule) then.
Write(FTemp, etd1);
Else
tri <--- False;
Eif
Done
// indiquer erreur dans le cas ou le matricule donne existe deja dans le fichie
If (etd1.matricule = etd2.matricule) then
Write("Matricule :", etd2.matricule, " existe deja dans le fichier");
Else
/* Ecrire l'element a ajouter */
Write(FTemp, etd2);
If (tri = False) then
Write(FTemp, etd1); /* ecrire l'element dans etd1 qui est > element etd2
*/
/* Recopier les elements qui restent dans FEtd dans FTemp */
While (NOT(EOF(FEtd))) Do
Read(FEtd, etd1);
Write(FTemp, etd1);
Done
Eif
Close(FEtd);
Close(FTemp);

/* Recopier maintenant FTemp dans FEtd */


ReRead(FTemp);
ReWrite(FEtd);
While (NOT(EOF(FTemp))) Do
Read(FTemp, etd1);
Write(FEtd, etd1);
Done
Eif
Close(FEtd);
Close(FTemp);
End.

9.6- Ouverture d'un fichier en lecture plusieurs fois en même temps


On peut ouvrir en lecture un fichier plusieurs fois en même temps. Dans ce cas on
aura plusieurs noms logiques du fichier qui correspondent au même nom physique
du fichier.
Il faut se rappeler que la tête de lecture/écriture correspond au nom logique et non
pas au nom physique du fichier, c'est à dire qu'on a une tête de lecture/écriture pour
chaque nom logique du fichier..
Exemple
Supposons qu'on a le fichier d'entiers de nom physique "Nombres.bin" qui éxiste et
qu'on veut écrire un algorithme qui affiche sur écran chaque élément du fichier l'un
après l'autre mais après chaque élément du fichier on affiche aussi tous le fichier.

Si par exemple Nombres.bin contient les 5 entiers


12 - 5 - 18 - 7 - 22
on veut afficher sur ecran:
12 - 12 - 5 - 18 - 7 - 22
5 - 12 - 5 - 18 - 7 - 22
18 - 12 - 5 - 18 - 7 - 22
7 - 12 - 5 - 18 - 7 - 22
22 - 12 - 5 - 18 - 7 - 22

Une manière simple d'écrire cet algorithme est d'avoir 2 variables noms logiques du
fichier F1 et F2, d'assigner F1 et F2 au même nom physique Nombres.bin, d'ouvrir
F1 en lecture et de boucler sur F1 et lire élément par élément F1 et chaque fois
qu'on lit un élément de F1 on ouvre le fichier F2 en lecture et on lit le fichier F2 et
on afficher les éléments de F2.

Algorithm LectureSimultanee;
Var
F1, F2 : File of Integer;
nb1, nb2: Integer;
Begin
Assign(F1, "Nombres.bin");
Assign(F2, "Nombres.bin");
ReRead(F1);
While (NoT(EOF(F1))) Do
Read(F1, nb1);
Write(nb1);
ReRead(F2);
While (NOT(EOF(F2))) Do
Read(F2, nb2);
Write(nb2);
Done
Close(F2);
Done
Close(F1);
End.

9.7- Calcult de la somme et de la moyenne des éléments d'un fichier d'entiers


Soit le fichier NOMBRES.BIN qui contient une liste de nombres entiers. Ecrire un
algorithme qui affiche les nombres du fichier, leur somme et leur moyenne.

Algorithm SomMoyFichEntiers;
Var
F : File of Integer;
nbr, Som, cpt : integer;
Begin
Assign(F, "NOMBRES.BIN");
ReRead(F);
cpt <--- 0; /* compte combien d'entiers il y'a dans le fichier */
Som <--- 0;
While (NOT(EOF(F))) Do
Read(F, nbr);
Write(nbr);
Som <--- Som + nbr;
cpt <--- cpt + 1;
Done
Close(F);
If (cpt = 0) then
Write("Fichier NOMBRES.BIN est Vide");
Else
Write("Somme des elements du fichier = ", Som, " et Moyenne = ", Som/cpt);
Eif
End.

9.8- Recherche des éléments d'un fichier dans un autre fichier et création d'un
fichier difference
Soient F1 et F2 deux fichiers de chaînes de caractères. Chaque chaîne représente un
mot.
Ecrire un algorithme qui construit un fichier F3, tel que F3 contient les mots de F1
qui n’existent pas dans F2.
Exemple:
F1 : "Benali" - "Doukal" - "Bendali" – "Mostefa" – "Ali"
F2 : "Douma" - "Benali" - "Bendali" - "Ali"
F3 : "Doukal" - "Mostefa"

Algorithm MotsF1SansF2;
Type
Chaine50 = String[50];
Var
F1, F2, F3 : File of Chaine50;
ch1, ch2 : Chaine50;
Trouve : Boolean;
Begin
Assign(F1, "F1");
Assign(F2, "F2");
Assign(F3, "F3");
ReRead(F1);
ReWrite(F3);
While (NOT(EOF(F1))) Do
Read(F1, ch1);
Trouve <--- False;
ReRead(F2);
While ( NOT(EOF(F2)) and NOT(Trouve)) Do
Read(F2, ch2);
If (ch1 = ch2) then
Trouve <--- True;
Eif
Done
Close(F2);
If (NOT(Trouve)) then
Write(F3, ch1);
Eif
Done
Close(F1);
Close(F3);
End.

9.9- Tri d'un Fichier


Soit Fdata un fichier d'entiers.
1. Ecrire une procédure InsertF permettant d'insérer un entier N dans un fichier trié
par ordre croissant.
2. En utilisant cette procédure écrire un algorithme permettant de trier le
fichier Fdata dans un ordre croissant.

Algorithm TriFichierEntiers;
Type
FEnt = File of Integer;
Var
F : FEnt;
elt : Integer;

Procedure InsertF(I-O/ F: FEnt, I/ N: Integer)


Var
Ftemp : FEnt;
Superieur : Boolean;
nbr : Integer;
Begin
Assign(Ftemp, "FichTemp2");
ReRead(F);
ReWrite(Ftemp);
Superieur <--- False;

/* Recopier tous les entiers de F <= N dans Ftemp */


While (NOT(EOF(F)) and NOT(Superieur)) Do
Read(F, nbr);
If (nbr <= N) then
Write(Ftemp, nbr);
Else
Superieur <--- True;
Eif
Done
/* ecrire N dans Ftemp*/
Write(FTemp, N);
If (Superieur) then
Write(FTemp, nbr); /* ecrire le premier entier nbr qui est > N */
/* Recopier tous les entiers qui restent dans F dans FTemp */
While (NOT(EOF(F)) Do
Read(F, nbr);
Write(FTemp, nbr);
Done
Eif
Close(F);
Close(FTemp);

/* Recopier maintenant FTemp dans F */


ReRead(FTemp);
ReWrite(F);
While (NOT(EOF(FTemp)) Do
Read(FTemp, nbr);
Write(F, nbr);
Done
Close(F);
Close(FTemp);
End;
Begin
Assign(F, "Fdata");
/* Consideron le fichier temporaire FTemporaire. C'est ce fichier qui va contenir
les entiers tries
lorsqu'on va appeler la procedure InsertF. Pour s'assurer que FTemporaire est
vide au debut on
va faire un Reecrire suivi d'un Fermer.
*/
Assign(FT, "Ftemporaire");
ReWrite(FT);
Close(FT);

ReRead(F);
While (NOT(EOF(F))) Do
Read(F, elt);
InsertF(FT, elt);
Done
Close(F);

/* Recopier maintenant FT dans F */


ReRead(FT);
ReWrite(F);
While (NOT(EOF(FT))) Do
Read(FT, elt);
Write(F, elt);
Done
Close(F);
Close(FT);
End.

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


Les Listes Chainées Simples

1. Introduction
On a vu jusqu'a présent que si on a un ensemble d'éléments de même type et qu'on
connait le
maximum nombre de ces éléments, on peut sauvegarder ces éléments dans un
tableau et accéder à un élément en utilisant un index qui indique la position de
l'élément dans ce tableau. Il y'a plusieurs problèmes avec cette représentation.
Le premier problème est qu'il faut connaitre au préalable le nombre maximum
d'éléments que cet ensemble peut avoir. Aussi il y'a perte d'espace avec cette
représentation si le nombre réel d'éléments est plus petit que le nombre maximum
d'éléments, ce qui est généralement le cas. Autre problème si jamais on veut ajouter
ou supprimer un élément au début ou au milieu du tableau il faut décaler les
éléments qui viennent après, ce qui est couteux en temps d'execution.
Pour palier à ces problèmes on utilise une structure dynamique appelée liste
chainée.

2. Definition
Une liste est une structure d'éléments de même type. Chaque élément est composé
de 2 parties: une partie qui contient l'information de l'élément qui peut être de type
simple ou composé et une partie qui contient l'adresse de l'élément qui suit appelée
lien de chainage. Ce lien est un pointeur qui est l'adresse de l'élément suivant. Ainsi
à partir de chaque élément on peut accéder à l'élément suivant.

Une liste est définie par sa tête (voir Exemple figure ci-dessous). La tête est un
pointeur vers le premier élément, c'est à dire que la tête contient l'adresse du
premier élément. Donc la tête ne contient pas la partie information. Autre chose, il
n'y a pas d'élément après le dernier élément, cela est representé en ayant la valeur
Null dans la partie lien de chainage du dernier élément. Une liste est créee de
manière dynamique, c'est à dire au cours de l'execution du programme. Au début la
liste est vide, cela est representé par la tête ayant la valeur Null.

Exemple
La figure ci-dessous represente la liste d'entiers: 12, 27, -19, 35, 45.
5 Elements correspondant aux 5 valeurs 12, 27, -19, 35 et 45 ont été alloués
dynamiquement aux adresses: 520, 200, 800, 400 et 160.

Le premier élément contenant la valeur 12 a été alloué à l'adresse 520 donc la Tête
contient l'adresse de ce premier élément qui est 520. Aussi chaque élément a son
champ suivant qui contient l'adresse de l'élément suivant. Par exemple le premier
élément a son champ suivant qui contient 200 qui est l'adresse du 2eme élément
alloué. Le dernier élément contenant la valeur 45 n'a pas de suivant donc son
champ suivant contient Null.
Généralement on ne s'interesse pas à la valeur des adresses car d'une éxecution à
une autre les adresses changent. L'essentiel c'est que la tête contient l'adresse du
premier élément, chaque élément contient l'adresse du suivant et le suivant du
dernier élément contient Null.
Donc lorsqu'on montrera une liste on ne vas pas montrer des exemples d'adresses
mais on montrera uniquement les chainages (c'est a dire les flèches). Ainsi la liste
ci-dessus sera montrée comme:

3. Declaration d'une Liste


Type
<element> = Record
<idf_info> : <type_info>;
<suivant> : ^<element>;
End;
Var
tete : ^<element>;

Exemples
Declaration d'une liste d'entiers
Type
Element = Record
val : Integer;
suivant : ^Element;
End;
Var
tete : ^Element;

Declaration d'une liste d'etudiants


Type
Etudiant = Record
nom , prenom : String[20];
matricule : Integer;
moyenne : Real;
End;
Element = Record
etud : Etudiant;
suivant : ^Element;
End;
Var
tete : ^Element;

4 Creation d'une Liste


Supposons qu'on veut écrire un algorithme qui crée une liste d'entiers. On va
demander au début à l'utilisateur de nous donner combien d'éléments la liste va
contenir au début. On va mettre cette valeur dans une variable qu'on appelera N.
Supposons que l’utilisateur donne N égale à 4, ensuite il nous donne les valeurs -
15, 44, 88, 12 dans cet ordre. Ces valeurs sont les valeurs qu'on va mettre dans le
champ val de chaque élément alloué dynamiquement.

Il y’a 2 manières de créer cette liste.


La première en ajoutant chaque valeur que l’utilisateur donne en fin de liste et dans
ce cas la liste créee aura le même ordre que celui donné par l’utilisateur. On dit que
c’est une liste FIFO (First In/First out) ou bien premier arrivé/premier servi. Dans
l’exemple ci-dessus la liste sera {-15, 44, 88, 12}

La seconde manière de créer la liste est d’ajouter chaque valeur donnée par
l’utilisateur en tête de liste (plutôt que en fin de liste) et dans ce cas la liste crée
aura l’ordre inverse de l’ordre donné par l’utilisateur. On dit que c’est une liste
LIFO (Last In/First Out) ou bien dernier arrivé/premier servi. Dans l’exemple ci-
dessus la liste sera {12, 88, 44, -15}

Creation d'une Liste LIFO


N=4 et l'utilisateur donne les valeurs -15, 44, 88, 12 dans cet ordre.
Au debut la liste est vide, donc tête est mise à Null.
Chaque fois que l'utilisateur donne une valeur, la valeur est ajoutée en tête de liste.

Debut: tête <--- Null


Utilisateur donne -15.
La liste devient: tête ---> -15 ---> Null
Utilisateur donne 44.
La liste devient: tête ---> 44 ---> -15 ---> Null
Utilisateur donne 88.
La liste devient: tête ---> 88 ---> 44 ---> -15 ---> Null
Utilisateur donne 12.
La liste devient: tête ---> 12 ---> 88 ---> 44 ---> -15 ---> Null
Algorithm CreationListeLiFo;
Type
pList = ^Element;
Element = Record
val : Integer;
suivant : pList;
End;
Var
tete : pList;
N: Integer;

Function CreerListeLifo(N: Integer) : pList


Var
L, p : pList;
i : Integer;
Begin
L <--- Null;
For i <--- 1 to N Do
Allocate(p);
Write("Donner ", i , " eme Valeur");
Read(p^.val);
p^.suivant <--- L;
L <--- p;
Done

Return L;
End;

Procedure AfficherListe(I/ L : pList)


Begin
Write("Liste L:");
While (L <> Null) Do
Write(L^.val, " ->");
L <--- L^.suivant;
Done
Write("Null");
End;

Begin
Repeat
Write("Donner Nombre d'elements de la liste");
Read(N);
Until (N > 0);

tete <--- CreerListeLifo(N);


AfficherListe(tete);
End.

Creation d'une Liste FIFO


N=4 et l'utilisateur donne les valeurs -15, 44, 88, 12 dans cet ordre.
Au début la liste est vide, donc tête est mise a Null.
Chaque fois que l'utilisateur donne une valeur, la valeur est ajoutée en fin de liste.

Debut: tête <--- Null


Utilisateur donne -15.
La liste devient: tête ---> -15 ---> Null
Utilisateur donne 44.
La liste devient: tête ---> -15 ---> 44 ---> Null
Utilisateur donne 88.
La liste devient: tête ---> -15 ---> 44 ---> 88 ---> Null
Utilisateur donne 12.
La liste devient: tête ---> -15---> 44 ---> 88 ---> 12 ---> Null

La tête est modifiée uniquement lorsqu'on ajoute le premier élément, donc on vas
traiter le premier élémen à part.

Algorithm CreationListeFiFo;
Type
pList = ^Element;
Element = Record
val : Integer;
suivant : pList;
End;
Var
tete : pList;
N: Integer;

Function CreerListeFifo(N: Integer) : pList


Var
L, p, prec : pList; /* prec represente pointeur vers le precedent */
i : Integer;
Begin
Allocate(p);
Write("Donner la Premiere Valeur");
Read(p^.val);
L <--- p;
prec <--- p; /* initialiser prec à l'@ du premier élément car le precedent du 2eme
est le 1er élément */

/* commencer à partir du 2eme élément (i = 2) */


For i <--- 2 to N Do
Allocate(p);
Write("Donner ", i , " eme Valeur");
Read(p^.val);
prec^.suivant <--- p; /* le suivant du precedent est le courant p */
prec <--- p; /* le courant devient le precedent pour le prochain */
Done
p^.suivant <--- Null; /* Mettre Null dans le suivant du dernier element */

Return L;
End;

Procedure AfficherListe(I/ L : pList)


Begin
Write("Liste L:");
While (L <> Null) Do
Write(L^.val, " ->");
L <--- L^.suivant;
Done
Write("Null");
End;

Begin
Repeat
Write("Donner Nombre d'elements de la liste");
Read(N);
Until (N > 0);

tete <--- CreerListeFifo(N);


AfficherListe(tete);
End.

5. Traitements sur les Listes


On considère une liste d'entiers dans tous les traitements qui suivent.
Type
pList = ^Element;
Element = Record
val : Integer;
suivant : pList;
End;

5.1 Recherche d'un élément dans une liste


Etant donné une liste, on veut rechercher un élément dans cette liste. La recherche
consiste à parcourir la liste jusqu'a trouver l'élément si l'élément appartient à la liste
et dans ce cas retourner son adresse ou bien jusqu'à parcourir toute la liste dans le
cas où l'élément n'appartient pas à la liste et dans ce cas retourner Null.
Cette recherche peut être basée soit sur la valeur de l'élément soit sur sa position.

5.1.1 Recherche d'un élément dans une liste par Valeur


Etant donné une liste définie par sa tête L et un entier V, on va écrire une fonction
qui retourne l'adresse du premier élément où se trouve V si V existe dans la liste. Si
V ne se trouve pas dans la liste la fonction retourne Null.

Function rechercheV(L: pList, V: Integer) : pList


Var
p : pList;
Begin
p <--- L;
While ((p <> Null) and (p^.Val <> V)) Do
p <--- p^.suivant;
Done

Return p;
End;

Remarque: Dans la fonction RechercherV() et dans le Tant Que l'ordre des


conditions est important. Il faut écrire la condition (p <> Null) avant (p^.val <> V)
car les conditions sont evaluées dans l'ordre où elles sont écrites. Si le Tant Que est
écrit comme "Tant Que ((p^.val <> V) et (p <> Null)) lorsque p devient égale à
Null alors (p^.val) n'est pas definie et on aura une erreur à l'execution.

5.1.2 Recherche d'un élément dans une liste par Position


Etant donné une liste definie par sa tête L et un entier pos, on va écrire une fonction
qui retourne l'adresse de l'élément ayant la position pos s'il y'a un élément à la
position pos dans la liste. S'il n'y a pas d'élément à la position pos dans la liste (pos
est plus grand que le nombre d'elements dans la liste ou bien pos <= 0) la fonction
retourne Null. Noter que pos=1 corréspond au premier élément de la liste.

Function recherchePos(L: pList, pos: Integer) : pList


Var
p : pList;
i : Integer;
Begin
p <--- L;
i <--- 1;
While ((p <> Null) and (i <> pos)) Do
p <--- p^.suivant;
i <--- i + 1;
Done

Return p;
End;

5.2 Insertion d'un élément dans une liste


Etant donné une liste définie par sa tête L, un entier V qu'on veut insérer et un
entier pos contenant la position où on veut inserer V on va écrire une fonction qui
va insérer V dans la liste. pos sera la position de V après insertion de V dans la
liste. Si pos est egale à 1 alors V sera inséré en tête de liste.

On va d'abord écrire une fonction qui insère V en tête de liste car c'est un cas
particulier le seul où la tête va changer. Cette fonction retourne la nouvelle tête de
liste.

Function insererVEnTete(L: pList, V: Integer) : pList


Var
p : pList;
Begin
Allocate(p);
p^.val <--- V;
p^.suivant <--- L;

Return p;
End;

On va écrire maintenant la fonction InsererV() pour le cas générale où on insert un


entier V à une position pos. Il faut noter que insererV() va appeler
InsererVEnTete() dans le cas où pos est egale à 1 ou bien dans le cas où la liste est
vide (L=Null).
On suppose dans ce qui suit que pos est >= 1.
Dans le cas où pos est different de 1 et la liste n'est pas vide, V sera inséré au
milieu ou bien à la fin de la liste. Donc on aura besoin de chercher le précédent
après qui V sera inséré pour changer son chainage.
Cette fonction retourne la tête de liste.

Function insererV(L: pList, pos: Integer, V: Integer) : pList


Var
pIn, p, prec : pList;
i: Integer;
Begin
If ((pos = 1) or (L = Null))
L <--- insererVEnTete(L, V);
Else
Allocate(pIn); // Allouer dans pointeur pIn (pInserer)
pIn^.val <--- V;
p <--- L;
i <--- 1;
While ((p <> Null) and (i <> pos)) Do
prec <--- p;
p <--- p^.suivant;
i <--- i + 1;
Done
/* Ajouter l'element dont l'adresse est dans pIn apres prec */
/* Le suivant de pIn est le suivant de prec */
pIn^.suivant <--- prec^.suivant;
/* le suivant de prec est p */
prec^.suivant <--- pIn;
Eif

Return L;
End;

Il y'a 2 choses à remarquer dans la fonction insererV():


- Insérer à la fin est similaire à insérer au milieu de la liste. Lorsqu'on insert à la fin
prec^.suivant est Null et lorsqu'on insert à la fin et qu'on fait pIn^.suivant <---
prec^.suivant le suivant de l'élément qu'on insert pIn devient Null.
- Si la valeur de pos est plus grande que le nombre d'éléments dans la liste avant
insertion, le nouveau élément sera inséré à la fin de la liste et cela quelque soit la
valeur de pos plus grande que le nombre d'éléments avant insertion. Si par exemple
le nombre d'éléments dans la liste avant insertion est 4, si pos=5, ou pos=6, ou
pos=7,... (quelque soit la valeur de pos > 4) le nouveau élément sera inséré à la fin
de la liste.

5.3 Suppression d'un élément d'une liste


Etant donné une liste on veut supprimer un élément de cette liste. La suppression
consiste à mettre à jour le chainage et à liberer l'espace mémoire de l'élément
supprimé. Comme pour la recherche la suppression peut être basée soit sur une
valeur soit sur une position.

5.3.1 Suppression d'un élément d'une liste par Valeur


Etant donné une liste definie par sa tête L et un entier V on veut supprimer
l'élément qui contient V si V est dans la liste. Donc on a besoin d'abord de
rechercher V dans la liste. Si V n'appartient pas à la liste on n'a rien à supprimer
dans ce cas.
Si V appartient à la liste, il y'a 2 scenarios dans ce cas. Si V est le premier élément
de la liste alors on va supprimer le premier élément de la liste et la tête va changer
dans ce cas. Si V n'est pas le premier élément de la liste on doit modifier le
chainage du suivant du précédent avant de supprimer l'élément.
S'il y a plusieurs occurrences de V dans la liste, on supprimera la première
occurrence de V.
Cette fonction retourne la tête de liste.

Function supprimerV(L: pList, V: Integer) : pList


Var
p, prec : pList;

Begin
p <--- L;
While ((p <> Null) and (p^.val <> V)) Do
prec <--- p;
p <--- p^.suivant;
Done
If (p <> Null) then /* V est dans la liste */
If (p = L) then /* V est le premier element de la liste */
L <--- L^.suivant;
Else /* p a supprimer est au milieu ou a la fin de la liste */
prec^.suivant <--- p^.suivant; /* le suivant du precedent devient le suivant de
p */
Eif
Free(p);
Eif

Return L;
End;

5.3.2 Suppression d'un élément d'une liste par Position


Etant donné une liste definie par sa tête L et un entier pos on veut supprimer
l'élément à la position pos dans la liste. Donc on a besoin d'abord de rechercher
l'élément à la position pos dans la liste. S'il n'y a pas d'élément à la position pos il
n'y a rien à supprimer.
S'il y'a un élément à la position pos dans la liste, il y'a 2 scenarios dans ce cas. Si
c'est le premier élément de la liste alors on va supprimer le premier élément de la
liste et la tête va changer dans ce cas. Si ce n'est pas le premier élément de la liste
on doit modifier le chainage du suivant du précédent avant de supprimer l'élément.
Cette fonction retourne la tête de liste.

Function supprimerPos(L: pList, pos: Integer) : pList


Var
p, prec : pList;
i : Integer;
Begin
p <--- L;
i <--- 1;
While ((p <> Null) and (i <> pos)) Do
prec <--- p;
p <--- p^.suivant;
i <--- i + 1;
Done
If (p <> Null) then /* Element est dans la liste */
If (p = L) then /* C'est le premier element de la liste */
L <--- L^.suivant;
Else /* p a supprimer est au milieu ou a la fin de la liste */
prec^.suivant <--- p^.suivant; /* le suivant du precedent devient le suivant de
p */
Eif
Free(p);
Eif

Return L;
End;

5.4 Suppression de tous les éléments d'une liste


Etant donné une liste definie par sa tête L, on veut écrire une fonction qui supprime
tous les éléments de cette liste et libère ainsi tous l'espace occupé par cette liste.
Cette fonction a comme paramètre d'entrée la tête de liste et retourne Null. On
commence par libérer l'espace occupé par l'élément en tête de liste, ensuite le
second élément devient l'élément en tête de liste et on le libère et ainsi de suite
jusqu'à libérer tous les éléments de la liste.

Function libererListe(L: pList) : pList


Var
p : pList;
Begin
While (L <> Null) Do
p <--- L;
L <--- L^.suivant;
Free(p);
Done

Return Null;
End;

6. Applications
Exercice :
Soit une liste d’entiers L, écrire une action paramétrée pour résoudre chacun des
problèmes suivants:
a. Le calcul du nombre d'éléments, et la détermination du maximum et du
minimum.
b. La vérification si la liste L est triée dans l'ordre croissant.
c. La suppression de la valeur maximale d'une liste.

a. Le calcul du nombre d'éléments, et la détermination du maximum et du


minimum.
Procedure nbrEltsMinMax(I/ L: pList, O/ nbr, min, max: Integer)
Var
p : pList;
Begin
If (L = Null) then
nbr <--- 0;
Else
nbr <--- 1;

/* Supposer que min et max c'est le premier et commencer a comparer a partir


du deuxieme */
min <--- L^.val;
max <--- L^.val;
p <--- L^.suivant;
While (p <> Null) Do
nbr <--- nbr + 1;
If (p^.val > max) then
max <--- p^.val;
Eif
If (p^.val < min) then
min <--- p^.val;
Eif
p <--- p^.suivant;
Done
Eif
End;

b. La vérification si la liste L est triée dans l'ordre croissant.


Function listeTrieCroissant(L: pList) : Boolean
Var
p: pList;
trie: Boolean;
Begin
trie <--- True;
If (L <> Null) then
p <--- L;
While ((p^.suivant <> Null) and trie) Do
If (p^.val > (p^.suivant)^.val) alors
trie <--- False;
Else
p <--- p^.suivant;
Eif
Done
Eif
Return trie;
End;

c. La suppression de la valeur maximale d'une liste.


On va écrire d'abord une procédure qui donne l'adresse du maximum de la liste
ainsi que l'adresse de son précédent (si le maximum n'est pas l'élément en tête de
liste). Si le maximum est l'élément en tête de liste le précédent retourné est Null.

Procedure PtrMaxEtPrcd(I/ L: pList, O/ pMax, pMaxPrcd: pList)


Var
p, prcd : pList;
Begin
If (L = Null) then
pMax <--- Null;
pMaxPrcd <--- Null;
Else
pMax <--- L; /* Considerer le Max comme le 1er element */
pMaxPrcd <--- Null;
p <--- L^.svt; /* commencer a comparer a partir du 2eme et le precedent du
2eme est le 1er */
prcd <--- L;
While (p <> Null) Do
If (p^.val > pMax^.val) then
pMax <--- p;
pMaxPrcd <--- prcd;
Eif
prcd <--- p;
p <--- p^.svt;
Done
Eif
End;

Function SupprimerMax(L: pList) : pList


Var
pMax, pMaxPrcd : pList;
Begin
If (L <> Null) then
PtrMaxEtPrcd(L, pMax, pMaxPrcd);
If (pMax = L) then /* Le maximum est le premier */
L <--- L^.suivant;
Else
pMaxPrcd^.suivant <--- pMax^.suivant;
Eif
Free(pMax);
Eif
Return L;
End;

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com


 --- Home ---
 Contact

Les Pointeurs

1- La Memoire Centrale (MC)


La MC contient un certain nombre d'octets. Chaque octet a une adresse bien
spécifique.
Après compilation d'un programme et au moment de l'execution du programme
toutes les variables utilisées dans ce programme occupent un espace (un ou
plusieurs octets) quelque part en Mémoire Centrale (MC). Chaque octet de la MC
ayant une adresse différente, chacune de ces variables a une adresse spécifique en
MC. Les variables déclarées à l'interieur du programme ont leur espace mémoire
alloué de manière statique automatiquement par le système.
A l'intérieur de la MC un programme a 3 parties: le code objet (c'est à dire les
instructions du programme traduit par le compilateur en code objet), les variables
allouées de manière statique (c'est à dire le systeme alloue automatiquement de
l'espace mémoire pour ces variables) et une zone mémoire où on fait de l'allocation
dynamique (c'est à dire qu'on alloue dans le programme au moment de l'execution
du programme de l'espace mémoire).
On utilise de l'allocation dynamique parcequ'on ne veut pas perdre de l'espace
mémoire: on alloue uniquement la quantité d'espace mémoire qu'on a besoin et au
moment où on a besoin et dés qu'on n'a plus besoin de cet espace mémoire on le
libère.

2- Definition
Un pointeur est une variable qui peut contenir l'adresse d'une autre variable.
Après compilation d'un programme et au moment de l'execution du programme
toutes les variables utilisées dans ce programme occupent un espace (un ou
plusieurs octets) quelque part en Mémoire Centrale (MC). Chaque octet de la MC
ayant une adresse différente, chacune de ces variables a une adresse specifique en
memoire.

Soit par exemple une variable X de type entier qui est située à l'adresse memoire
400 en MC et qui contient la valeur 12. Si on a une autre variable PX pointeur vers
un entier et qu'on met dans la variable PX l'adresse de X, on aura dans PX la valeur
400 comme montré dans la figure ci-dessous (bien sûr en MC toutes les valeurs
sont codés en binaire). Dans ce cas PX est un pointeur vers X. On dit que PX pointe
vers X. On peut dans ce cas accéder à X en utilisant X ou bien en utilisant PX.

3- Cas d'Utilisation des Pointeurs


Il y'a plusieurs cas où on a besoin d'utiliser des pointeurs, on citera 2 cas
principaux.
Le premier est le suivant. Dans le cas par exemple où on avait dans un algorithme
un tableau, on déclarait le tableau par exemple de 100 éléments ensuite l'utilisateur
nous donnait un N <= 100 et on utilisait les N premiers éléments du tableau. On dit
que le tableau est une variable statique car l'espace mémoire occupé par le tableau
est alloué à l'avance avant que le programme commence l'execution.
Il y'a 2 problèmes avec cela: Le premier est qu'on a pu faire ça parce qu'on savait
que le maximum nombre d'éléments que le tableau pouvait avoir est de 100. Or il
se peut qu'il y'a des cas où on ne peut pas savoir cela avant l'execution du
programme. Le deuxième problème est que même si on connait le nombre
maximum d'éléments du tableau et qu'on utilise les N premiers éléments du tableau,
si
l'utilisateur donne par exemple N = 40, les 60 derniers éléments du tableau ne sont
pas utilisés et donc ont été inutilement reservés en mémoire et par conséquent il y'a
perte d'espace mémoire. Pour remédier à ce genre de problème la solution est
d'allouer de l'espace dynamiquement: autant d'espace qu'on a besoin au moment de
l'execution du programme et de libérer cet espace dés qu'on n'a plus besoin. Pour
cela on a besoin d'avoir un pointeur qui va contenir l'adresse de la zone mémoire
allouée dynamiquement.
Le deuxieme cas d'utilisation est le suivant. On a vu lors du chapitre sur les actions
parametrees (AP) qu'un paramètre peut être passé par valeur comme il peut être
passé par adresse (ou référence) à une AP. Lors de la passation par valeur le
paramètre formel est une copie du paramètre réel; donc si le paramètre formel est
modifié le paramètre réel n'est pas modifié (c'est la copie qui est modifiée). Lors de
la passation par adresse, le paramètre formel est l'adresse du paramètre réel. Si on
veut que le paramètre réel soit modifié il faut faire une passation par adresse, c'est à
dire passer un pointeur vers le parametre réel. Il faut noter que lorsqu'on a une
variable de type enregistrement (structure en C) à passer comme paramètre à une
AP si on fait une passation par valeur il faut faire une copie de tout l'espace occupé
par l'enregistrement, donc s'il s'agit d'un enregistrement occupant beaucoup
d'espace cela prendra du temps et de l'espace. Parfois pour des raisons de
performance même si le parametre réel de l'enregistrement ne sera pas modifié on
fait une passation par adresse pour ne pas perdre espace et temps. En algorithmique
la passation de paramètre par adresse se fait de manière implicite en utilisant la
notation S/ ou bien E/S avant de spécifier le nom du parametre formel. Dans le
langage C il faut utiliser explicitement un pointeur pour faire une passation par
adresse.

En cours et en TD on utilisera les pointeurs dans le premier cas, c'est a dire pour
allocation dynamique de la mémoire.

4- Declaration
Syntaxe
<idf_pointeur> : ^ <type_variable_pointe>;

<idf_pointeur>: L'identificateur de la variable pointeur


<type_variable_pointe>: type de la variable pointe (c'est a dire le type de la variable
dont l'adresse sera dans la variable <idf_pointeur>. <type_variable_pointe> peut
être un type simple (integer, real ou character), comme il peut être un type définie
comme un record (enregistrement).

Exemple:
Type
Etudiant=Record
matricule: Integer;
nom, prenom: String[20];
moyenne: Real;
End;
Var
P1: ^Integer;
P2: ^Real;
P3: ^Character;
P4: ^Etudiant;

P1 est un pointeur vers un Integer (entier).


P2 est un pointeur vers un real (reel).
P3 est un pointeur vers un character (caractere).
P4 est un pointeur vers un record (enregistrement) de type Etudiant.

5- Utilisation des Pointeurs avec les Variables Allouées Statiquement


Il y'a 2 opérateurs qu'on utilise:
@: pour avoir l'adresse d'une variable (opérateur équivalent en C: &)
^: pour accéder à la variable pointée (opérateur équivalent en C: *)

Exemple:
Type
Etudiant=Record
matricule: Integer;
nom, prenom: String[20];
moyenne: Real;
End;
Var
p1: ^Integer;
p2: ^Etudiant;
X: Integer;
etd: Etudiant;
Begin
p1 <--- @X; /* On met dans p1 l'adresse de X */
p2 <--- @etd; /* On met dans p2 l'adresse de etd */

X <--- 12; /* affectation de la valeur 12 a la variable X */


/* Ou bien on peut ecrire: */
p1^ <--- 12; /* affectation de la valeur 12 a la variable X car p1 contient
l'adresse de X */

/* Pour affecter a chacun de champs de la variable etd une valeur on ecrit: */


etd.matricule <--- 125;
etd.nom <--- "Benali";
etd.prenom <--- "Omar";
etd.moyenne <--- 12.5;

/* Puisque p2 contient l'adresse de etd on peut faire cela avec: */


p2^.matricule <--- 125;
p2^.nom <--- "Benali";
p2^.prenom <--- "Omar";
p2^.moyenne <--- 12.5;

6- Allocation Dynamique de la Memoire


Comme déja mentionné il existe 2 types d'allocation mémoire: statique fait
automatiquement par le système et dynamique fait explicitement à l'intérieur d'un
programme.
Toutes les variables déclarées à l'intérieur d'un programme (ou algorithme) sont
allouées statiquement.
Les variables globales d'un programme sont crées au début de l'execution du
programme et détruites à la fin de l'execution du programme.
Les variables locales des actions parametrées (AP) ainsi que les paramètres d'appel
sont crées lors de l'appel de l'AP et détruites à la fin de l'execution de l'AP.

L'allocation dynamique permet d'allouer et de libérer de l'espace mémoire durant


l'execution d'un programme. Une region de la mémoire centrale est reservée pour
l'allocation dynamique de l'espace mémoire.

6.1 Allocation de l'espace mémoire


Syntaxe
Allocate(<idf_pointeur>);

Exemple:
Var
p1: ^Integer;
p2: ^Etudiant;
Begin
Allocate(p1);
Allocate(p2);

Allocate(p1) alloue de l'espace mémoire pour un entier et met son adresse dans p1.

Allocate(p2) alloue de l'espace mémoire pour un enregistrement de type Etudiant et


met son adresse dans p2.
Si par exemple l'entier est alloué dynamiquement à l'adresse 400 et l'enregistrement
de type etudiant est alloué dynamiquement à l'adresse 800 on peut schematiser cela
par:
On representera le faite que p1 contient l'adresse de l'entier alloué dynamiquement
et p2 contient l'adresse de l'enregistrement etudiant alloué dynamiquement par une
flèche allant de p1 et p2 vers respectivement l'entier et l'enregistrement etudiant.

6.2 Libération de l'espace mémoire


Syntaxe:
Free(<idf_pointeur>);

Exemple:
Free(p1);
Free(p2);

Free(p1) libère l'espace mémoire occupé par l'entier dont l'adresse est dans p1.
Free(p2) libère l'espace mémoire occupé par l'enregistrement de type Etudiant dont
l'adresse est dans p2.

6.3 Utilisation des Pointeurs avec l'allocation dynamique


On utilise:
Allocate(ptr): Met dans la variable ptr l'adresse de l'espace mémoire alloué
(equivalent malloc() en C)
Operateur ^: Pour accéder à l'espace mémoire alloué (equivalent * ou -> en C)
Free(ptr): libere l'espace mémoire alloué (equivalen free() en C)
Remarque: Les emplacements mémoire alloués dynamiquement ne peuvent être
accessibles qu'à travers leurs pointeurs.

Exemple:
Algorithme ExempleAllocDynamique;
Type
Etudiant=Record
matricule: Integer;
nom, prenom: String[20];
moyenne: Real;
End;
Var
p1: ^Integer;
p2: ^Etudiant;
Begin
Allocate(p1);
Allocate(p2);

p1^ <--- 25;


p2^.matricule <--- 142;
p2^.nom <--- "BenMohamed";
p2^.prenom <--- "Ali";
p2^.moyenne <--- 7..5;

Free(p1);
Free(p2);
End.

Remarques:
1) Si p est une variable pointeur et que l'on écrit "p <--- Null", cela veut dire que p
ne pointe vers aucune adresse.
2) Si on déclare un pointeur p, Ne jamais utiliser l'operation ^ alors que p contient
n'importe quoi après déclaration de p. Dans ce cas on aura une erreur à l'execution
(erreur de segmentation).
Exemple:
Var
p:^Integer;
Begin
p^ <--- 15; /* Erreur à l'execution: Tentative d'accés à une adresse mémoire
indeterminée */
3) Ne jamais essayer d'accéder à une zone mémoire qui a été liberée.
Var
p: ^Integer;
Begin
Allocate(p);
p^ <--- 14;
Free(p);
p^ <--- 25; /* Erreur : p pointe vers une adresse dont l'espace a ete libere */

7 Operations sur les Pointeurs


7.1 Affectation de Pointeurs
On peut affecter une variable pointeur vers un type à une autre variable pointeur
vers le même type. Cela veut dire que les 2 pointeurs vont pointer vers la même
adresse après l'affectation.
Exemple
Var
p1, p2: ^Integer;
Begin
Allocate(p1);
p2 <--- p1;

Allocate(p1) alloue de l'espace mëmoire pour un entier et met son adresse dans p1.
Après execution de l'instruction "p2 <--- p1", p2 et p1 pointent vers le même entier
qui a été alloué.

7.2 Comparaison de Pointeurs


L'ecriture "Si p = Null" compare p à Null. Si p est egale à Null cela veut dire p ne
pointe vers aucune adresse.
L'ecriture "Si p1=p2" compare les pointeurs p1 et p2. Cette condition est vrai si p1
et p2 pointent vers la même adresse (ou bien les 2 sont egaux à Null et ainsi ne
pointent vers aucune adresse).

8. Pointeurs et Actions Parametrees (AP)


8.1 Pointeur Comme Parametre d'une AP
Un pointeur peut être passé comme paramètre à une AP. Il est recommandé dans ce
cas de déclarer le type pointeur dans la partie Type de l'algorithme.
Exemple:
Algorithm Exemple;
Type
PEntier = ^Integer;
Var
p: PEntier;
Procedure Mettre0(E/ p:PEntier)
Begin
p^ <--- 0;
End;
Begin
Allocate(p);
Mettre0(p);
End.

Remarque: Comme une variable ordinaire, un pointeur peut être passé par valeur
comme il peut être passé par adresse comme paramètre à une AP. Si le pointeur
n'est pas modifié par l'AP, le pointeur est passé par valeur. Si le pointeur peut être
modifié par l'AP, le pointeur est passé par adresse (dans ce cas on parle de pointeur
vers un pointeur).

8.2 Pointeur Retourné par une Fonction


Comme en C on va considérer que en algorithmique une fonction peut retourner un
pointeur.
Exemple:

Type
PEntier = ^Integer;
Function AllouerEntier(X:Integer) : PEntier
Var
p: PEntier;
Begin
Allocate(p);
p^ <--- X;
Return p;
End;

9. Application

Exercice
Soient les types suivants :

Date=Record
jour , mois, année :Integer;
End;
Adresse = Record
Numéro : Integer;
Rue : String [50];
Ville : String [20];
Wilaya : String [20];
End;
Habitant = Record
Nom, prénom : String [20];
Date_naiss : Date;
Residence : Adresse;
End;

Ecrire un algorithme permettant de :


- Remplir un tableau T de N habitants (N<=100).
- Afficher a partir de T les adresses des habitants agés exactement de 18 ans à une
date donnée D(j, m, a).

Solution 1: Solution Statique


On va utiliser un tableau de 100 Habitants où on utilise les N premiers Habitants.

Algorithm HabitantStatique;
Type
Date=Record
jour , mois, année :Integer;
End;
Adresse = Record
Numéro : Integer;
Rue : String [50];
Ville : String [20];
Wilaya : String [20];
End;
Habitant = Record
Nom, prénom : String [20];
Date_naiss : Date;
Residence : Adresse;
End;
Var
T: Array[100] of Habitant;
i, N: Integer;
D: Date;
Begin
/* Remplir un tableau T de N habitants (N<=100). */
Repeat
Write("Donner N Entier compris entre 1 et 100");
Read(N);
Until ((N>0) and (N<=100));
For i <--- 1 to N Do
Ecrire("Donner Nom, Prenom, Date de Naissance (jour, mois, annee) et
Adresse (No, rue, ville, wilaya)");
Read(T[i].Nom, T[i].prenom, T[i].Date_naiss.jour, T[i].Date_naiss.mois,
T[i].Date_naiss.annee, T[i].Residence.Numero, T[i].Residence.Rue,
T[i].Residence.Ville, T[i].Residence.Wilaya);
Done

/* Afficher a partir de T les adresses des habitants ages de 18 ans a une date
donnee D(j, m, a). */
Write("Donner une Date (jour, mois, annee)");
Read(D.jour, D.mois, D.annee);
Write("Liste de Residence des Habitants ages de 18 ans a date D");
For i <--- 1 to N Do
If ((T[i].Date_naiss.jour = D.jour) and (T[i].Date_naiss.mois = D.mois) and
(T[i].Date_naiss.annee + 18 = D.annee)) then
Write(T[i].Residence.Numero, T[i].Residence.Rue,Residence.Ville,
T[i].Residence.Wilaya);
Eif
Done
Write("Fin de Liste");
End.

Solution 2: Solution Dynamique (utilisation de pointeurs)


Dans la solution précédente on perd beaucoup d'espace car on a un tableau de 100
Habitant où chaque élément du tableau est un enregistrement de type Habitant alors
qu'on utilise uniquement les N premiers enregistrements. Si par exemple N=20, on
n'utilise pas les 80 derniers enregistrements. Dans cette 2eme solution on va utiliser
un tableau de 100 pointeurs où chaque pointeur est un pointeur vers Habitant et on
alloue de l'espace dynamiquement pour les N habitants. Donc par exemple si N=20
on alloue uniquement 20 enregistrements de type Habitant qu'on utilise.

Algorithme HabitantDynamique;
Type
Date=Record
jour , mois, année :Integer;
End;
Adresse = Record
Numéro : Integer;
Rue : String [50];
Ville : String [20];
Wilaya : String [20];
End;
Habitant = Record
Nom, prénom : String [20];
Date_naiss : Date;
Residence : Adresse;
End;
Var
T: Array[100] of Habitant;
i, N: Integer;
D: Date;
Begin
/* Remplir un tableau T de N habitants (N<=100). */
Repeat
Write("Donner N Entier compris entre 1 et 100");
Read(N);
Until ((N>0) and (N<=100));

For i <--- 1 to N Do
Allocate(T[i]);
Write("Donner Nom, Prenom, Date de Naissance (jour, mois, annee),
Adresse (No, rue, ville, wilaya)");
Read(T[i]^.Nom, T[i]^.prenom, T[i]^.Date_naiss.jour, T[i]^.Date_naiss.mois,
T[i]^.Date_naiss.annee, T[i]^.Residence.Numero, T[i]^.Residence.Rue,
T[i]^.Residence.Ville, T[i]^.Residence.Wilaya);
Done

/* Afficher a partir de T les adresses des habitants ages de 18 ans a une date
donnee D(j, m, a). */
Write("Donner une Date (jour, mois, annee)");
Read(D.jour, D.mois, D.annee);
Write("Liste de Residence des Habitants ages de 18 ans a date D");
For i <--- 1 to N Do
If ((T[i]^.Date_naiss.jour = D.jour) and (T[i]^.Date_naiss.mois = D.mois)
and
(T[i]^.Date_naiss.annee + 18 = D.annee)) then
Write(T[i]^.Residence.Numero, T[i]^.Residence.Rue,
T[i]^.Residence.Ville, T[i]^.Residence.Wilaya);
Eif
Done
Write("Fin de Liste");

/* Liberer l'espaces alloues */


For i <--- 1 to N Do
Free(T[i]);
Done
End.

About | Privacy Policy | Sitemap


Log in
Jimdo

You can do it, too! Sign up for free now at https://www.jimdo.com

Vous aimerez peut-être aussi