Vous êtes sur la page 1sur 84

Version de septembre 2005

Programmation avec DELPHI



Notes de cours pour les classes
de II
e
B et de I
re
B

Applications en console en II
e
B
Programmes Delphi en I
re
B


par
Hubert GLESENER, Jean-Claude HEMMER,
David MANCINI, Alexandre WAGNER

page 2 de 84
Table des matires
1 Introduction ............................................................................................................................ 5
1.1 Gnralits...................................................................................................................... 5
1.2 Cycle de dveloppement ................................................................................................ 5
1.3 Types dapplications....................................................................................................... 5
1.4 Exemple dun cycle de dveloppement.......................................................................... 6
2 Affectation.............................................................................................................................. 8
2.1 Entres-sorties ................................................................................................................ 8
2.2 Les oprations arithmtiques.......................................................................................... 9
2.3 Variables....................................................................................................................... 10
2.4 Type dune variable...................................................................................................... 10
2.5 Dclaration dune variable ........................................................................................... 11
2.6 Laffectation ................................................................................................................. 12
2.7 Initialisation dune variable.......................................................................................... 12
2.8 Linstruction readln.................................................................................................. 14
2.9 Diffrents types derreurs............................................................................................. 15
3 Structure alternative ............................................................................................................. 16
3.1 Problme introductif..................................................................................................... 16
3.2 Syntaxe ......................................................................................................................... 18
3.3 Les conditions (expressions logiques).......................................................................... 18
3.4 Exercices ...................................................................................................................... 20
4 Structure rptitive ............................................................................................................... 22
4.1 Introduction .................................................................................................................. 22
4.2 Exemple........................................................................................................................ 22
4.3 Terminaison dune boucle............................................................................................ 23
4.4 Boucles for................................................................................................................. 23
4.5 Un algorithme efficace ................................................................................................. 25
4.6 Exercices ...................................................................................................................... 27
5 Fonctions et procdures........................................................................................................ 29
5.1 Les fonctions ................................................................................................................ 29
5.2 Les procdures.............................................................................................................. 31
5.3 Porte............................................................................................................................ 33
5.4 Passage des variables dans une fonction ou une procdure ......................................... 37
6 Les structures de donnes composes .................................................................................. 40
6.1 Les tableaux.................................................................................................................. 40
6.2 Les enregistrements...................................................................................................... 43
page 3 de 84
7 Delphi ................................................................................................................................... 47
7.1 Introduction .................................................................................................................. 47
7.2 Les fichiers utiliss en Delphi ...................................................................................... 47
7.3 Lapproche Orient-Objet ............................................................................................ 48
7.4 Passage Pascal Delphi un premier exemple ........................................................... 49
7.5 Calcul de la factorielle.................................................................................................. 51
7.6 Equation du second degr............................................................................................. 53
7.7 Vrification du numro de matricule............................................................................ 57
7.8 Une petite machine calculer ...................................................................................... 60
7.9 Calcul matriciel - utilisation du composant StringGrid................................................ 65
8 La rcursivit........................................................................................................................ 70
8.1 Exemple........................................................................................................................ 70
8.2 Dfinition : fonction ou procdure rcursive ......................................................... 70
8.3 Etude dtaille dun exemple ....................................................................................... 71
8.4 Fonctionnement interne................................................................................................ 72
8.5 Exactitude dun algorithme rcursif ............................................................................. 73
8.6 Comparaison : fonction rcursive fonction itrative ................................................. 73
8.7 Rcursif ou itratif ?.....................................................................................................74
8.8 Exercices ...................................................................................................................... 75
9 Comptage et frquence......................................................................................................... 76
9.1 Algorithme de comptage .............................................................................................. 76
9.2 Frquence dune lettre dans une liste ........................................................................... 76
10 Recherche et tri................................................................................................................. 77
10.1 Introduction .................................................................................................................. 77
10.2 Sous-programmes utiles ............................................................................................... 77
10.3 Les algorithmes de tri ................................................................................................... 78
10.4 Les algorithmes de recherche....................................................................................... 83

Remarques mthodologiques
Un des soucis principaux de la Commission Nationale tait de mettre au point un programme
dintroduction lalgorithmique plutt quun cours dapplication dun langage de
programmation. Pour cette raison tous les aspects trop spcifiques ont t vits.
page 4 de 84







Premire partie

Cours de II
e


Applications en cosole

page 5 de 84
1 Introduction
1.1 Gnralits
Lobjectif de ce cours est dapprendre lart de programmer : au dpart, un nonc sera analys,
tudi et finalement transform en un programme bien structur.
La solution informatique du problme pos est appele algorithme. Celui-ci est indpendant du
langage de programmation choisi. Cependant nous devons opter pour un langage de
programmation dans lequel lalgorithme sera traduit. Dans ce cours nous allons utiliser le
langage Pascal.
Un langage de programmation est un ensemble dinstructions qui permettent de dcrire
lordinateur une solution possible du problme pos. Il existe une multitude de langages de
programmation diffrents, chacun ayant ses avantages et ses dsavantages. Exemples : Pascal,
C, Ada, Fortran, Java
Le langage Pascal est un langage de programmation volu et polyvalent, driv de lAlgol-60.
Il a t dvelopp par Niklaus Wirth au dbut des annes 1970 lcole Polytechnique Fdrale
de Zrich. Au cours des annes le langage Pascal a volu et la plus importante modification est
sans doute lincorporation de la notion de programmation oriente objet.
1.2 Cycle de dveloppement
Pour dvelopper efficacement un programme nous suivons les tapes suivantes :
Analyse du problme
Quelles sont les donnes dentre ?
Quelles sont les donnes la sortie que le programme doit produire ?
Comment devons-nous traiter les donnes dentre pour arriver aux donnes la sortie ?
tablissement dun algorithme en utilisant un langage de programmation compris par le
systme.
Traduction du programme Pascal en langage machine laide dun compilateur.
Excution et vrification du programme.
1.3 Types dapplications
Il existe deux types dapplications diffrents : les applications en console et les applications
graphiques. Les applications en console se limitent des entres et des sorties purement
textuelles. Les applications en console nutilisent pas de graphismes. Ce type dapplications tait
usuel avant larrive de Windows.
Les applications graphiques ncessitent un environnement graphique comme par exemple
Windows de Microsoft. Ce type dapplications est caractris par lutilisation de fentres pour
lentre et la sortie dinformations.
Cette anne nous allons nous limiter aux applications en console. Ces applications se
dveloppent plus facilement que les applications graphiques qui ncessitent des techniques de
programmation plus volues.
page 6 de 84
1.4 Exemple dun cycle de dveloppement
Pour rdiger, compiler et dboguer
1
un programme Pascal, nous avons besoin dun milieu de
dveloppement. Dans le cadre du cours de cette anne, nous pouvons utiliser tout compilateur
rpondant aux spcifications du langage Pascal, comme par exemple FreePascal ou Turbo
Pascal. Nous allons utiliser le milieu de dveloppement Delphi de Borland. Delphi permet de
dvelopper des applications du type console aussi bien que des applications graphiques.
1.4.1 Enonc
Nous voulons tablir un programme qui affiche un simple message sur lcran, savoir :
Bonjour tout le monde ! .
1.4.2 Analyse du problme
Il ny a pas de donnes lentre. Il ny a pas de traitement de donnes. A la sortie, il y a un
message afficher : Bonjour tout le monde !
1.4.3 Programme Pascal
program Bonjour;
begin
writeln(Bonjour tout le monde !)
end.
1.4.4 Milieu de dveloppement Delphi
Avant de dmarrer Delphi, il est impratif de crer pour chaque programme un sous-rpertoire
individuel. Tous les fichiers relatifs au programme sont alors sauvegards dans ce sous-
rpertoire.
Crez un sous-rpertoire nomm Bonjour .
Lancez le programme Delphi. Delphi vous propose immdiatement les structures pour
dvelopper une application graphique. Or nous nutilisons pas ce type dapplications pour
linstant, cest pourquoi nous fermons ce projet laide du menu : File Close All.
Ensuite nous crons une nouvelle application de type console laide du menu : File New.


1
Chercher et liminer les erreurs
page 7 de 84
Un double click sur loption Console Application ouvre une nouvelle fentre qui reoit le
code de notre programme :

Recopiez ensuite le programme propos plus haut. Noubliez pas de sauvegarder laide du
menu File Save. Lextension pour les programmes Delphi est .dpr , qui est une
abrviation de delphi project . On constate alors que dans le texte program
Project1;, le mot Project1 est remplac par le nouveau nom du fichier, sans
lextension.
1.4.5 Excution et test du programme
Aprs avoir copi le programme, vous pouvez essayer de le compiler et de lexcuter une
premire fois laide du menu Run Run ( raccourci clavier : F9 ), ou en appuyant sur le
bouton (semblabe au bouton play dun magntoscope) avec le petit triangle vert.
Si lon excute le programme, on constate quune fentre apparat brivement et quon ne voit
pas le contenu de cette fentre. Cette fentre est suppose contenir les entres et les sorties de
notre programme. Cependant dans ce cas, on naperoit pas la sortie, car la fentre disparat
immdiatement. Cette disparition provient du fait que si un programme atteint sa fin, sa fentre
est immdiatement ferme. Cest pourquoi on doit ajouter la fin de chaque programme une
instruction qui permet de geler la fentre : readln (qui attend que lutilisateur appuie sur une
touche du clavier).
1.4.6 Version dfinitive du programme
program Bonjour;
{$APPTYPE CONSOLE}
begin
writeln(Bonjour tout le monde !); {affichage}
readln; {attente}
end.
Les parties entre accolades ne font pas partie du programme proprement dit. Il sagit de
commentaires que le programmeur peut ajouter pour expliquer le fonctionnement du
programme. Ici Delphi a ajout des commentaires quil ne faut pas enlever. Le texte
{$APPTYPE CONSOLE} en particulier indique au systme quil sagit dune application en
console et non pas dune application Windows.
2


2
Pour transfrer un ancien programme crit en Pascal (Turbo Pascal, Free Pascal ou similaire) vers Delphi, il suffit
dajouter ce commentaire et de changer lextension .pas en .dpr . Le programme va alors sexcuter comme
attendu.
writeln(Bonjour tout le monde !)
page 8 de 84
2 Affectation
2.1 Entres-sorties
Dans la suite nous allons transformer notre premier programme pour quil produise un autre
effet. Les instructions, que nous allons y ajouter vont toutes se placer entre begin et end.
Les instructions write et writeln (comme write mais suivi dun saut la ligne)
permettent dafficher lcran des donnes. Ces instructions sont suivies dun point virgule
comme toute instruction Delphi.
Exemples :
writeln(4785); {affiche le nombre 4785}
writeln(47.85); {affiche le nombre dcimal 47,85 (point dcimal !!!)}
writeln(delphi); {affiche la chane de caractres delphi }

Retenons ici la rgle de syntaxe importante :
Chaque instruction se termine par un point-virgule ; .
Devant end on peut laisser de ct ce point virgule.

Linstruction readln fait attendre le programme jusqu ce que lutilisateur presse la touche
enter. Cela est ncessaire ici pour laisser lutilisateur le temps de lire laffichage avant que
le programme ne se termine et ne ferme la fentre.
Aprs avoir ajout ces instructions au programme, la partie centrale de celui-ci se prsente sous
la forme suivante.
begin
writeln(4785);
writeln(47.85);
writeln(delphi);
readln;
3

end.
Si nous lanons programme maintenant, alors laffichage est le suivant :
4785
4.78500000000000E+0001
delphi
_
Le curseur dans la quatrime ligne indique que le programme attend une entre de la part de
lutilisateur. Pressez enter pour terminer le programme.
Laffichage de 47.85 peut surprendre. Delphi utilise doffice une criture, lourde mais prcise,
en notation scientifique lire
1
10 785 . 4 .
Linstruction writeln permet de formater laffichage de la faon suivante :

3
Un tel ; devant end nest pas ncessaire, mais nous allons quand-mme le laisser systmatiquement et mettre
laccent sur les choses importantes !
page 9 de 84
writeln(47.85:10:8); {10 chiffres au total, dont 8 derrire la virgule)
writeln(4785:6); {affichage 6 places, 2 blancs suivis des 4 chiffres 4785 }
Apportez ces modifications dans le programme et relancez-le pour vous en convaincre. Essayez
dautres paramtres daffichage pour en constater leffet !
Ces formatages sont ncessaires pour garantir une bonne prsentation lcran, surtout si on
prvoit dafficher beaucoup dinformations, ventuellement en colonnes ou en tableaux.
2.2 Les oprations arithmtiques.
Delphi permet deffecteur les oprations arithmtiques et mathmatiques usuelles :
Laddition + , la soustraction -, la multiplication * , la division / donnent les
rsultats attendus.
Les parenthses peuvent tre utilises comme en mathmatiques et elles peuvent tre imbriques
plusieurs niveaux. Les crochets et accolades qui apparaissent dans des expressions
mathmatiques doivent tre remplaces par des parenthses. Delphi effectue les expressions
arithmtiques en appliquant correctement les rgles de priorit.
Les oprations div et mod sont seulement dfinies pour des nombres entiers : div donne le
quotient (entier) et mod le reste de la division euclidienne.
15 div 7 = 2 et 15 mod 7 = 1 car 15 = 7 * 2 + 1
Les fonctions sqrt (racine carre, square root ) et sqr (carr, square ) sont aussi dfinies
et utilises comme en mathmatiques mais les parenthses sont obligatoires.
Exemples Affichage
writeln(5+3*7) 26
writeln((2-7)*5+3/(2+4)) -2.45000000000000E+0001
writeln(57 div 15) 3
writeln(57 mod 15) 12
writeln(sqrt(9)) 3.00000000000000E+0000
writeln(sqr(5)) 25
writeln(sqrt(sqr(3)+sqr(4))) 5.00000000000000E+0000

Exercice 2-1
Ecrivez une instruction qui calcule et affiche le rsultat de chacune des expressions suivantes :
a) 3 : 2 4 7 15 + +
b) ( ) | | 2 8 2 7 3 14 17
c)
4 3 13
7 5 12
+


d)
( )
( ) 4 3 13
7 5 12
+


page 10 de 84
e)
( )
5 7
5 3
5
7 2
2 2

|
.
|

\
|

f)
2 2
20 48 +
Exercice 2-2
Effectuez (sans lordinateur) les expressions suivantes :
a) 86 div 15
b) 86 mod 15
c) (5-(3-7*2)*2)*2
d) sqrt(sqr(9)+19)
e) 145-(145 div 13)*13
f) 288 div 18
g) 288/18
2.3 Variables
Un concept fondamental de linformatique est celui de la variable. Comme en mathmatiques
une variable reprsente une certaine valeur. Cette valeur peut tre un nombre, une chane de
caractres, un tableau,
Le nom dune variable nest pas limit une seule lettre. Un nom de variable admissible
(accept par le systme) commence par une lettre et peut tre suivi dune suite de symboles qui
peuvent tre des lettres, des chiffres ou le blanc soulign _ ( underscore ). Un nom
valable sera appel identificateur dans la suite. Vu que le nombre de variables dun programme
peut tre trs grand, il est utile de choisir des identificateurs qui donnent une indication sur
lusage envisag de la variable.
Par exemple : Dans un programme calculant une puissance les noms de variables base et
exposant seraient appropris. Il est important de noter que ce choix est seulement fait pour
simplifier la lecture et la comprhension du programme et que la signification ventuelle du
nom chappe compltement Delphi.
Delphi ne distingue pas entre majuscules et minuscules. Les identificateurs a et A ne peuvent
donc tre discerns. Dans la suite nous nutiliserons que des lettres minuscules.
2.4 Type dune variable
Pour des raisons dorganisation de la mmoire, il est ncessaire de dclarer au dbut du
programme chaque variable et le type associ. Nous utiliserons dans la suite les types integer,
real, boolean, char, string qui sont utiliss pour reprsenter :
Type Valeur spcifications
integer
nombre entier relatif entre -2
63
et 2
63
-1
real
nombre dcimal
(en notation scientifique)
voir alina suivant
boolean
true ou false indique si une condition est vraie ou fausse
char
un caractre lettre, chiffre ou autre caractre
string
chane de caractres p.ex. 'abfzr3_45*' ou '1235'
page 11 de 84
Le type real demande plus dattention. Vu que lcriture dcimale dun nombre rel
(mathmatique) peut ncessiter une infinit de chiffres dcimaux une reprsentation fidle ne
peut pas tre garantie dans lordinateur. Chaque langage de programmation impose des
contraintes aux nombres. En Delphi un nombre de type real est reprsent par un nombre un
virgule flottante ( floating point ). Cest une notation scientifique ou la mantisse peut avoir
jusqu 15 chiffres dcimaux significatifs et lexposant est compris entre 324 et +308. Ces
bornes sont assez grandes pour garantir le bon fonctionnement de presque tout programme
raisonnable.
Le type boolean qui admet seulement les deux valeurs true et false peut surprendre. Ce type
est utilis par Delphi pour reprsenter ltat de vrit (par exemple dune condition). Une
expression comme a<5 aura comme valeur true si a est effectivement infrieur 5 et false dans
le cas contraire.
Dans un programme, un caractre ou une chane de caractres sont entours du symbole '
(apostrophe). Si la chane contient elle-mme un apostrophe, alors il faut en mettre deux de suite
sinon Delphi pense que cet apostrophe termine la chane. Ainsi lexpression lordinateur ,
scrit 'l''ordinateur' en Delphi. Il ne faut surtout pas mettre de guillemets " comme
on a lhabitude de les mettre dans un texte. Lorsque Delphi affiche un caractre ou une chane
de caractres par une instruction write ou writeln, alors les apostrophes au dbut et la fin
sont omis. De mme, un double apostrophe lintrieur dune chane est affich comme simple
apostrophe. Il est aussi dconseill dutiliser des lettres accentues, car leur affichage en console
nest pas correct.
2.5 Dclaration dune variable
Avant la premire utilisation dans un programme, une variable doit imprativement tre
dclare. Toutes les dclarations de variables suivent directement le mot rserv var et se
prsentent sous la forme :
var <ident_a1>,<ident_a2>,...,<ident_an>: <type_a>;
<ident_b1>,<ident_b2>,...,<ident_bm>: <type_b>;
...;
La syntaxe est respecter scrupuleusement :
Diffrents identificateurs de variables de mme type sont spars par une virgule ( , ).
Lidentificateur et le type sont spars par un deux-points ( : ).
Le type est suivi dun point-virgule ( ; )
Les dclarations se trouvent avant le bloc begin ... end.
Exemple :
program Project1;
{$APPTYPE CONSOLE}
var {dclarations de variables}
a,exposant:integer;
base,puissance:real;
mot:string;
begin
{instructions du programme}
end.
page 12 de 84
Cette dclaration permet au compilateur de rserver efficacement pour chaque variable lespace
mmoire ncessaire pour stocker la valeur ultrieure.
2.6 Laffectation
Jusqu prsent les variables ont t dclares mais elles ne reprsentent pas encore de valeur
dtermine. Lopration qui consiste attribuer une valeur une variable est appele affectation
et elle respecte la syntaxe suivante :
<nom_de_variable> := <expression>;
Par exemple :
a:=45;
base:=12.34;
puissance:=3*3*3*3;
mot:=test;
Delphi effectue dabord lexpression droite de := et affecte (attribue) le rsultat obtenu
la variable dont le nom se trouve gauche de := .
Pour que laffectation soit possible, il faut que le rsultat de lexpression de droite existe et
soit du mme type que la variable !
Ensuite le nom de la variable peut apparatre dans une expression.
Par exemple
nombre:=6; la valeur 6 est affecte la variable nombre
writeln(nombre+2); afficher nombre+2, cest--dire afficher 8
Lexpression de droite peut contenir aussi des variables y compris celle qui se trouve gauche
de laffectation !
nombre:=6 ; la valeur 6 est affecte la variable nombre
nombre:=nombre+2; effectuer le membre de droite : nombre+2=8 et affecter le
rsultat 8 comme nouvelle valeur la variable nombre
leffet de linstruction est donc nombre:=8;
writeln(nombre); afficher la valeur actuelle de nombre, donc 8.

2.7 Initialisation dune variable
Il est important de constater que la valeur dune variable peut varier (do le nom) au cours de
lexcution du programme. La premire affectation dune variable est appele initialisation de la
variable. Avant linitialisation, la variable a une valeur non dfinie ! Linitialisation dune
variable doit prcder lapparition de la variable dans une expression. En particulier une
affectation comme
terme:=terme+1;
nest utile que si la variable terme a t initialise auparavant. Sinon le membre de droite,
contenant terme nest pas dfini. Il est important de remarquer que le fait de ne pas initialiser
la variable ne va pas empcher le programme de dmarrer, mais le rsultat sera
vraisemblablement faux!
page 13 de 84
Exercice 2-3 (rsolu)
Les variables a, b et c sont de type integer. Faites un tableau reprenant la valeur de chaque
variable aprs chaque ligne. Un ? indiquera que la valeur de la variable nest pas connue
cet instant !
Instruction a b c
a:=7 7 ? ?
b:=4 7 4 ?
a:=a+b 11 4 ?
c:=2*a-3*b 11 4 10
b:=(a+c) div 4
11 5 10
c:=c-a 11 5 -1

Exercice 2-4
Mme question que pour lexercice prcdent.
Instruction a b c
a:=37 mod 7;

b:=a*3;
c:=a-2*b;
a:=(a*3) div 5 + a;

b:=(b-2)*(b-1);
b:=b*b;

Exercice 2-5
Mme question que pour lexercice prcdent, mais les variables sont de type real !
Instruction a b
a:=9;
b:=sqrt(a);
b:=2*b/5+a;
a:=sqr(a);
b:=b/2+a/2;
b:=(b+a)/2;

page 14 de 84
2.8 Linstruction readln
Il existe une autre mthode pour attribuer une valeur une variable : la lecture de la valeur du
clavier. Linstruction
readln(nombre);
attend que lutilisateur introduise une valeur, suivie de enter , au clavier, lit cette valeur et
laffecte la variable nombre. Si la valeur nest pas compatible avec le type de la variable,
alors le systme arrte le programme et affiche un message derreur. Pour viter ce type de
problme, il est utile dinformer lutilisateur sur ce quil est cens introduire :
write(Veuillez introduire un nombre: );
readln(nombre);
Il est important de remarquer quil faut introduire une valeur et non pas une expression
valuer. Si le programme attend un nombre et que lutilisateur introduit par exemple 2+5, alors
le systme va interrompre lexcution avec un message derreur ! Si le programme attend une
chane de caractres, alors ce type derreur ne peut pas arriver car 2+5 est une chane valable.
Il nest bien sr pas garanti que le programme va en faire un usage intelligent . Il ne va en
aucun cas valuer lexpression !
Exercice 2-6 Swap
a) crivez un programme qui lit 2 nombres entiers du clavier et les affecte respectivement aux
variables nombre1 et nombre2.
b) Ecrivez ensuite des instructions qui permettent dchanger ( swap ) les valeurs des
variables nombre1 et nombre2.
Exercice 2-7 Moyenne arithmtique
Ecrivez un programme qui lit 2 nombres rels du clavier, qui calcule et qui affiche la moyenne
(arithmtique) de ces 2 nombres.
Exercice 2-8 Moyenne harmonique
Ecrivez un programme qui lit 2 nombres rels strictement positifs du clavier, qui calcule et qui
affiche la moyenne harmonique de ces 2 nombres. Rappelons que la moyenne harmonique de 2
nombres strictement positifs est donne par la formule
2
1
1 1
b a
h
m
+
= . Il est recommand de
transformer la formule avant de lutiliser dans le programme !
Exercice 2-9 TVA
Ecrivez un programme qui lit un nombre rel strictement positif, reprsentant le prix dun article
quelconque (TVA de 15% comprise). Ensuite ce programme devra calculer et afficher le prix
hors TVA du mme article.
Exercice 2-10 Loi des rsistances
Ecrivez un programme qui lit 2 nombres rels, strictement positifs, reprsentant 2 rsistances, du
clavier. Ensuite ce programme devra calculer (par la loi dOhm) et afficher la rsistance
rsultante si lon met ces 2 rsistances en circuit parallle.
Exercice 2-11 Aire dun triangle par la formule dHron
Ecrivez un programme qui lit 3 nombres rels, reprsentant les mesures des 3 cts dun triangle
(et vrifiant ainsi lingalit triangulaire). Ensuite ce programme devra calculer (par la formule
dHron) et afficher laire du triangle correspondant ces mesures.
page 15 de 84
Exercice 2-12 Division euclidienne
Ecrivez un programme qui lit le dividende et le diviseur non nul et qui affiche la division
euclidienne rsultante.
Exemple : si le dividende est 34 et le diviseur 8, alors le programme devra afficher 34=8*4+2.
Exercice 2-13 Suite arithmtique
Ecrivez un programme qui lit le premier terme et la raison dune suite arithmtique. Ensuite le
programme lira un nombre naturel n et il calculera et affichera le n
e
terme et la somme des n
premiers termes de la suite.
2.9 Diffrents types derreurs
Si un programme ne produit pas le rsultat attendu ou pas de rsultat du tout, alors cela peut tre
d des erreurs de nature trs varie. Selon linstant o le problme se manifeste, on distingue
les erreurs et les alertes suivantes :
2.9.1 Erreur de compilation ( compilation error )
On parle derreur de compilation, si Delphi nest pas capable de traduire correctement le
programme. Lerreur la plus typique de ce genre est lerreur de syntaxe ( syntax error ), qui
indique que lcriture na pas t respecte : mot cl mal crit, ; manquant, instruction ou
expression mal formes... . Dautres erreurs de compilation apparaissent si le programme utilise
une variable non dclare auparavant ou si dans une affectation le type de la valeur et de la
variable sont incompatibles.
2.9.2 Erreur dexcution ( runtime error )
Pour ce type derreur, lexcution du programme commence correctement, mais elle est
interrompue par le systme suite un vnement non prvu. Des exemples typiques de cette
sorte sont la division par zro, la lecture dune valeur ne correspondant pas au type de la
variable.
2.9.3 Erreur de programmation
Ce type derreur ne provoque aucune raction du systme, mais il se manifeste par un rsultat
incorrect. Dans ce cas il faut revoir lalgorithme. Le programme est mal conu !
2.9.4 Alertes ( warnings )
Une alerte est un message que Delphi affiche lors de la compilation pour indiquer non pas une
erreur proprement dite, mais une instruction suspecte, de mauvais style. Un warning est par
exemple affich si une variable non initialise est utilise ou si lon dclare une variable et
ensuite elle nest jamais utilise ou sa valeur nest jamais utilise. Une alerte sert souvent
dindication pour trouver une erreur de programmation.

page 16 de 84
3 Structure alternative
3.1 Problme introductif
3.1.1 Enonc
Les compteurs de gaz affichent 5 chiffres et permettent d'indiquer des consommations allant de
00000 99999 m
3
. Lorsque la consommation est plus leve que cette valeur, le compteur
recommence 00000.
Pour calculer la consommation, on retranche le dernier affichage connu de l'affichage actuel.
La consommation ainsi obtenue est multiplie par le prix du gaz au m
3
afin d'obtenir le prix
payer.
De nos jours, le prix payer est calcul par ordinateur. Concevez un programme permettant de
raliser le calcul.

3.1.2 Premire Solution
program gaz1;
{$APPTYPE CONSOLE}
var A1,A2,CONSO:integer;
PM3,PRIX:real;
begin
write('Entrez le dernier affichage connu et l''affichage actuel : ');
readln(A1,A2);
write('Entrez le prix au m3 : ');
readln(PM3);
CONSO:=A2-A1;
PRIX:=CONSO*PM3;
writeln('Le prix a payer est de : ',PRIX);
readln;
end.
3.1.3 Exemples d'excution

A1=78000
A2=98000
PM3=0.23
Instruction A1 A2 PM3 CONSO PRIX
readln A1,A2 78000 98000 ? ? ?
readln PM3 78000 98000 0.23 ? ?
CONSO:=A2-A1 78000 98000 0.23 20000 ?
PRIX:=CONSO*PM3 78000 98000 0.23 20000 4600

page 17 de 84

A1=98000
A2=18000
PM3=0.23
Instruction A1 A2 PM3 CONSO PRIX
Readln A1,A2 98000 18000 ? ? ?
readln PM3 98000 18000 0.23 ? ?
CONSO:=A2-A1 98000 18000 0.23 -80000 ?
PRIX:=CONSO*PM3 98000 18000 0.23 -80000 -18400

On constate que dans le premier exemple, le rsultat est correct. Par contre, le rsultat du
deuxime exemple n'a pas de sens. Il ne peut y avoir de consommation ni de prix ngatifs.

La raison pour laquelle on obtient ces rsultats est que le programme ne tient pas compte du fait
que le compteur peut dpasser 100000 et que dans ce cas, il recommence 0. Dans le deuxime
cas, l'tat du compteur n'est pas 18000 mais 18000+100000=118000.
En consquence, il faudrait ajouter 100000 l'affichage actuel du compteur si cette valeur est
infrieure au dernier affichage connu.

La structure alternative permet de raliser ce genre d'oprations conditionnelles.
3.1.4 Deuxime solution
program gaz2;
{$APPTYPE CONSOLE}
var A1,A2,CONSO:integer;
PM3,PRIX:real;
begin
write('Entrez le dernier affichage connu et l''affichage actuel : ');
readln(A1,A2);
write('Entrez le prix au m3 :');
readln(PM3);
if A2>=A1 then
CONSO:=A2-A1
else
CONSO:=A2-A1+100000;
PRIX:=CONSO*PM3;
writeln('Le prix a payer est de : ',PRIX);
readln;
end.

On vrifie que le programme ci-dessus fournit les rsultats voulus dans les cas de figure
prcdents. Par contre, le cas o le compteur fait plusieurs fois le tour pour arriver au-del de
200000 n'est pas trait.
page 18 de 84

3.2 Syntaxe
3.2.1 Syntaxe simplifie
if <condition> then
<instruction>;
3.2.2 Syntaxe complte
if <condition> then
<instruction>
else
<instruction>;

Remarque importante :
L'instruction if ... then ... else est considrer comme une seule instruction.
Elle se termine donc par un seul point-virgule ( ; ) la fin
Il n'y a pas de ( ; ) aprs then ni avant else
S'il y a plusieurs instructions, il faut les mettre dans un bloc dbutant par begin et se
terminant par end

3.3 Les conditions (expressions logiques)
3.3.1 Les oprateurs relationnels

Opration Oprateur en Delphi
gal =
diffrent de <>
strictement suprieur >
strictement infrieur <
suprieur ou gal >=
infrieur ou gal <=
Deux variables de type string (chane de caractres) peuvent tre compares l'aide des
oprateurs relationnels.
ALBERTA > ALBERT et BERNARD > ALBERTA
page 19 de 84
Lordre de classement des chanes est l'ordre lexicographique (celui appliqu dans les lexiques).
Les majuscules prcdent les minuscules.
3.3.2 Les oprateurs logiques AND, OR, NOT
Les oprateurs logiques (NOT, AND, OR respectivement en franais non, et, ou) permettent de
combiner plusieurs conditions :
p.ex. (A>3) et (B<2) n'est vrai que si les deux conditions sont vrifies la fois ;
et (A>3) ou (B<0) est vrai si au moins une des conditions est vraie.

Valeur de X Valeur de Y X AND Y
TRUE TRUE TRUE
TRUE FALSE FALSE
FALSE TRUE FALSE
FALSE FALSE FALSE

Valeur de X NOT X
TRUE FALSE
FALSE TRUE
3.3.3 Rgles de priorit des oprateurs
1. NOT, -,+ (signe)
2. *, /, DIV, MOD, AND
3. +, -, OR
4. = , <= , => , < , > , <>
Valeur de X Valeur de Y X OR Y
TRUE TRUE TRUE
TRUE FALSE TRUE
FALSE TRUE TRUE
FALSE FALSE FALSE
page 20 de 84

3.4 Exercices
Exercice 3-1
Quel est le rsultat des oprations suivantes?
6 <= 10
3 = 3
NOT false
(3 > 1) AND (2 > 0)
(3 > 1) OR (2 > 0)
5 > 4
3 <> 3
NOT true
NOT (3 < 2)
(3 <= 1) AND (2 > 0)
(3 <= 1) OR (2 > 0)
Exercice 3-2
Ecrivez un programme qui affiche le quotient de deux nombres lus au clavier. Respectez le cas
o le diviseur est gal 0.
Exercice 3-3
Ecrivez un programme qui calcule la valeur absolue d'un nombre (positif ou ngatif) sans
utiliser la fonction prdfinie abs.
Exercice 3-4
Ecrivez un programme qui affiche le maximum de 2 nombres.
Exercice 3-5
Ecrivez un programme qui affiche le maximum de 3 nombres.
Exercice 3-6
crivez un programme qui vrifie si un nombre lu au clavier est divisible par 2.
Exercice 3-7
Modifiez les valeurs de trois variables A, B, C entres au clavier de manire avoir A B C.
Exercice 3-8
Afficher la moyenne de 3 nombres lus au clavier. La moyenne est arrondie vers le haut. Le
programme affiche un message moyenne insuffisante si elle est infrieure 30, sinon il
affiche moyenne suffisante .
Exercice 3-9
Imprimez le signe du produit de deux nombres sans faire de multiplication.

page 21 de 84
Exercice 3-10
Imprimez le signe de la somme de deux nombres sans faire d'addition.
Exercice 3-11
Vrifiez la validit d'un numro de compte chque postal. Le numro de contrle est le reste de
la division euclidienne du numro principal par 97. Si la division est sans reste alors le numro
de contrle est 97.
Exercice 3-12
Soit une quation de la forme ax
2
+bx+c=0.
a) Rsolvez cette quation en supposant a 0.
b) crivez un nouveau programme qui tient compte du fait que les paramtres a, b, c
peuvent tre nuls
page 22 de 84
4 Structure rptitive
4.1 Introduction
Les programmes rencontrs jusqu prsent sont dune utilit trs limite. En effet le gain de
temps ralis laide de lordinateur est quasi nul (par rapport une calculatrice par exemple).
Lunique avantage provenait du fait quun mme programme peut tre rutilis pour diffrentes
valeurs des donnes. Cette situation va changer radicalement dans ce chapitre. Le mcanisme de
structure rptitive permet dexcuter plusieurs fois une certaine partie dun programme !
4.2 Exemple
Considrons la partie suivante dun programme :
var i,puiss:integer;
...
puiss:=1;
i:=1;
while i<=15 do
begin
puiss:=puiss*2;
i:=i+1;
end;
Que fait ce programme?
Dabord les variables puiss et i sont initialises 1. Ensuite nous arrivons la nouvelle
instruction
while <condition> do <instruction>;
qui comme son nom lindique excute instruction aussi longtemps que condition est
vrifie. Linstruction suivant le do est appele corps de boucle ; elle peut tre constitue
dune instruction simple ou dun bloc begin ... end.
Dans notre exemple
1. Dabord la condition est teste. Elle est vrifie car i=1 et donc i<=15.
2. Ensuite puiss est multiplie par 2 et i augmente de 1.
3. Lexcution reprend au point 1 (avec les nouvelles valeurs des variables)
4. La condition est nouveau teste. Elle est vrifie car i=2 et donc i<=15
5. Ensuite puiss est nouveau multiplie par 2 et i augmente de 1.
6. Lexcution ne quitte la boucle que si la condition nest plus vrifie ! Cela arrive
lorsque i atteint la valeur 16 (i est entier et augmente de 1 chaque passage dans la
boucle). La boucle est donc excut 15 fois car si on part de i :=1, il faut ajouter 15
fois le nombre 1 i pour arriver 16. En mme temps puiss aura t multiplie 15 fois
de suite par 2. Vu que puiss avait la valeur 1 avant le premier passage de boucle
puiss aura la valeur 1*2*2*2*2*2=2
15
=32768.


page 23 de 84
Exercice 4-1
On donne la partie de programme (toutes les variables sont de type integer) :
resultat:=1;
facteur:=5;
while facteur > 1 do
begin
resultat:=resultat*facteur;
facteur:=facteur-1;
end;
writeln(resultat);
Simulez lexcution de ce programme en reprsentant dans un tableau les valeurs successives
des variables. Que va afficher le programme ?
Compltez (entte, dclarations, etc.) le programme pour quil soit accept par Delphi et vrifiez
votre rsultat !

4.3 Terminaison dune boucle
Lors de la conception dune boucle, il est essentiel de veiller ce que la boucle se termine, cest-
-dire quaprs un nombre fini de passages la condition de boucle va finir par ne plus tre
vrifie. Si la boucle ne sarrte pas, lutilisateur va perdre patience un instant ou un autre et il
se verra forc dinterrompre lexcution du programme (menu Run Program Reset). Cette
situation dsagrable doit tre vite tout prix !
i:=1;
while i<=5 do
begin
puiss:=puiss*2;
end;
Cette boucle est mal conue car la seule variable i de la condition nest pas modifie dans le
corps de boucle. chaque passage lvaluation de la condition donne le mme rsultat et le
programme ne va plus sortir de la boucle.
4.4 Boucles for
4.4.1 Boucles for to
Dans beaucoup de cas on peut simplifier lcriture du programme en utilisant une boucle for.
Exemple dune boucle for :
puiss:=1;
for i:=1 to 5 do puiss:=puiss*2;
Dans la boucle for, moins flexible que while, la condition est remplace par un compteur
(dans lexemple prcdent le compteur est la variable i). Ce compteur est initialis une
certaine valeur (ici 1, par i:=1) et augment de 1 chaque passage de boucle. La boucle va
tre parcourue jusqu ce quune valeur finale (ici 5) soit atteinte. Les valeurs initiale et finale
sont calcules une fois pour toute avant lentre dans la boucle. Elles ne sont plus rvalues
plus tard. Ds lentre dans la boucle le nombre de passages est donc connu. Le compteur et les
valeurs initiale et finale seront tous de type integer.
page 24 de 84
Si par malheur (cette situation tmoigne souvent dune mauvaise analyse du problme) la valeur
initiale est suprieure la valeur finale, alors le corps de boucle nest pas excut du tout.
Une boucle for de la forme for i:=a to b do <instruction>; peut toujours tre
rcrite en boucle while de la manire suivante sans que leffet du programme ne change :
4

i:=a
while i<=b do begin <instruction>; i:=i+1 end;
Le passage dune boucle while une boucle for nest pas toujours possible sans changer la
nature de lalgorithme. Cela est clair vu quune boucle for se termine toujours alors que ce
nest pas le cas de toute boucle while.
4.4.2 Boucles for downto
Il existe une variante de la boucle for o le compteur est diminu de 1 chaque passage :
for i:=a downto b do <instruction>;
qui a le mme effet net que
i:=a
while i>=b do begin <instruction>; i:=i1 end;
Exercice 4-2
On donne la partie de programme (toutes les variables sont de type integer) :
resultat:=0;
terme:=7;
for i :=0 to 5 do
resultat:=resultat+terme;
writeln(resultat);
Simulez lexcution de ce programme en reprsentant dans un tableau les valeurs successives
des variables. Que va afficher le programme ?
Compltez (entte, dclarations, etc...) le programme pour quil soit acceptable par Delphi et
vrifiez votre rsultat !
Exercice 4-3
Rcrivez le programme prcdent laide dune boucle while.
Compltez ensuite le programme pour quil soit accept par Delphi et vrifiez votre rsultat !
Exercice 4-4 Somme de nombres lus du clavier
Ecrivez un programme qui calcule et affiche la somme de nombres rels lus successivement du
clavier. Le programme continue jusqu ce que lutilisateur entre le nombre 0. Sil entre 0
comme premier nombre, le programme affichera 0.
Est-ce que vous allez utiliser une boucle for ou une boucle while ? Expliquez votre choix !
Exercice 4-5 Somme de n nombres lus du clavier
Ecrivez un programme qui lit dabord le nombre naturel n, reprsentant le nombre de termes
ajouter. Ensuite le programme va lire n nombres rels du clavier, calculer leur somme et
lafficher.

4
condition que les valeurs des variables i et b ne soient pas modifies lintrieur du bloc <instruction>
page 25 de 84
Est-ce que vous allez utiliser une boucle for ou une boucle while ? Expliquez votre rponse
et comparez avec lexercice prcdent !

Exercice 4-6 (*) Table de multiplication
Ecrivez un programme qui calcule et affiche une table de multiplication ( Einmaleins ) de 00
jusqu 1010. Laffichage doit se faire sous forme de tableau bien format .

4.5 Un algorithme efficace
Le premier programme calcule une puissance (de base relle non nulle et dexposant naturel) par
un algorithme simple bas sur la dfinition par multiplications successives :

=
=
+
a a a
a
n n 1
0
1

program puisssance;
{$APPTYPE CONSOLE}
var
expo:integer;
base,puiss:real;
begin
writeln(Introduisez la base (reelle non nulle): )
readln(base);
writeln(Introduisez lexposant (naturel): )
readln(expo);
puiss:=1;
while expo<>0 do
begin
puiss:=puiss*base;
expo:=expo-1 ;
end;
writeln(la puissance vaut,puiss)
end.
Ce premier programme effectue toujours n multiplications pour une puissance dexposant n.
Pour le deuxime programme, le nombre de multiplications va se rduire de faon spectaculaire.
Il suffit dajouter une ligne supplmentaire la dfinition pour traiter les exposants pairs.
( )

=
=
=
+
a a a
a a
a
n n
n
n
2 1 2
2 2
0
1

Le programme nest pas trs diffrent de la puissance simple . A lintrieur de la boucle,
lexcution diffre selon la valeur de la variable expo. Si expo est pair, on peut appliquer la
formule ( )
n
n
a a
2 2
= . Cela consiste remplacer la base par son carr et rduire lexposant de
moiti. Si expo nest pas pair, alors le programme applique le mme algorithme que la
puissance par produits successifs. Remarquons que dans ce cas, lexposant est diminu de 1 et
quil va donc devenir pair pour le prochain passage dans la boucle ! Donc lexposant est rduit
de moiti aprs au plus deux passages dans la boucle. Ainsi pour nimporte quel exposant
page 26 de 84
infrieur 1024 le nombre de produits calculer ne va pas dpasser 20 (car 1024 2
10
= ), alors
que
1000
2 ncessite exactement 1000 produits avec lalgorithme simple !
Examinons le fonctionnement du programme laide dun exemple dexcution. Pour calculer
8192 2
13
= , les variables base, expo et puiss vont prendre successivement les valeurs
reprises dans le tableau suivant. On remarquera que lexpression puiss base I =
expo
garde la
mme valeur aprs chaque passage de la boucle. Cette expression est un invariant. La notion
dinvariant est utile pour montrer lexactitude dun programme.
Base Expo puiss
puiss base I =
expo

2 13 1
8192 1 2
13
= = I
2 1 13 12 = 2 1 2 =
8192 2 2
12
= = I
2 2 4 = 2 : 12 6 = 2
8192 2 4
6
= = I
4 4 16 = 2 : 6 3 = 2
8192 2 16
3
= = I
16 1 3 2 = 16 2 32 =
8192 32 16
2
= = I
256 1 32
8192 32 256
1
= = I
256 0 8192
8192 8192 256
0
= = I
Et voici le programme :
program puisssance_rapide;
{$APPTYPE CONSOLE}
var
expo:integer;
base,puiss:real;
begin
writeln(Introduisez la base (reelle non nulle): )
readln(base);
writeln(Introduisez lexposant (naturel): )
readln(expo);
puiss:=1;
while expo<>0 do
begin
if (expo mod 2)=0 then
begin
base:=base*base;
expo:=expo div 2
end
else
begin
puiss:=puiss*base;
expo:=expo-1 ;
end;
end;
writeln(la puissance vaut,puiss)
end.
page 27 de 84

4.6 Exercices
Exercice 4-7 Suite arithmtique
crivez un programme qui lit le premier terme et la raison dune suite arithmtique. Ensuite le
programme lira un nombre naturel n et il calculera par sommation et affichera le n
e
terme et la
somme des n premiers termes de la suite. Dans cet exercice, contrairement lexercice de mme
nom du chapitre 2, on nutilisera pas les formules des suites arithmtiques mais seulement la
dfinition par rcurrence.
Exercice 4-8 Suite gomtrique
Mme question pour une suite gomtrique.
Exercice 4-9 Factorielle
La factorielle dun nombre naturel n, note n! est dfinie par
( ) ( )

+ = +
=
1 ! ! 1
1 ! 0
n n n

donc si n nest pas nul on a: n!=n(n-1)(n-2)...321 et en particulier 1!=1, 2!=21=2,
3!=321=6, 4!=4321=24 etc.
a) crivez un programme qui lit un nombre naturel n et qui calculera et affichera ensuite n! par
une boucle for...to.
b) Mme question mais avec une boucle for...downto.
c) Mme question mais avec une boucle while.
Exercice 4-10 (*) PGCD par lalgorithme dEuclide (par soustraction)
Les formules dEuclide pour trouver le pgcd de 2 nombres naturels non nuls sont :

> =
=
=
b a si b b a b a
a b b a
a a a
) , ( pgcd ) , ( pgcd
) , ( pgcd ) , ( pgcd
) , ( pgcd

crivez un programme qui lit les 2 nombres naturels a et b et qui calcule et affiche leur pgcd en
utilisant ces formules.
Exercice 4-11 (*) PGCD par lalgorithme dEuclide (par division)
Les formules suivantes, aussi attribues Euclide, mnent plus vite au rsultat :
( )

> > =
=
=
0 ) , mod ( pgcd ) , ( pgcd
, pgcd ) , ( pgcd
) 0 , ( pgcd
b a si b b a b a
a b b a
a a

crivez un programme qui lit les 2 nombres naturels a et b et qui calcule et affiche leur pgcd en
utilisant ces formules.
Exercice 4-12 (*) Test de primalit
crivez un programme qui lit un nombre naturel non nul n et qui vrifie ensuite si n est premier.
Vous pourrez amliorer le programme en nessayant que les diviseurs potentiels infrieurs ou
gaux n .
page 28 de 84

Exercice 4-13 (**) Factorisation premire
En vous basant sur lexercice prcdent, crivez un programme qui lit un nombre naturel non
nul n et qui calcule et affiche ensuite la dcomposition en facteurs premiers de ce nombre :
Exemple : Pour 360, le programme affichera : 360=222335
Exercice 4-14 (***) Factorisation premire (produit de puissances)
Mme question qu lexercice prcdent, mais on demande dafficher le rsultat comme produit
de puissances.
Exemple : Pour 360, le programme affichera : 360=2^33^25^1



page 29 de 84
5 Fonctions et procdures
5.1 Les fonctions
5.1.1 Introduction
Exemple
crivons un programme qui calcule le nombre de combinaisons de n objets p p.
Rappelons que ce nombre se dtermine par la formule :
)! ( !
!
p n p
n
p
n

=
|
|
.
|

\
|

En regardant cette formule nous constatons que pour chaque calcul d'un nombre de
combinaisons nous devons effectuer trois fois le calcul d'une factorielle et ainsi rpter trois fois
le mme code. Les fonctions ont t dveloppes pour viter ces redondances dans les
programmes.
Grce elles il suffit de noter une fois le code de calcul de la factorielle et de l'utiliser chaque
besoin.
tablissons d'abord le calcul de la factorielle sous forme de fonction.

function fact(a:integer):integer;
var i, res : integer;
begin
i:=2;
res:=1;
while i<=a do
begin
res:=res*i;
i:=i+1;
end;
result:= res;
end;

L'identificateur a est un paramtre dont la valeur va tre fixe chaque nouvel appel de la
fonction.
Il est important de remarquer que la fonction fact retourne une valeur qui sera transmise au
programme appelant.
Une fonction, une fois dfinie comme telle, peut tre utilise sous son nom dans le programme
principal, qui va donc avoir la forme :

program factorielle;
{$APPTYPE CONSOLE}
var n, p, res_c : integer;
{***************************************}
function fact(a:integer) :integer;
var i, res : integer;

page 30 de 84
begin
i:=2;
res:=1;
while i<=a do
begin
res:=res*i;
i:=i+1;
end;
result:= res;
end;
{**************************************}
begin
write('n = ');
readln(n);
write('p= ');
readln(p);
res_c:= fact(n) div (fact(p)*fact(n-p));
write('Nombre de combinaisons de ',n,' objets ',p,' a ',p,' =
',res_c);
readln;
end.
5.1.2 Dfinition
Une fonction est une partie de code d'un programme que nous pouvons utiliser plusieurs fois.
Chaque fois que nous utilisons la fonction nous pouvons lui transmettre d'autres valeurs qu'elle
utilisera pendant son excution. Le code de la fonction est plac directement aprs les
dclarations de variables (du programme principal).
Syntaxe de la dfinition d'une fonction
function nom(paramtre1:type1 ; paramtre2:type2 ; ) : type;
var
begin
<instructions>
result := <valeur transmettre>
end;
Lorsquon utilise plusieurs paramtres de mme type alors on peut utiliser la syntaxe simplifie :
function nom(paramtre1A , paramtre1B: type1 ; ) : type;
Avant le mot clef end doit toujours figurer laffectation qui indique le rsultat faire passer au
programme appelant. Dans cette affectation, on utilise comme variable gauche lidentificateur
result ou le nom de la fonction.
Syntaxe de l'appel d'une fonction dans le programme appelant
nom(valeur1,valeur2, ) ;
Les valeurs valeur1, valeur2, ... sont affectes aux paramtres formels paramtre1,
paramtre2,... dans le mme ordre qu'ils interviennent dans la partie dclarative de la fonction.
Dans le corps de la fonction les paramtres formels se comportent comme des variables et ils
peuvent tre utiliss comme telles.
page 31 de 84
On remarquera que dans la dfinition, des paramtres de types diffrents sont spars par un
; , alors que dans lappel tous les paramtres sont suivis dun , .
Une fonction peut contenir elle-mme une ou plusieurs fonctions dont elle a besoin.
Exercice 5-1
crivez une fonction qui retourne le maximum de 3 valeurs.
Exercice 5-2
crivez une fonction qui dtecte si une chane de caractres est vide.
Exercice 5-3
crivez une fonction qui compte le nombre de chiffres contenus dans une chane compose de
chiffres et de lettres.
Exercice 5-4
crivez un programme qui lit le numrateur et le dnominateur d'une fraction et fournit la
fraction simplifie.

5.2 Les procdures
Exemple
crivez un programme moy qui lit successivement trois valeurs positives a, b et c et dtermine
la moyenne arithmtique. La valeur de a doit tre infrieure 10, celle de b infrieure 20 et
celle de c infrieure 30.
Si les valeurs ne vrifient pas ces conditions, le programme met un message d'erreur, aussitt la
valeur saisie. Si les valeurs sont correctement saisies, le programme affiche la moyenne
arithmtique.
Ici aussi nous voyons que le message d'erreur peut tre plusieurs fois le mme. Il n'est donc pas
ncessaire de mettre plusieurs fois le code servant afficher le message d'erreur. De plus si nous
voulons modifier le texte des messages, il suffit de le changer une fois.
Pour ce faire nous utilisons les procdures.
La diffrence entre une procdure et une fonction se trouve dans le fait qu'une fonction renvoie
une valeur au programme appelant tandis qu'une procdure effectue un traitement (affiche un
message lcran) mais ne renvoie pas de valeur.
program moy;
{$APPTYPE CONSOLE}
var
a, b, c : integer;
moy : real;
(****************************************)
procedure erreur();
begin
writeln('Valeur incorrecte. Recommencez.');
end;
(****************************************)
begin
a:= 10;
b:= 20;
page 32 de 84
c:= 30;
while a>=10 do
begin
write('Valeur 1 (<10): ');
readln(a);
if a>=10 then
erreur();
end;
while b>=20 do
begin
write('Valeur 2 (<20): ');
readln(b);
if b>=20 then
erreur();
end;
while c>=30 do
begin
write('Valeur 3 (<30): ');
readln(c);
if c>=30 then
erreur();
end;
moy:= (a+b+c)/3;
writeln('La moyenne de ',a,',',b,' et ',c,' vaut ',moy:5:2);
readln;
end.

5.2.1 Dfinition
Une procdure est, comme une fonction, une partie de code que nous pouvons utiliser plusieurs
fois. Le code de la procdure est aussi plac directement aprs les dclarations de variables (du
programme principal).
La diffrence entre une fonction et une procdure rside dans le fait qu'une procdure ne
transmet pas de valeur au programme appelant. Comme effet une procdure peut afficher un
message lcran ou modifier des variables du programme.
Syntaxe de la dfinition d'une procdure
procedure nom (paramtre1 : type1 ; paramtre2 : type2 ; );
var
begin
<instructions>
end;
Syntaxe de l'appel en Delphi d'une procdure dans le programme appelant
nom(valeur1, valeur2 ) ;
Ici aussi, les valeurs valeur1, valeur2, ... sont affectes aux paramtres formels var1, var2, ... dans le
mme ordre qu'ils interviennent dans la partie dclarative de la procdure. Dans le corps de la procdure
les paramtres formels se comportent comme des variables et peuvent tre utiliss comme telles.
page 33 de 84
5.2.2 Avantages des fonctions et procdures
Nous vitons les redondances : Avec ces notions nous ne rptons pas inutilement du code.
Ceci rend les programmes plus petits.
Nous retrouvons facilement les fonctions et/ou procdures : Si nous voulons modifier un
programme nous n'avons pas besoin de passer en revue toutes les pages du code.
La lisibilit est amliore : Il est plus facile de relire du code, surtout si nous ne l'avons pas
rdig nous-mmes.
Les fonctions et procdures sont portables : Une fonction et/ou une procdure une fois
crite pour un certain programme peut tre rutilise pour un autre programme sans pour
autant la rcrire. Nous pouvons ainsi construire des bibliothques de telles fonctions ou
procdures.
5.2.3 Exercices
Adaptez les programmes des chapitres prcdents en les crivant l'aide de fonctions et de
procdures chaque fois que cela est utile.

5.3 Porte
On appelle porte d'une fonction, procdure ou d'une variable la partie du code dans laquelle
elles conservent la signification dfinie par la dclaration, c'est--dire dans laquelle elles
peuvent tre utilises comme elles ont t dfinies.
5.3.1 Porte d'une fonction/procdure
Rgle 1 :
En Delphi une fonction ou une procdure n'est connue que si sa dfinition prcde
lendroit do elle est appele.
Exemple :
program por11;
{$APPTYPE CONSOLE}
{******************************************}
function f: integer;
var f1 : integer;
begin
f1 := 23;
result := f1;
end;
procedure p;
begin
writeln(f);
end;
{******************************************}
begin
p;
readln;
end.
page 34 de 84
Ce programme donnera comme rsultat 23.
Si nous dfinissons la procdure p avant la fonction f, le programme marquera comme erreur
qu'il ne trouve pas la fonction f.
Rgle 2 :
Une fonction ou procdure dfinie l'intrieur d'une autre fonction ou procdure n'est
connue que dans celle-ci.
Exemple :
program por12;
{$APPTYPE CONSOLE}
var v : integer;
{***********************************************}
procedure p1(a:integer);
{*************************************}
function carre(p: integer): integer;
var res: integer;
begin
res:=p*p;
result:=res;
end;
{************************************}
begin
writeln('a*a = ',carre(a));
end;
{**********************************************}
begin
v:=4;
p1(v);
readln;
end.
Ce programme donnera comme rsultat 16.
Si nous remplaons l'appel p1(v) par writeln('v*v = ',carre(v)); le compilateur
nous donne l'erreur Undeclared identifier: 'carre', puisque la fonction carre est dclare dans la
procdure p1 et ainsi elle n'est pas connue l'extrieur de cette procdure.
5.3.2 Porte des variables
Nous distinguons entre deux types de variables: les variables locales une fonction/procdure et
les variables globales.
Une variable est locale une fonction/procdure si elle est dclare dans la fonction/procdure ;
Exemple :
program por21;
var a: integer;
{$APPTYPE CONSOLE}
{p1***********************}
procedure p1;
var a_1: integer;
{p11***************}
procedure p11;
var a_11 : integer;
page 35 de 84
begin

end;
{p11**************}
begin

end;
{p1***********************}
begin

end.
Dans cet exemple la variable a est globale, tandis que les variables a_1 et a_11 sont des
variables internes respectivement p1 et p11.
Rgle 3 :
La porte d'une variable locale est strictement limite la fonction ou la procdure o
elle est dclare.
La porte d'une variable est interrompue chaque fois que dans la lecture du code nous
rencontrons le code d'une fonction ou d'une procdure interne dans lequel le mme
identificateur est utilis.

Exemple :
program por22;
{$APPTYPE CONSOLE}
{***************************************}
procedure p1;
var a : integer;
procedure p11;
var a : integer;
begin
a := 12;
write('Valeur de a dans p11 :');
writeln(a);
end;

begin
a:= 5;
write('Valeur de a avant p11 :');
writeln(a);
p11;
write('Valeur de a apres p11 :');
writeln(a);
end;
{***************************************}
begin
p1;
readln;
end.
Voici un tableau qui montre le droulement du programme.
page 36 de 84
Programme
principal
procedure p1 procedure p11 a
program
Project1;
{$APPTYPE
CONSOLE}

begin


procedure p1;

var a : integer;


a:= 5; 5
write('Valeur de a
avant p11 :');
5
writeln(a); 5
procedure p11; 5
var a : integer;
begin
a := 12; 12
write('Valeur de a
dans p11 :');
12
writeln(a); 12
p11;
end; 5
write('Valeur de a
apres p11 :');

5
writeln(a); 5
p1;
end;


readln;
end.



page 37 de 84
5.3.3 Exercice
Soit le code suivant :

program expor;
{$APPTYPE CONSOLE}
var a, b, c : integer;
procedure p1();
var a, b:integer;
begin
a:= 2;
b:= 4;
writeln('a= ',a,', b= ',b,', c= ',c);
end;
{**************************************}
begin
a:= 10;
b:= 15;
c:= 30;
writeln('a= ',a,', b= ',b,', c= ',c);
p1();
writeln('a= ',a,', b= ',b,', c= ',c);
readln;
end.

Dterminez les valeurs qui seront sorties par le programme.
5.4 Passage des variables dans une fonction ou une
procdure
Exercice: crivez une procdure qui change deux variables.
crivons notre programme de la faon suivante:

program pass1;
{$APPTYPE CONSOLE}
var a,b : integer;
procedure ech(v1, v2: integer);
var temp: integer;
begin
temp:= v1;
v1:= v2;
v2:= temp
end;

begin
write('a= '); readln(a);
write('b= '); readln(b);
ech(a,b);
write('a= ',a,' b= ',b)
readln;
end.
page 38 de 84
Ce programme ne ralisera pas l'effet escompt, mais laissera inchanges les valeurs des
variables. Ceci est d au fait quen Delphi, le passage des paramtres se fait, sauf indication
spciale, par valeurs.
Passons en revue les valeurs des diffrentes variables lors du droulement du programme:
Supposons qu'on donne a la valeur 5 et b la valeur 8.

program pass1;
var a,b : integer; cration de
a
cration de b
Begin
write('a= ');
readln(a);
5
write('b= ');
readln(b);
8
procedure ech(
v1 , v2: integer);

cration de v1
avec la valeur 5
cration de v2
avec la valeur 8

var temp: integer
cration de
temp
temp:= v1;
5
v1:= v2;
8
v2:=temp
5
end; {ech)
destruction de v1 destruction de v2 destruction de
temp
write('a= ',a,' b=
',b)
sortie de la
valeur de a:
5
sortie de la
valeur de b:
8

End. destruction
de a
destruction
de b


Au moment du passage des valeurs une copie est faite, sur laquelle agit la procdure ech. En
sortant de la procdure ech toute rfrence cette copie est dtruite et nous nous retrouvons
avec les anciennes valeurs de a et de b.
Une autre mthode de passage des valeurs est celle qu'on appelle normalement par rfrence ou
par variable. Cette dernire appellation est utilise en Delphi.
Avec cette mthode de passage des valeurs une rfrence est passe au programme appel qui
permet d'accder directement la variable du programme appelant.
Pour arriver en Delphi un passage des valeurs par variable nous devons faire prcder
les diffrents paramtres formels par le prfixe VAR.
Dans notre exemple la ligne de dfinition de la procdure ech aura donc la forme:
procedure ech(var V1, V2: integer);

page 39 de 84
Si nous voulons donc qu'une variable dfinie dans le programme appelant change de
valeur par une action dans le programme appel, nous devons passer la valeur par
rfrence.
5.4.1 Exercices
crivez une procdure qui change deux valeurs.
Utilisez cette procdure pour classer 4 valeurs lues au clavier lors du droulement du
programme.
Soit le code suivant :
program pass;
{$APPTYPE CONSOLE}
var a,b : integer;
procedure p1(a,b :integer);
begin
a:=a+2;
b:=b*b;
writeln('Dans la procedure p1');
writeln('a=',a,' b=',b);
end;
procedure p2(a: integer; var b :integer);
begin
a:=a+2;
b:=b*b;
writeln('Dans la procedure p2');
writeln('a=',a,' b=',b);
end;
begin
a:=5;
b:=7;
writeln('Avant la procedure p1');
writeln('a=',a,' b=',b);
p1(a,b);
writeln('Apres la procedure p1');
writeln('a=',a,' b=',b);
p2(a,b);
writeln('Apres la procedure p2');
writeln('a=',a,' b=',b);
readln ;
end.
Quel est l'effet de ce programme, c'est--dire quelles sont les valeurs de a et de b qui
seront dites ?

page 40 de 84
6 Les structures de donnes composes
Jusqu prsent nous navons utilis que des donnes de type simple : entier, rel, boolen et
chanes de caractres. Une variable de type simple ne peut reprsenter quune seule donne.
Dans ce chapitre nous allons dcouvrir les donnes de type structur. Ces donnes ont la
proprit que chaque identificateur individuel peut reprsenter des donnes multiples. On peut
traiter lensemble de ces donnes multiples aussi bien que les donnes individuelles. Les
donnes de type structur se manipulent donc collectivement ou individuellement.
6.1 Les tableaux
6.1.1 Gnralits
Un tableau est une structure de donnes qui regroupe des donnes de type identique. On peut
dfinir des tableaux dentiers, de rels, de boolens, de chanes de caractres ou bien de tout
autre type identique. Laccs chaque lment dun tableau se fait moyennant un indice.
6.1.2 Dclaration
Comme pour les variables de type simple, les tableaux doivent tre dclars. Cette dclaration
doit comporter un nom et le type de donnes contenues dans le tableau. En plus on doit indiquer
le nombre dlments. On obtient la syntaxe suivante :
nom: array [A .. B] of type
avec :
nom : nom du tableau
A : dbut de lindice
B : fin de lindice
type : type de donne des lments du tableau
Exemples :
Tableau de 100 entiers :
Entiers : array [1..100] of integer;
Tableau de 50 noms :
Noms : array [51..100] of string;
Tableau de 30 rels :
Reels: array [30..59] of real;
Tableau de 15 boolens :
Booleens: array [31..45] of boolean;
6.1.3 Accs aux lments
Aprs avoir dclar un tableau, on peut utiliser les diffrents lments du tableau comme des
variables : On peut faire des accs en criture (affectation) ou en lecture. Laccs aux diffrents
lments du tableau est effectu moyennant un indice. Cet indice est not aprs le nom du
tableau entre crochets.


page 41 de 84
Exemples :
Les exemples suivants utilisent les dclarations ci-dessus.
Ecriture de la valeur 5 dans llment 3 du tableau Entiers :
Entiers[3]:=5
Affichage de la valeur de llment 3 du tableau Entiers :
writeln(Entiers[3]);
Affichage de toutes les valeurs du tableau Noms :
for I:=51 to 100 do
writeln(Noms[I]);
6.1.4 Remarques
Comme pour les variables simples, les lments dun tableau doivent tre initialiss avant tout
accs en lecture.
On doit respecter les limites de lindice : Tout accs un lment portant un indice non dfini
lors de la dclaration est interdit.
6.1.5 Exemple
Ecrivez un programme qui demande lutilisateur 10 entiers, les stocke dans un tableau et les
affiche ensuite.
program Exemple;
{$APPTYPE CONSOLE}
var
I:integer;
Tableau:array[1..10] of integer;
begin
for I:=1 to 10 do
readln(Tableau[I]);
for I:=1 to 10 do
writeln(La ,I,ime valeur vaut : ,Tableau[I]);
end.
6.1.6 Exercices
Exercice 6-1
Ecrivez un programme qui demande lutilisateur 5 rels, les stocke dans un tableau et affiche
la fin le contenu du tableau sur lcran.
Exercice 6-2
Remplissez un tableau avec 20 entiers alatoires
5
. Affichez-le puis recherchez le minimum et le
maximum du tableau et affichez-les.

5
Pour obtenir un nombre alatoire, il faut utiliser la fonction random (consulter laide en ligne (F1) pour plus de
dtails).
page 42 de 84

Exercice 6-3
Remplissez un tableau avec 10 entiers alatoires. Calculez la somme, la moyenne et lcart-type
des valeurs du tableau. Affichez le contenu du tableau ainsi que la somme, la moyenne et
lcart-type.

Exercice 6-4
Remplissez un tableau avec 100 entiers alatoires compris entre 10 et 25. Comptez le nombre
doccurrences (frquence) dun entier entr par lutilisateur.
Exercice 6-5
Rdigez un programme qui remplit un tableau avec 10 entiers alatoires. Affichez-le. Inversez
ensuite lordre des nombres dans le tableau et affichez ensuite le tableau rarrang.
Exercice 6-6
On vous donne le numro dun jour dune anne. En supposant quil ne sagit pas dune anne
bissextile, dterminez le jour et le mois en question.
Exercice 6-7
Demandez lutilisateur les coefficients dun polynme de degr 5. Calculez les coefficients de
la drive de ce polynme. Demandez lutilisateur une valeur relle pour valuer le polynme
ainsi que sa drive en utilisant le schma de Horner.
Exercice 6-8
Demandez lutilisateur les coefficients de deux polynmes de degr 4. Calculez les
coefficients de la somme, de la diffrence et du produit de ces deux polynmes et affichez-les.
Exercice 6-9 (**) Conversion dcimale binaire
Ecrivez un programme qui lit un nombre naturel (en notation dcimale) non nul n. Le
programme transformera et affichera ensuite ce nombre en notation binaire.
Exemple : Pour 43, on affichera : 101011 car
0 1 2 3 4 5
2 1 2 1 2 0 2 1 2 0 2 1 43 + + + + + =
Exercice 6-10 (**) Conversion binaire dcimale
Ecrivez un programme qui lit un nombre naturel (en notation binaire) non nul n. Le programme
transformera et affichera ensuite ce nombre en notation dcimale.
Exemple : Pour 101011, on affichera : 43. Le programme na pas besoin de vrifier si le nombre
donn est effectivement en criture binaire (seulement chiffres 0 et 1).
Exercice 6-11 (***) Simulation dun tirage Lotto
Un joueur peut choisir 6 nombres entiers entre 1 et 49. Faites la saisie des nombres proposs par
le joueur et mmorisez-les laide dun tableau de boolens. Veillez ce les 6 nombres soient
distincts deux deux.
Effectuez ensuite le tirage. Utilisez nouveau un tableau de boolens pour mmoriser le tirage.
Veillez ce quil y ait exactement 6 nombres diffrents.
Dterminez ensuite combien de nombres le joueur a devin correctement et affichez le tirage
ainsi que les nombres correctement devins.
page 43 de 84
6.2 Les enregistrements
6.2.1 Gnralits
Un enregistrement est une structure de donnes qui permet de regrouper des donnes nayant
pas besoin dtre de mme type. Les donnes qui composent un enregistrement sont appels :
champs. Un champ peut avoir nimporte quel type : integer, real, boolean, string, array ou mme
un autre enregistrement.
6.2.2 Dclaration
Comme pour les variables de type simple, les enregistrements doivent tre dclars. Cette
dclaration doit comporter un nom et doit numrer les diffrents champs contenus dans
lenregistrement. Pour chaque champ il faut spcifier son nom et son type. On obtient la syntaxe
suivante :
nom:record
champ1:type1;
champ2:type2;
champ3:type3;

champN:typeN;
end;
avec :
nom : nom de lenregistrement,
champ1 champN : noms des diffrents champs de lenregistrement,
type1 typeN : type de donne du champ concern.

Exemples :

Enregistrement dcrivant une date :
date:record
jour:integer;
mois:string;
annee:integer;
end;

Enregistrement dcrivant un vecteur du plan, deux enregistrements sont dclars :
vecteur1,vecteur2:record
x:real;
y:real;
end;
page 44 de 84

Enregistrement dcrivant un lve :
eleve:record
nom:string;
prenom:string;
classe:string;
naissance:record
annee:integer;
mois:string;
jour:integer;
end;
end;
Enregistrement dcrivant une voiture :
voiture:record
marque:string;
modele:string;
cylindree:integer;
places:integer;
essence:boolean;
options:string;
end;
6.2.3 Accs aux lments
Aprs avoir dclar un enregistrement, on peut utiliser les diffrents champs de lenregistrement
comme des variables : on peut faire des accs en criture (affectation) ou en lecture.
Laccs aux diffrents champs de lenregistrement est effectu moyennant la notation suivante :
enregistrement.champ
Exemples :
Les exemples suivants utilisent les dclarations ci-dessus.
On inscrit la date du 3 juin 2003 dans lenregistrement date :
date.jour:=3;
date.mois:=juin;
date.annee:=2003;
Le vecteur2 est gal 3 fois le vecteur1 :
vecteur2.x:=3*vecteur1.x;
vecteur2.y:=3*vecteur1.y;
Affichage de la norme du vecteur2 :
writeln(Norme : ,sqrt(sqr(vecteur2.x)+sqr(vecteur2.y));
Llve Toto Tartempion de la classe 2B1 est n le 3 mai 1985.
eleve.nom:=Tartempion;
eleve.prenom:=Toto;
eleve.classe:=2B1;
eleve.naissance.jour:=3;
eleve.naissance.mois:=mai;
eleve.naissance.annee:=1985;
page 45 de 84
Remarque
Comme pour les variables simples, les champs dun enregistrement doivent tre initialiss avant
tout accs en lecture.
6.2.4 Exemple
Ecrivez un programme qui demande lutilisateur dentrer 2 vecteurs du plan et qui calcule et
affiche la somme et le produit scalaire de ces deux vecteurs.
program Exemple;
var
scalaire:integer;
vecteur1,vecteur2,vecteur3:record
x:integer;
y:integer;
end;
begin
writeln(Entrez les composants du premier vecteur :)
readln(vecteur1.x,vecteur1.y);
writeln(Entrez les composants du deuxime vecteur :)
readln(vecteur2.x,vecteur2.y);
{ Calcul de la somme }
vecteur3.x:=vecteur1.x+vecteur2.x;
vecteur3.y:=vecteur1.y+vecteur2.y;
{ Calcul du produit scalaire }
scalaire:=vecteur1.x*vecteur2.x+vecteur1.y*vecteur2.y;
writeln(La somme vaut :(,vecteur3.x,;,vecteur3.y,);
writeln(Le produit scalaire vaut :,scalaire);
end.
6.2.5 Exercices
Exercice 6-12
Donnez la dclaration dun enregistrement qui permet de mmoriser les donnes relatives un
article dun supermarch.
Exercice 6-13
Donnez la dclaration dun enregistrement qui permet de mmoriser les donnes relatives un
livre dune bibliothque.
Exercice 6-14 (**) Tableau des valeurs
crivez un programme qui :
demande lutilisateur les coefficients dun polynme de degr 4 et les mmorise dans un
tableau,
remplit ensuite un tableau de valeurs, reprsent par un tableau dont les lments sont des
enregistrements, de premire composante X et de deuxime composante Y, X variant de -5
5,
affiche le tableau des valeurs.
page 46 de 84




Deuxime partie

Cours de I
e


Delphi

page 47 de 84
7 Delphi
7.1 Introduction
Aprs son lancement, Delphi se prsente sous la forme de 4 fentres.
La premire fentre occupe la partie suprieure de l'cran; elle correspond l'environnement de
programmation proprement dit.
Cette fentre contient:
la barre de titre;
la barre de menu de Delphi ;
une zone barre d'outils (sur la gauche) ;
une zone contenant les divers composants regroups par familles.
La seconde fentre se trouve par dfaut gauche de l'cran: c'est l'inspecteur d'objets. Il permet
de visualiser, pour chaque objet ou composant, les proprits et les vnements auxquels l'objet
peut rpondre.
La troisime fentre constitue la fiche principale de la future application Delphi. Il s'agit, au
dpart, d'une fentre vide dans laquelle on placera les divers objets.
La dernire fentre, cache sous la prcdente constitue lditeur proprement dit, contenant le
code source de l'application.
Pour dmarrer une nouvelle application, il faut choisir l'option New Application du menu File.
Pour sauvegarder une application, il faut choisir l'option Save All du menu File. Une rgle
suivre absolument est de crer un rpertoire par application. Comme Delphi cre plusieurs
fichiers pour une application donne, il est plus facile de les retrouver s'ils ne sont pas
enregistrs avec d'autres fichiers de noms pratiquement identiques.
Lors du premier tout enregistrement de l'application, une fentre permet de choisir
l'emplacement de sauvegarde et mme de le crer.
Pour excuter une application, il faut choisir l'option Run du menu Run. Si les options d'auto-
enregistrement ont t slectionnes et que l'application n'a encore jamais t sauvegarde, la
fentre d'enregistrement s'affiche. L'application est ensuite compile puis excute, si elle ne
contient pas d'erreur.
7.2 Les fichiers utiliss en Delphi
Les fichiers d'un projet:
.DPR fichier projet Delphi Project File
.DFM fichier fiche Delphi Form File
.PAS fichier unit - code source
.EXE fichier excutable (le programme dvelopp)
.DCU fichier unit - code compil Delphi Compiled Unit
.RES fichier ressource (icnes, bitmaps, curseurs, . . .)
.DPL fichier paquet compil Delphi Package Library
page 48 de 84
.DPK fichier paquet source Delphi Package
Les fichiers .DPR,.DFM et .PAS sont les fichiers ncessaires la programmation et doivent tre
copis pour continuer le dveloppement sur une autre machine.
Autres fichiers:
.DOF options du projet Delphi Options File
.DSK paramtres du bureau Delphi Desktop File
.~?? fichiers de sauvegarde

7.3 Lapproche Orient-Objet
Dans la programmation en Delphi, nous allons manipuler des objets. Ces objets sont dfinis par
leurs proprits, leurs mthodes et leurs vnements.
Dans la vie courante, un objet peut tre toute chose vivante ou non (par exemple : une voiture,
une montre, ). En informatique, un objet pourra tre un bouton, une fentre, un menu
7.3.1 Les proprits
Cependant, chaque personne voit lobjet diffremment. Ainsi, chacun aura une perception
diffrente de lobjet voiture, selon limportance quil attribue aux caractristiques de lobjet.
Une proprit est une information dcrivant une caractristique de lobjet.
Ainsi, il est facile dnumrer quelques proprits pour lobjet voiture : vitesse maximale,
cylindre, marque, modle, couleur,
Nous pouvons consulter les proprits et galement les modifier. Par exemple, nous pouvons
dfinir les proprits dune voiture dans un jeu de course, tel que la couleur. Ceci se fait de la
manire suivante :
Voiture1.Couleur := Rouge
Bien entendu, il faut que la constante Rouge soit dfinie.

Les objets (dans Delphi ces objets sont appels composants) que nous allons utiliser sont
prdfinis (boutons, fentres, menus, ). Pour afficher les proprits dun objet, il suffit de
cliquer dessus. Les proprits saffichent alors dans linspecteur dobjet.
Il existe des composants en lecture seule.
7.3.2 Les mthodes
Pour simplifier, on peut se reprsenter une mthode comme un ordre fais ceci , Cet ordre
provoque lexcution dune certaine action par lobjet.
Par exemple, pour lobjet voiture, on peut numrer les mthodes suivantes : acclrer, freiner,
changer de vitesse ,
Donc, linstruction
Voiture1.Acclrer(10) indique la voiture quelle doit acclrer dun facteur 10.
Les proprits ne font que changer une caractristique dun objet alors que les mthodes
effectuent une action. On nutilise pas de signe daffectation lorsquon excute une mthode.
page 49 de 84
7.3.3
Pour chaque objet, il peut survenir certains vnements, qui dclenchent des ractions.
Dans lexemple de la voiture, lorsquon tourne la cl dans le contact ou lorsquon appuie sur
lacclrateur, la voiture dmarre respectivement acclre.
Pour les objets informatiques, il leur arrive des vnements auxquels ils peuvent ragir. Par
exemple, un bouton peut avoir les vnements OnMouse (vnements lis la souris),
OnKey (vnements lis au clavier), OnEnter (rception focus), On Exit (perte focus),
Les vnements existants pour un objet sont visibles dans linspecteur dobjet.

7.4 Passage Pascal Delphi un premier exemple
7.4.1 L'interface
En Delphi, nous utiliserons les composants de l'interface graphique (les fentres de Windows)
pour entrer les donnes et afficher les rsultats. Les algorithmes PASCAL que nous avons
utiliss jusqu maintenant pour obtenir les rsultats pourront rester inchangs.
D'abord, nous allons crer l'interface du programme. Nous allons adapter les noms internes
(proprit Name) de chaque composant que nous utilisons.
En plus, nous allons modifier les inscriptions sur les diffrents composants (proprits Caption
ou Text).















7.4.2 Les conversions de types
Les donnes inscrites dans les botes ddition sont de type texte (string). Nous devons donc les
transformer afin de pouvoir effectuer des calculs.
Voici quelques fonctions permettant deffectuer certaines conversions :
Fiche (TForm)
Name: frmMain
Etiquette (TLabel)
Name: lblMoy
Bouton (TButton)

Name: btnCalcul
Bote
d'dition
(TEdit)
Bote
d'dition
(TEdit)
page 50 de 84

StrToInt(string) : convertit une chane de caractres en un nombre entier (type integer)
StrToFloat(string) : convertit une chane de caractres en un nombre rel (type real)
De mme, pour pouvoir afficher le rsultat, nous devons le transformer en texte. Ceci peut se
faire grce aux fonctions FloatToStr et IntToStr.

7.4.3 Le traitement
Aprs l'entre des donnes dans les botes d'dition, l'utilisateur va cliquer sur le bouton
btnCalcul. A cet instant l'vnement 'OnClick' du bouton est gnr et la mthode
btnCalculClick est lance. Nous allons donc entrer les instructions effectuer dans la mthode
btnCalculClick:
procedure TfrmMain.btnCalculClick(Sender: TObject);
var A,B,MOY : real;
begin
A := StrToFloat(edtA.Text);
B := StrToFloat(edtB.Text);
MOY := (A+B)/2;
lblMoy.Caption := FloaToStr(MOY);
end;

7.4.4 Exercices
Exercice 7-1
Ecrivez un programme qui affiche le plus grand de trois nombres rels A, B, C.
Exercice 7-2
Ecrivez un programme qui calcule la somme d'une srie de nombres entrs au clavier, en
utilisant deux botes ddition et un bouton pour la remise zro de la somme.
Exercice 7-3
Ralisez le programme qui calcule et affiche la factorielle d'un entier naturel N entr au clavier.
Exercice 7-4
Ralisez le programme PUISSANCE qui calcule et affiche la puissance X
N
(puissance X
exposant N pour un rel X et un entier N positif, ngatif ou zro).
Pour les cas o X
N
ne se laisse pas calculer, affichez un message d'erreur!
Exercice 7-5
a) Ralisez un programme qui permet de simplifier une fraction
b) Utilisez une partie du programme ralis sous a) pour faire un programme qui additionne
deux fractions.
page 51 de 84
7.5 Calcul de la factorielle
Comme premier programme essayons dimplmenter en Delphi le calcul de la factorielle.
Rappelons que pour tout entier naturel x,

=

=
0 si 1
1 si 1
!
x
x x
x


Pour laborer ce calcul nous pouvons utiliser le programme dvelopp dans le cours de 2
e
et
lincorporer dans celui en Delphi.
7.5.1 Prsentation visuelle
Commenons par tablir un formulaire dans lequel nous notons les valeurs et ditons les
rsultats.
Voici un exemple dun tel formulaire.




Ce formulaire est un nouvel objet que nous appellerons Tformulaire, de capture (Caption) :
Factorielle. Il est compos des proprits suivants :

Name type text Caption
lblTitre TLabel Calcul de la factorielle
dun nombre
lblEgal TLabel ! =
edtNombre TEdit valeur de la
factorielle calculer

lblResultat TLabel
btnOk Tbutton Calcul

Il est vident que tous ces champs possdent encore davantage de proprits. Nous navons
numr ici que les plus importantes.
lblTitre
lblEgal
edtNombre
lblResultat
btnOk
page 52 de 84
7.5.2 Code
Une fois ce formulaire tabli, nous pouvons crire le code ncessaire pour calculer la factorielle.
Rappelons que nous y utiliserons le code Pascal tabli en 2
e
.
Delphi soccupera de la dclaration du formulaire et de ses proprits.
La seule partie du code que nous devons crire est celle de la procdure btnOkClick qui va tre
excute, comme son nom le dit, aprs que lutilisateur ait pouss sur le bouton Ok. Nous dirons
que la procdure sexcute aprs lvnement onClick appliqu la proprit btnOk.
Le tout se trouvera dans lunit Unit1.
Voici une possibilit de code pour la procdure en question.

procedure Tformulaire.btnOkClick(Sender: TObject);
var a,i,res:integer;
begin
a:= StrToInt(edtNombre.Text);
i:= 2;
res:= 1;
while i<=a do
begin
res:=res*i;
i:=i+1;
end;
lblResultat.caption:= IntToStr(res);
end;

7.5.3 Explication du programme.
En regardant de prs ce code quelques remarques simposent :
Comme la procdure semploie dans le formulaire Tformulaire, elle sappellera sous son
nom complet : Tformulaire.btnOkClick.
La valeur saisie du nombre est la valeur de la proprit Text du champ edtNombre. Nous
notons donc cette valeur par edtNombre.Text. De plus, comme il sagit dune chane de
caractres, nous devons encore transformer cette chane en une valeur numrique par la
fonction StrToInt, fonction prdfinie dans Delphi.
La valeur de la factorielle calcule sera affecte la proprit Text du champ edtResult
que nous noterons par edtResult.Text. Comme de plus cette valeur doit tre du type
chane de caractres, nous devons transformer res par la fonction IntToStr, autre fonction
prdfinie dans Delphi.

Lunit Unit1 se prsentera finalement ainsi :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
type
Tformul = class(TForm)
lblTitre: TLabel;
page 53 de 84
edtNombre: TEdit;
lblEgal: TLabel;
btnOk: TButton;
lblResultat: TLabel;
procedure btnOkClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
formul: Tformul;
implementation
{$R *.dfm}
procedure Tformul.btnOkClick(Sender: TObject);
var a,i,res:integer;
begin
a:= StrToint(edtNombre.Text);
i:= 2;
res:= 1;
while i<=a do
begin
res:=res*i;
i:=i+1;
end;
lblResultat.Caption:= intToStr(res);
end;
procedure Tformul.FormCreate(Sender: TObject);
begin
end;
end.
7.5.4 Excution du programme
Une fois ce code saisi, nous sauvegardons le tout dans un rpertoire rserv cette application.
Nous cliquons ensuite sur le bouton qui reprsente un petit triangle vert et le programme
sexcutera.
7.5.5 Remarques
Une fois lanc ce programme ne se terminera pas par une manipulation sur le formulaire.
La saisie fautive respectivement dun nombre ngatif ou dcimal ne conduira pas un
message derreur de la part du programme mais nous affichera un rsultat erron. Nous
laissons au lecteur le soin de corriger le programme pour lamliorer de ce point de vue.
7.6 Equation du second degr
crivons maintenant un programme qui demande la saisie les trois coefficients a, b et c dune
quation du second degr et qui calcule, si elles existent, les racines de lquation
0
2
= + + c bx ax .
Ce mme programme a t demand comme exercice dans le cours de 2
e
. Nous en faisons ici un
programme Delphi.
page 54 de 84
7.6.1 Prsentation visuelle
Comme dans lexemple prcdent nous commenons par dessiner un formulaire que nous
appellerons Tformulaire, dont linstance formulaire nous permet de saisir les coefficients et de
lire le(s) rsultat(s). La proprit Caption de lobjet Tformulaire aura comme valeur : quation
du 2
e
degr.



Ce formulaire est compos des champs suivants :

name type text caption
lblA TLabel a =
lblB TLabel b =
lblC TLabel c =
lblTexte TLabel texte sur le rsultat
lblX1 TLabel valeur de la racine
lblX2 TLabel valeur de la racine
edtA TEdit valeur de a
edtB TEdit valeur de b
edtC TEdit valeur de c
btnCalcul TButton Calcul
gbCoeff TGroupBox Coefficients
gbRes TGroupBox Rsultat

Nous remarquons tout-de-suite une nouvelle notion :
les champs du type TGroupBox : Ils servent regrouper diffrents champs dans un
mme groupe quils affichent avec un cadre et un nom donn sous Caption. Dans notre
exemple la TGroupBox gbCoeff regroupe les champs lblA, lblB et lblC, tandis la
TGroupBox gbRes affichera les rsultats et contient ainsi les champs lblTexte, lblX1 et
page 55 de 84
lblX2.
Nous dfinissons ces TGroupBox comme suit :




Nous venons dj de remarquer que le rsultat sera affich dans la TGroupBox gbRes.
Mais les tiquettes (labels) lblTexte, lblX1 et lblX2 sont invisibles pour linstant.
Si nous avons un rsultat afficher, lblTexte contiendra une des phrases suivantes :
Il n'y a pas de solution relle ! ,
Il existe une solution relle ! ou
Il y a deux solutions relles diffrentes ! (ceci en fonction du rsultat du calcul),
tandis que lblX1 et lblX2 contiendront les valeurs des racines ventuelles. Comme
actuellement ces tiquettes ne contiennent pas de texte (caption vide), elles
napparatront pas lcran.
7.6.2 Code
Une fois ce formulaire tabli nous crivons le code suivant :

unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons;
type
Tformulaire = class(TForm)
gbCoeff: TGroupBox;
lblA: TLabel;
lblB: TLabel;
lblC: TLabel;
edtA: TEdit;
edtB: TEdit;
edtC: TEdit;
btnFermer: TBitBtn;
btnCalcul: TButton;
gbRes: TGroupBox;
lblTexte: TLabel;
lblX1: TLabel;
page 56 de 84
lblX2: TLabel;
procedure btnCalculClick(Sender: TObject);
private
{ Private-Declarations}
public
{ Public-Declarations }
end; //Tformulaire
var formulaire: Tformulaire;
implementation
{$R *.DFM}
procedure Tformulaire.btnCalculClick(Sender: TObject);
var a,b,c,disc : real;
begin
a:=StrtoFloat(edta.Text);
b:=StrtoFloat(edtb.Text);
c:=StrtoFloat(edtb.Text);
disc:=b*b-4*a*c;
if disc < 0 then
begin
lblTexte.Caption:='Il n''y a pas de solution relle !';
lblX1.Caption:='';
lblX2.Caption:='';
end;
if disc = 0 then
begin
lblTexte.Caption:='Il existe une solution relle !';
lblX1.Caption:='x = ' + FloattoStr(-b/(2*a));
lblX2.Caption:='';
end;
if disc > 0 then
begin
lblTexte.Caption:='Il y a deux solutions relles diffrentes !';
lblX1.Caption:='x1 = ' + FloattoStr((-b-sqrt(disc))/(2*a));
lblX2.Caption:='x2 = ' + FloattoStr((-b+sqrt(disc))/(2*a));
end;
end;
end.

7.6.3 Explications du programme
Nous lisons dabord les 3 coefficients a, b et c de lquation. Comme nous les avons dfinis
comme variables relles, nous devons utiliser la fonction StrtoFloat pour faire la
transformation entre la chane de caractres que reprsente edt*.Ttext et les variables a, b et c.
Nous calculons ensuite le discriminant. En fonction du signe du discriminant nous envisageons
les 3 cas :
disc<0 : il ny a pas de rsultat rel ;
disc=0 : il y a une racine ;
disc>0 : il y a deux racines relles distinctes.
En fonction des diffrents cas nous calculons les valeurs des racines.
la fin il nous reste encore transformer les valeurs relles, rsultats des calculs, en chanes de
caractres pour les affecter la proprit Caption des diffrentes tiquettes. Nous faisons ceci
avec la fonction FloatToStr.
page 57 de 84

7.6.4 Amlioration du programme
Comme dans lexemple prcdent, ce programme ne termine pas nen plus. Pour permettre
lapplication de terminer, une possibilit serait de :
crer un bouton supplmentaire btnArret avec le capture : Arrt ;
crer une mthde Tformulaire.btnArretClick qui aura comme seule commande
Application.Terminate ;
De cette manire lvnement Click li au bouton btnArret aura comme effet darrter
lapplication.
Exercice : Compltez lexercice ci-dessus en le compltant avec un bouton darrt.

7.7 Vrification du numro de matricule
Dveloppons ici un exercice qui prend en entre le numro de matricule dune personne et qui
vrifie que le chiffre de contrle est correct.
7.7.1 Rappelons la mthode de calcul du numro de contrle.
Si nous notons c n n j j m m a a a a
2 1 2 1 2 1 4 3 2 1
un numro de matricule, nous formons le dernier chiffre
en parcourant les tapes suivantes :
Nous formons la somme :
2 1 2 1 2 1 4 3 2 1
* 2 * 3 * 4 * 5 * 6 * 7 * 2 * 3 * 4 * 5 n n j j m m a a a a sum + + + + + + + + + = ;
soit n le reste de la division de sum par 11 ;
si n=1 il y a une faute ;
si n=0 le chiffre de contrle reste 0 ;
si 1 et 0 n n alors le chiffre de contrle vaut n 11 .

Nous essayons de traduire ceci en Delphi.
7.7.2 Prsentation visuelle
Pour cela il nous faut dabord un formulaire que nous appellerons, comme toujours,
Tformulaire dont une instance nous servira manipuler les entres et sorties.
La valeur de la proprit Caption de lobjet Tformulaire sera : Numro de matricule.
Voici un exemple dun tel formulaire.


page 58 de 84



Il contient les lments suivants :

nom type text caption
lblTitre TLabel Contrle du numro
de matricule
lblSaisie TLabel Indiquez votre
numro de
matricule :
lblResultat TLabel Votre numro de
matricule est :
edtSaisie TEdit numro de matricule
edtResultat TEdit correct/faux
btnVerif TButton Vrification
btnArret TButton Arrt

7.7.3 Code
Une fois ce formulaire tabli, nous devons programmer le code ncessaire.
Voici un exemple dimplmentation.

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
page 59 de 84
type
Tformulaire = class(TForm)
lblTitre: TLabel;
lblSaisie: TLabel;
lblResultat: TLabel;
edtSaisie: TEdit;
edtResultat: TEdit;
btnVerif: TButton;
btnArret: TButton;

procedure btnVerifClick(Sender: TObject);
procedure btnArretClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; //Tformulaire
var
formulaire: Tformulaire;

implementation
{$R *.dfm}
procedure Tformulaire.btnVerifClick(Sender: TObject);
var
a1,a2,a3,a4,m1,m2,j1,j2,n1,n2,nc,c: integer;
sum : integer;
s : string;
begin
s:=edtSaisie.Text;
if length(s) <> 11 then
ShowMessage('Numro de matricule mal saisi')
else
begin
a1:= StrToInt(copy(s,1,1));
a2:= StrToInt(copy(s,2,1));
a3:= StrToInt(copy(s,3,1));
a4:= StrToInt(copy(s,4,1));
m1:= StrToInt(copy(s,5,1));
m2:= StrToInt(copy(s,6,1));
j1:= StrToInt(copy(s,7,1));
j2:= StrToInt(copy(s,8,1));
n1:= StrToInt(copy(s,9,1));
n2:= StrToInt(copy(s,10,1));
nc:= StrToInt(copy(s,11,1));
sum := 5*a1+4*a2+3*a3+2*a4+7*m1+6*m2+5*j1+4*j2+3*n1+2*n2;
sum := sum mod 11;
if sum = 1 then s:='faux'
else
begin
if sum = 0 then c:= 0
else c:= 11-sum;
if nc=c then s:='correct'
else s:='faux';
end;
edtResultat.Text:=s;
end;
end;
procedure Tformulaire.btnArretClick(Sender: TObject);
begin
Application.Terminate;
end;
end.
page 60 de 84

7.7.4 Explication du code
La variable s va contenir le numro de matricule saisi. Cest la valeur saisie.
Pour viter quun utilisateur ne donne quune partie dun numro de matricule, nous faisons un
test sur la longueur du numro et nous affichons une erreur si la longueur ne correspond pas.
Le message derreur est affich par la procdure ShowMessage dont la syntaxe est la suivante :
ShowMessage(msg: string);
o
msg chane de caractres afficher.
Ensuite nous extrayons les diffrentes valeurs du numro de matricule. Comme toutes les
valeurs saisies sont des caractres nous devons les transformer en entiers par la fonction
StrToInt.
La fonction copy sert extraire des parties de chanes de caractres. Sa syntaxe est la suivante :
Copy(s, index, count: Integer): string;
o :
S chane de laquelle est extraite la partie ;
Index indice de dbut de la chane extraire (commence par 1) ;
Count nombre de caractres extraire.

Les tapes suivantes correspondent lalgorithme nonc.
Pour terminer nous ditons le rsultat comme texte du champ edtResultat.
La procdure Tformulaire.btnArretClick sert de nouveau arrter lapplication.

7.8 Une petite machine calculer
Dans ce prochain exercice nous nous proposons de mettre en uvre une petite machine
calculer, qui effectuera les 4 oprations lmentaires.
7.8.1 Prsentation visuelle
Comme toujours il nous faut dfinir dabord un formulaire. Voici une possibilit dune telle
interface entre loprateur et la machine.

page 61 de 84

Nous appellerons, comme toujours Tformulaire lobjet que nous allons dfinir ci-dessous.
Nom type text caption
edtNum TEdit Saisie des nombres et des
oprateurs qui interviennent dans le
calcul

btnButton0 TButton 0
btnButton1 TButton 1
btnButton2 TButton 2
btnButton3 TButton 3
btnButton4 TButton 4
btnButton5 TButton 5
btnButton6 TButton 6
btnButton7 TButton 7
btnButton8 TButton 8
btnButton9 TButton 9
btnButtonclear TButton C
btnButtondiv TButton /
btnButtonequal TButton =
btnButtonminus TButton -
btnButtonmult TButton *
btnButtonplus TButton +
btnButtonarret TButton Stop
page 62 de 84
7.8.2 Code
Une possibilit de code pour cette machine calculer est le suivant :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
Tformulaire = class(TForm)
btnButton0: TButton;
btnButton1: TButton;
btnButton2: TButton;
btnButton3: TButton;
btnButton4: TButton;
btnButton5: TButton;
btnButton6: TButton;
btnButton7: TButton;
btnButton9: TButton;
btnButton8: TButton;
edtNum: TEdit;
btnButtonplus: TButton;
btnButtonclear: TButton;
btnButtonmult: TButton;
btnButtondiv: TButton;
btnButtonminus: TButton;
btnButtonequal: TButton;
btnArret: TButton;
procedure btnButton0Click(Sender: TObject);
procedure btnButton1Click(Sender: TObject);
procedure btnButton2Click(Sender: TObject);
procedure btnButton3Click(Sender: TObject);
procedure btnButton4Click(Sender: TObject);
procedure btnButton5Click(Sender: TObject);
procedure btnButton6Click(Sender: TObject);
procedure btnButton7Click(Sender: TObject);
procedure btnButton8Click(Sender: TObject);
procedure btnButton9Click(Sender: TObject);
procedure btnButtonplusClick(Sender: TObject);
procedure btnButtonminusClick(Sender: TObject);
procedure btnButtonmultClick(Sender: TObject);
procedure btnButtondivClick(Sender: TObject);
procedure btnButtonclearClick(Sender: TObject);
procedure btnButtonequalClick(Sender: TObject);
procedure btnArretClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
flag, n1, n2, op : integer;
n3 : real;
st : string;
end;//Tformulaire
var
formulaire : Tformulaire;
implementation
{$R *.dfm}
procedure Tformulaire.btnButton0Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'0'
else
begin
page 63 de 84
edtNum.Text:='0';
flag:=0
end;
end;//btnButton0Click
procedure Tformulaire.btnButton1Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'1'
else
begin
edtNum.Text:='1';
flag:=0
end;
end;//btnButton1Click
procedure Tformulaire.btnButton2Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'2'
else
begin
edtNum.Text:='2';
flag:=0
end;
end;//btnButton2Click
procedure Tformulaire.btnButton3Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'3'
else
begin
edtNum.Text:='3';
flag:=0
end;
end;//btnButton3Click
procedure Tformulaire.btnButton4Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'4'
else
begin
edtNum.Text:='4';
flag:=0
end;
end;//btnButton4Click
procedure Tformulaire.btnButton5Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'5'
else
begin
edtNum.Text:='5';
flag:=0
end;
end;//btnButton5Click
procedure Tformulaire.btnButton6Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'6'
else
begin
edtNum.Text:='6';
flag:=0
end;
end;//btnButton6Click
procedure Tformulaire.btnButton7Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'7'
else
begin
page 64 de 84
edtNum.Text:='7';
flag:=0
end;
end;//btnButton7Click
procedure Tformulaire.btnButton8Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'8'
else
begin
edtNum.Text:='8';
flag:=0
end;
end;//btnButton8Click
procedure Tformulaire.btnButton9Click(Sender: TObject);
begin
if flag=0 then edtNum.Text:=edtNum.Text+'9'
else
begin
edtNum.Text:='9';
flag:=0
end;
end;//btnButton9Click
procedure Tformulaire.btnButtonplusClick(Sender: TObject);
begin
Val(edtNum.Text, n1, error);
flag := 1;
op := 1;
end;//btnButtonplus
procedure Tformulaire.btnButtonminusClick(Sender: TObject);
begin
Val(edtNum.Text, n1, error);
flag := 1;
op := 2;
end;//btnButtonminus
procedure Tformulaire.btnButtonmultClick(Sender: TObject);
begin
Val(edtNum.Text, n1, error);
flag := 1;
op := 3;
end;//btnButtonmult
procedure Tformulaire.btnButtondivClick(Sender: TObject);
begin
Val(edtNum.Text, n1, error);
flag := 1;
op := 4;
end;//btnButtondiv
procedure Tformulaire.btnButtonclearClick(Sender: TObject);
begin
edtNum.Text := '';
n1 := 0;
end;//btnButtonclear
procedure Tformulaire.btnButtonequalClick(Sender: TObject);
begin
Val(edtNum.Text, n2, error);
case op of
1: n3:=n1+n2;
2: n3:=n1-n2;
3: n3:=n1*n2;
4: n3:=n1/n2;
end;//case
Str(n3:7:3, st);
edtNum.Text:=st;
flag := 1;
page 65 de 84
op := 4;
end;//btnButtonequal
procedure Tformulaire.btnArretClick(Sender: TObject);
begin
Application.Terminate
end;//btnArret
end.//Unit1
7.8.3 Explication du code
La valeur flag est initialise 0. Si tel est le cas, tout nombre saisi dans edtNum est concatn
la chane de caractres dj saisie. Si on clique sur un signe dopration, le contenu de edtNum
constituera un des deux oprants. Dans ce cas, flag devient 1, edtNum.Text est copi comme
valeur dans n1 ou n2, edtNum.Text est remis la chane vide, flag redevient 0 et edtNum est
prt contenir le prochain oprant.
Le reste du programme sexplique facilement la lecture.

7.9 Calcul matriciel - utilisation du composant StringGrid
Le prochain programme que nous allons tablir est un programme qui manipule les oprations
sur les matrices 2x2.
Exercice :
Il est laiss au lecteur la possibilit de changer ce programme pour la manipulation des matrices
3 dimensions.
7.9.1 Le composant StringGrid
Dans cet exercice nous utilisons le type prdfini : matrice ou StringGrid qui se trouve dans la
barre des objets sous Additional. Il possde de nouvelles proprits dont nous numrons ici les
plus importantes :

proprit Type explications
ColCount Integer nombre de colonnes
RowCount Integer nombre de lignes
FixedCols Integer nombre de colonnes den-ttes
FixedRows Integer nombre de lignes denttes
DefaultColWidth Integer largeur des colonnes (pixels)
DefaultRowHeight Integer hauteur des colonnes (pixels)
Cells ensemble de cellules

Nous rfrenons une cellule par Cells[colonne,ligne].
Attention : nous devons faire attention que le comptage des lignes et des colonnes commence,
comme si souvent, par 0.
page 66 de 84
7.9.2 Le composant ListBox
Dans cet exemple nous utilisons aussi un nouveau type, la ListBox. Elle sert afficher plusieurs
lignes de caractres et donner la possibilit lutilisateur de choisir une ligne prcise.
Nous trouvons la ListBox dans la barre des composants standards. Trois proprits sont
importantes relever :

Proprit type explications
Items strings tableau des lignes de la liste
ItemIndex entier indice de la ligne slectionne
Sorted boolen lignes tries ou non



7.9.3 Prsentation visuelle
Commenons dabord, comme dans les exercices prcdents, par tablir un formulaire qui nous
sert saisir les donnes et les afficher. Voici un exemple dun tel formulaire.



page 67 de 84

Ce formulaire prsente les composants suivants :

name type text caption
lblTitre TLabel Calculs sur les matrices
lblEg1 TLabel =
lblEg2 TLabel =
lblInv TLabel inv
btnEff TButton effectuez
btnInv TButton inverse
btnArret TButton Stop

name type items
lbOp TListBox + - *

name type colcount/rowcount fixedcols/fixedrows
sgMat1 TStringGrid 2/2 0/0
sgMat2 TStringGrid 2/2 0/0
sgMat3 TStringGrid 2/2 0/0
sgMatInv TStringGrid 2/2 0/0
sgMatRes TStringGrid 2/2 0/0

Le champ lbOp de type ListBox sert numrer les diffrentes oprations et donner
lutilisateur la possibilit de choisir.
Aprs llaboration de ce formulaire nous pouvons crire le code ncessaire. Voici un exemple
possible.
unit Unit1 ;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, Buttons ;
type
Tformulaire = class(TForm)
lblTitre : Tlabel ;
sgMat1 : TstringGrid ;
sgMat2 : TstringGrid ;
page 68 de 84
sgMatRes : TstringGrid ;
sgMat3 : TstringGrid ;
sgMatInv : TstringGrid ;
lblEg1: Tlabel;
lblEg2: Tlabel;
lblInv: Tlabel;
lbOp: TlistBox;
btnEff: Tbutton;
btnInv: Tbutton;
btnArret: Tbutton;
procedure btnEffClick(Sender: Tobject);
procedure btnInvClick(Sender: Tobject);
procedure btnArretClick(Sender: Tobject);
private
{ Private declarations }
public
{ Public declarations }
end;//Tformulaire
var
formulaire: Tformulaire;
implementation
{$R *.dfm}
procedure Tformulaire.btnEffClick(Sender: TObject);
var a,i,j : integer;
begin
if lbOp.ItemIndex=0 then
for i:=0 to 1 do
for j:=0 to 1 do
begin
a:=StrToInt(sgMat1.Cells[i,j])+StrToInt(sgMat2.Cells[i,j]);
sgMatRes.Cells[i,j]:=IntToStr(a);
end;
//j
//i
//fi index=0
if lbOp.ItemIndex=1 then
for i:=0 to 1 do
for j:=0 to 1 do
begin
a:= StrToInt(sgMat1.Cells[i,j])-StrToInt(sgMat2.Cells[i,j]);
sgMatRes.Cells[i,j]:=IntToStr(a);
end;
//j
//i
//fi index=1
if lbOp.ItemIndex=2 then
for i:=0 to 1 do
for j:=0 to 1 do
begin
a:=StrToInt(sgMat1.Cells[0,j])*StrToInt(sgMat2.Cells[i,0])
+StrToInt(sgMat1.Cells[1,j])*StrToInt(sgMat2.Cells[i,1]);
sgMatRes.Cells[i,j]:=IntToStr(a);
end;
//j
//i
//fi index=0
end;//btnCalculClick
procedure Tformulaire.btnInvClick(Sender: TObject);
var a,det:real;
begin
det:=StrToInt(sgMat3.Cells[0,0])*StrToInt(sgMat3.Cells[1,1])
-StrToInt(sgMat3.Cells[1,0])*StrToInt(sgMat3.Cells[0,1]);
a:= det;//1/det*StrToFloat(sgMat3.Cells[1,1]);
page 69 de 84
sgMatInv.Cells[0,0]:=FloatToStr(a);
a:= (-1)*StrToInt(sgMat3.Cells[1,0]);
sgMatInv.Cells[1,0]:=FloatToStr(a);
a:= (-1)*StrToInt(sgMat3.Cells[0,1]);
sgMatInv.Cells[0,1]:=FloatToStr(a);
a:= StrToInt(sgMat3.Cells[0,0]);
sgMatInv.Cells[1,1]:=FloatToStr(a);
end;//btnInvClick
procedure Tformulaire.btnArretClick(Sender: TObject);
begin
Application.Terminate
end;//btnArret
end.//Unit1

7.9.4 Explication du code
Comme les oprations +, - et * exigent deux oprateurs, mais que lopration inverse na besoin
que dun seul, nous avons pu regrouper les trois premiers sous une seule procdure.
La TListBox lbOp nous donne les valeurs suivantes :

ItemIndex opration
0 addition
1 soustraction
2 multiplication

Pour le reste, le contenu des diffrentes parties des procdures correspond aux rgles
mathmatiques qui dfinissent les oprations sur les matrices.
page 70 de 84
8 La rcursivit
8.1 Exemple
La fonction suivante calcule une puissance de base relle non nulle et dexposant naturel :
function puissance(x:real;m:integer):real;
begin
if m=0 then result:=1
else result:=x*puissance(x,m-1)
end;
Cette fonction prsente une grande diffrence par rapport toutes les fonctions que nous avons
dfinies prcdemment. Dans la dfinition mme on trouve dj un appel la fonction
puissance. Il sagit ici dun mcanisme trs puissant, prsent dans tous les langages de
programmation modernes : la rcursivit. Le fonctionnement exact de ce mcanisme ainsi que
les conditions dutilisation seront tudies en dtail dans les paragraphes suivants. Remarquons
cependant quil existe un lien troit entre la rcursivit en informatique et la rcurrence en
mathmatique. La dfinition de la fonction puissance prsente ici est une transcription quasi
directe des formules

=
=
1
0
1
m m
x x x
x
, valables pour x non nul
6
.
8.2 Dfinition : fonction ou procdure rcursive
On dit quune fonction ou une procdure est rcursive (de manire directe) si elle sappelle
elle-mme. Une fonction ou une procdure est rcursive de manire indirecte si elle appelle
une autre fonction ou procdure qui rappelle la premire de faon directe ou indirecte.
La fonction puissance du paragraphe prcdent est bien sr une fonction rcursive directe.
Le mcanisme de la rcursivit est trs puissant, mais il faut une certaine exprience pour
pouvoir lutiliser dans de bonnes conditions. Dans la suite nous allons lucider principalement
les aspects suivants :
Sous quelles conditions et pourquoi une fonction rcursive donne-t-elle le rsultat
attendu ? Comment vrifier quune telle fonction est correcte ?
Comment le systme gre-t-il une fonction rcursive ? Cest--dire comment est-ce que
ce mcanisme fonctionne en pratique ?
Est-ce quune fonction rcursive est meilleure ou moins bonne quune fonction
itrative (normale) ?
Il est clair que ces diffrents aspects ne sont pas indpendants les uns des autres, mais quil faut
une vue densemble pour bien les comprendre.

6
La fonction puissance ne donne un rsultat correct que si x est non nul. De plus, il est ncessaire que m soit
un entier positif !
page 71 de 84
8.3 Etude dtaille dun exemple
Dans ce paragraphe nous revenons la fonction puissance de la page prcdente et nous
allons commencer par tudier quelques exemples dexcution.
puissance(7,0) : donne bien sr comme rsultat 1 vu que la condition m=0 est vrifie.
puissance(7,1) : la condition m=0 nest pas vrifie et la fonction calcule donc dabord
x*puissance(x,m-1) cest--dire 7*puissance(7,0) ce qui donne dans une
deuxime tape 7*1=7.
puissance(7,2) : ici la condition m=0 nest pas non plus vrifie et la fonction calcule
donc aussi dabord x*puissance(x,m-1) cest--dire 7*puissance(7,1) .
Suivent ensuite les deux tapes prcdentes. A la fin de la troisime tape le rsultat obtenu est
7*puissance(7,1)=7*[7*puissance(7,0)]=7*7*1=49.
Il est important de remarquer ici que le systme refait chaque fois toutes les tapes et ne se
souvient pas des appels de fonctions prcdents. Lexcution de puissance(7,12)
ncessite 13 passages dans la fonction : dabord 12 appels rcursifs et ensuite un dernier passage
o m=0.
Lexemple puissance(7,-2) est particulirement intressant. La condition m=0 nest pas
vrifie et la fonction calcule donc x*puissance(x,m-1) cest--dire
7*puissance(7,-3). Ensuite elle va valuer 7*puissance(7,-4),
7*puissance(7,-5), 7*puissance(7,-6), etc. Il est clair que cet appel ne vas
certainement pas donner le rsultat 1/49. Mais la situation est plus grave, lexcution de la
fonction ne va pas donner de faux rsultat, mais cette excution ne va pas se terminer
7
vu que la
condition m=0 ne sera plus jamais vrifie.
Pour quune fonction ou une procdure rcursive sarrte, il est ncessaire que le code vrifie les
conditions suivantes :
Pour une ou plusieurs valeurs des donnes, appeles cas de base , la fonction calcule
directement (sans appel rcursif) le rsultat.
Dans le code de la fonction il doit tre assur que chaque suite dappels rcursifs va
toujours finir par atteindre un cas de base.
Il est clair que le fait que la fonction sarrte, signifie seulement quelle va fournir un rsultat,
mais non pas que ce rsultat est correct. Larrt de la fonction est une condition pralable !
Dans notre exemple, il est donc ncessaire de prciser que la fonction puissance ne convient
pas pour les exposants ngatifs
8
.
Dans une dmonstration par rcurrence en mathmatiques la situation est semblable : Pour
montrer quune proprit est vraie pour tout entier naturel, on montre dabord quelle est vraie
pour le cas de base n=0 et ensuite on montre que si la formule est vraie pour le naturel n, alors
elle reste vraie pour n+1. La vracit de la proprit pour n=4 est alors ramene successivement
n=3, n=2, n=1 jusquau cas de base n=0, que lon sait vrifi.

7
Dans cette situation le systme risque dentrer dans un tat indfini provoqu par un dbordement de mmoire.
Dans le pire cas il sera ncessaire de redmarrer lordinateur (RESET) avec toutes les consquences que cela peut
impliquer. Dans un cas plus favorable, Delphi dtecte le problme et avorte lexcution de la fonction.
8
Elle ne convient pas non plus pour les exposants non entiers, mais ceux-ci sont de toute faon exclus vu que la
variable exposant m est de type integer.
page 72 de 84
8.4 Fonctionnement interne
Dans ce paragraphe on va chercher une rponse la question comment le systme gre
lexcution dune procdure rcursive. La bonne comprhension de ce mcanisme est
importante pour pouvoir rdiger des programmes efficaces.
Revenons lexemple de la fonction factorielle qui calcule la factorielle dun nombre
naturel donn. Cet exemple, dj implment de faon itrative au chapitre prcdent, se prte
particulirement bien tre programm de faon rcursive vu que la dfinition mathmatique de
la fonction se base sur des formules de rcurrence.
( )

=
=
0
! 1 !
1 ! 0
N n si n n n
ou bien
( ) ( )

=
=
0
1 2 3 2 1 !
1 ! 0
N n si n n n n


function factorielle(n:integer):integer;
begin
if n=0 then result:=1 else result:=n*factorielle(n-1)
end;

On peut lintgrer dans le programme Delphi du chapitre prcdent par :
procedure Tformulaire.btnOkClick(Sender: TObject);
function factorielle(n:integer):integer;
begin
if n=0 then result:=1 else result:=n*factorielle(n-1)
end;
var a,res : integer;
begin
a:= StrToInt(edtNombre.Text);
res:=factorielle(a);
edtResultat.Text:= IntToStr(res);
end;
Lors de lexcution de factorielle(1) le systme excute la fonction jusqu lappel
rcursif factorielle(n-1) A ce stade le systme mmorise ltat actuel de toutes les
variables locales de la fonction. Lors de lexcution de factorielle(n-1) le systme
recommence excuter la fonction factorielle avec le paramtre n-1=0. Lors de ce deuxime
passage dans la fonction, les variables locales sont rinitialises, leurs anciennes valeurs ne sont
pas accessibles ce moment mais elles sont sauvegardes pour une rutilisation ultrieure.
Maintenant on a donc n=0 et le systme termine ce passage dans la fonction avec result:=1.
Ensuite le systme revient dans le premier passage de la fonction lendroit
factorielle(n-1). Les variables locales rcuprent leur ancienne valeur et lexpression
n*factorielle(n-1) est value avec n=1 et factorielle(n-1)=1. La variable
result prend la valeur 1 et lexcution quitte dfinitivement la fonction.
Pour des appels de fonction avec des arguments plus grands, par exemple factorielle(15)
le systme doit donc conserver autant de copies de toutes les variables locales quil y a dappels
rcursifs avant datteindre le cas de base. Cela peut ncessiter une quantit apprciable de
mmoire et de temps dexcution pour la gestion qui en dcoule.

page 73 de 84
8.5 Exactitude dun algorithme rcursif
Il est souvent facile de montrer quune fonction rcursive donne le bon rsultat.
Normalement le raisonnement par rcurrence simpose. Pour la fonction factorielle, par
exemple :
Base : n=0, le rsultat est effectivement 1.
Hypothse de rcurrence : supposons que la fonction factorielle donne le bon rsultat
jusquau rang n-1 pour n>0, cest--dire que factorielle(n-1)=(n-1)!.
Pont : montrons que la fonction donne encore le bon rsultat au rang n, donc que
factorielle(n)=n!. En effet, la fonction donne le rsultat n*factorielle(n-1)
qui est gal n*(n-1)! par lhypothse de rcurrence et qui est encore gal n! par la
dfinition mathmatique de la factorielle.
Cette dmonstration ne prend pas en compte des problmes de dpassement de mmoire,
inhrents au systme Delphi, si n est trop grand .
8.6 Comparaison : fonction rcursive fonction itrative
9

Lexemple suivant est particulirement impressionnant.
La clbre suite de Fibonacci qui est dfinie par
{ }

+ =
= =

1 ; 0 ,
1 1
2 1
1 0
N n u u u
u et u
n n n
, simplmente
directement par la fonction rcursive suivante :
function fibo(n:integer):longint;
begin
if n<=1 then result:=1
else result:=fibo(n-1)+fibo(n-2)
end;
Le type du rsultat est longint, une variante de integer qui permet de reprsenter des
nombres entiers plus grands. La condition n<=1 prend en charge les deux cas de base n=0 et
n=1.

La fonction suivante, dont lalgorithme est base sur une simple boucle nest pas vraiment
difficile comprendre non plus. Si n est diffrent de 0 et de 1, alors tous les termes de la suite
jusquau n-ime sont calculs de proche en proche (comme on le ferait si on navait pas
dordinateur disposition).
function fibo_it(n:integer):longint;
var t0,t1:longint;
begin
if n<=1 then result:=1
else
begin
t0:=1;t1:=1;
while n>1 do
begin result:=t0+t1; t0:=t1; t1:=result; n:=n-1 end
end
end;

9
Iteratif: algortihme bas sur une boucle.
page 74 de 84
Pour se faire une ide de la situation, il est conseill de tester les 2 fonctions. En prenant
successivement les arguments 5, 10, 20, 30, 40, 50, on va finir par constater la mme chose
indpendamment de lordinateur utilis. Mme sur un ordinateur rapide la fonction rcursive va
finir par devenir terriblement lente alors que la fonction itrative va rester rapide (rsultat
immdiat) mme sur un ordinateur trs faible ! Pourquoi ?
Que fait la fonction itrative ? Si n>1, cette fonction effectue exactement n-1 additions sur des
nombres du type longint, et un nombre approximativement proportionnel n daffectations,
de soustractions et de comparaisons. Le temps dexcution de ces oprations est ngligeable par
rapport la croissance fulgurante des rsultats : cest--dire la fonction sera limit par la
capacit de reprsentation du type longint avant quon remarque un quelconque
ralentissement dans lexcution !
Que fait la fonction rcursive ? Etudions les excutions de la fonction pour les arguments 2, 3, 4,
et 5.
Pour fibo(2) [rsultat : 2], la condition nest pas vrifie et la fonction calcule donc
lexpression fibo(1)+fibo(0). Les deux appels rcursifs donnent directement le rsultat
1 et lexcution se termine donc assez rapidement aprs seulement 3 passages (chaque fois 1
appel avec les arguments 0, 1 et 2) dans la fonction.
Pour fibo(3) [rsultat : 3], la fonction calcule dabord fibo(2)+fibo(1). Le premier
appel ncessite trois passages (voir alina prcdent) dans la fonction et le deuxime appel
donne directement 1. Cela fait donc un total de 5 appels.
Pour fibo(4) [rsultat : 5], la fonction calcule fibo(3)+fibo(2). Le nombre dappels
se calcule par 5 (pour fibo(3)) + 3 (pour fibo(2)) + 1 (pour fibo(4)) = 9.
Sans entrer dans tous les dtails : Pour fibo(10) [rsultat : 89], il faut 177 appels, pour
fibo(20) [rsultat : 10946], il faut 21891 appels et pour fibo(30) [rsultat : 1346269], il
faut 2692537 appels.
Il est clair que le nombre dappels de fonctions doit tre suprieur ou gal au rsultat. En effet,
les deux seuls cas de bases donnent le rsultat 1 et lappel rcursif consiste ajouter deux
rsultats intermdiaires. Le rsultat final est donc atteint en ajoutant tant de fois le nombre 1. A
ct du nombre impressionnant de calculs que la fonctions effectue, il ne faut pas oublier la
quantit despace mmoire ncessaire pour sauvegarder toutes les valeurs intermdiaires de la
variable n.
8.7 Rcursif ou itratif ?
Contrairement ce que lexemple prcdent pourrait suggrer, un algorithme rcursif nest pas
automatiquement moins bon quun algorithme itratif. Si on tient compte de lvaluation
interne dune fonction rcursive, on peut parfois trouver une variante efficace de la fonction
rcursive.
Voici par exemple une formulation rcursive efficace de la fonction fibo. Lastuce consiste
utiliser une fonction auxiliaire rcursive avec deux arguments supplmentaires, ncessaires
pour passer les deux termes prcdents lappel suivant. On remarquera que dans le code de
cette fonction il ny a quun seul appel rcursif, de faon ce que le nombre dappels pour
calculer le n-ime terme de la suite de Fibonacci ne dpasse pas n.
page 75 de 84
function fibo(n:integer):longint;
function fib_aux(n:integer;i,j:longint):longint;
begin
if n<=1 then result:=i
else result:=fib_aux(n-1,i+j,i)
end;
begin result:=fib_aux(n,1,1) end;
Un certain nombre de problmes admettent une solution rcursive trs lgante (algorithme
simple rdiger et comprendre, mais pas ncessairement efficace). Nous verrons des exemples
de ce genre dans le chapitre sur les recherches et les tris
10
.
Pour certains de ces problmes, une formulation laide de boucles est trs complique. Mais
une telle formulation existe toujours. Dans le pire des cas, il est ncessaire de simuler
lalgorithme rcursif en stockant toutes les valeurs intermdiaires des variables dans un tableau.
Cest de cette faon-l que le programme Delphi lui-mme value les fonctions rcursives ; en
effet le langage machine, seul langage compris par le processeur, est un langage relativement
faible qui ne connat pas le mcanisme de la rcursivit.
8.8 Exercices
Exercice 8-1 Ecrivez un programme qui calcule la fonction dAckermann deux variables
naturelles dfinie par les galits :
( )
( ) ( )
( ) ( ) ( )

=
=
+ =
1 , 1 , , 1 ,
1 1 , 1 0 ,
1 , 0
m k si m k Ack k Ack m k Ack
k si k Ack k Ack
m m Ack

a) Essayez cette fonction pour quelques arguments. Par exemple ack(3,5)=253,
ack(4,0)=13, ack(4,1)=65533,
b) Dmontrez (mathmatiquement) que la fonction dAckermann est bien dfini, cest--
dire que les 3 formules ci-dessus permettent de trouver un rsultat et un seul pour tout
couple de naturels (k,m).
Exercice 8-2 Compltez la fonction puissance pour quelle calcule aussi correctement des
puissances exposant entier ngatif.
Exercice 8-3 Ecrivez une version rcursive de la fonction puissance rapide.
Aide : utilisez les formules ( )

=
=
=
+
a a a
a a
a
n n
n
n
2 1 2
2 2
0
1

Expliquez pour quelles valeurs de a et de n, lexcution va sarrter et donner un rsultat correct.
Exercice 8-4 Ecrivez une version rcursive de la fonction pgcd.
Exercice 8-5 Ecrivez un programme rcursif qui transforme un nombre binaire en notation
dcimale.
Exercice 8-6 Ecrivez un programme rcursif qui transforme un nombre dcimal en notation
binaire.

10
Voir par exemple recherche dichotomique et quicksort .
page 76 de 84
9 Comptage et frquence
9.1 Algorithme de comptage
On veut raliser une fonction qui compte le nombre doccurrences dune chane de caractres
dans une liste donne.
Pour raliser cet algorithme on parcourt la liste lment aprs lment et on le compare avec la
chane trouve. Si les deux chanes sont identiques, on augmente un compteur.
function compter(liste:TListbox;chaine:string):integer;
var
i,r:integer;
begin
r:=0;
for i:=0 to liste.Items.Count-1 do
if liste.Items[I] = chaine then r:=r+1;
result:=r;
end;
Exercice 9-1 Ralisez une fonction qui permet de compter le nombre doccurrences dune
lettre dans une chane de caractres donne.
9.2 Frquence dune lettre dans une liste
Soit une liste dont les lments sont des lettres. On veut savoir combien de fois chaque lettre est
reprsente dans la liste. Ce type dalgorithme est un lment trs important des algorithmes de
compression, comme par exemple celui de Huffman.
La solution propose utilise de manire un peu inhabituelle les tableaux, mais de ce fait-l
devient trs lgante. On utilise comme indice du tableau des lettres.
Le rsultat de lanalyse de la liste se trouve dans une deuxime liste passe comme paramtre et
a le format suivant : lettre : nb. doccurrences.
procedure frequence(liste:TListbox; var resultat:TListbox);
var
i:integer;
c:char;
tableau:array['A'..'Z'] of integer;
element:string;
begin
for c:='A' to 'Z' do tableau[c]:=0;
for i:=0 to liste.Items.Count-1 do
begin
element:=liste.Items[i];
tableau[element[1]]:=tableau[element[1]]+1;
end;
resultat.Items.Clear;
for c:='A' to 'Z' do
resultat.Items.Append(c+' : '+inttostr(tableau[c]));
end;
Exercice 9-2 Ralisez un sous-programme qui permet de compter le nombre doccurrences des
diffrentes lettres dans une chane de caractres donne. Le rsultat du sous-programme est un
tableau.
page 77 de 84
10 Recherche et tri
10.1 Introduction
Les algorithmes de recherche et de tri ont une trs grande importance en informatique. Cest
surtout dans le contexte des bases de donnes que ces algorithmes sont utiliss. Nous allons
traiter en premier lieu les algorithmes de tri car pour fonctionner certains algorithmes de
recherche prsument des donnes tries.
Bien que lillustration des diffrents algorithmes se base sur un petit nombre de donnes, il ne
faut pas oublier que ces algorithmes sont en gnral appliqus sur un nombre trs grand de
donnes ( plus que 10000, comme par exemple dans un annuaire tlphonique ).
10.2 Sous-programmes utiles
Nous allons dfinir deux sous-programmes qui vont nous permettre de faciliter la
programmation et le test des algorithmes de tri et de recherche.
10.2.1 Echange du contenu de deux variables entires
procedure echange (var liste:TListbox; posa,posb:integer);
var
temp: string;
begin
temp:=liste.Items[posa];
liste.Items[posa]:=liste.Items[posb];
liste.Items[posb]:=temp;
end;
Cette procdure change le contenu de deux lments dune liste.
10.2.2 Remplissage dune liste
procedure remplissage(var liste: TListbox; n: integer);
const
a=ord('A');
var
i,j:integer;
s : string ;
begin
liste.Clear;
for i:= 1 to n do
begin
s:='';
for j:=0 to random(5)+1 do
s:=s+chr(random(26)+a);
liste.Items.Append(s);
end;
end;
Cette procdure remplit une liste avec n mots (comportant de 2 6 lettres) pris au hasard.
page 78 de 84
10.3 Les algorithmes de tri
Le but dun algorithme de tri est d'arranger des donnes selon un critre impos. Ce critre
reprsente une relation entre les donnes comme par exemple le tri dune liste de mots selon
lordre lexicographique ou le tri dune liste de nombre en ordre croissant.
10.3.1 Tri par slection
10.3.1.1 Ide
On cherche dans la liste le plus petit lment et on lchange avec le premier lment de la liste.
Ensuite on recommence lalgorithme en ne prenant plus en considration les lments dj tris
et ceci jusqu ce quon arrive la fin de la liste.
10.3.1.2 Solution rcursive
procedure tri_selection_r(var liste:TListbox; debut:integer);
var
j,min:integer;
begin
min:=debut;
for j:=debut+1 to liste.Items.Count-1 do
if liste.Items[j]<liste.Items[min] then min:=j;
echange(liste,debut,min);
if debut < liste.Items.Count-2 then
tri_selection_r(liste,debut+1);
end;
10.3.1.3 Solution itrative
procedure tri_selection_i(var liste:TListbox);
var
i,j,min:integer;
begin
for i:=0 to liste.Items.Count-2 do
begin
min:=i;
for j:=i+1 to liste.Items.Count-1 do
if liste.Items[j]<liste.Items[min] then min:=j;
echange(liste,i,min);
end;
end;
10.3.1.4 Exercice
Excutez pas pas les deux algorithmes en utilisant la liste suivante :
E ;X ;E ;M ;P ;L ;E.
page 79 de 84
10.3.2 Tri par insertion
10.3.2.1 Ide
On considre un lment aprs lautre dans la liste et on cherche sa position dans la liste dj
trie. Ensuite on linsre la juste position. De ce fait les lments suivants de la liste doivent
tre dplacs.
10.3.2.2 Solution rcursive
procedure tri_insertion_r(var liste: TListbox;gauche,droite:integer);
var j:integer;
candidat:string;
begin
if gauche<droite then
begin
tri_insertion_r(liste,gauche,droite-1);
candidat:=liste.Items[droite];
j:=droite;
while (j>0) and (liste.Items[j-1] > candidat) do
begin
liste.Items[j]:=liste.Items[j-1];
j:=j-1;
end;
liste.Items[j]:=candidat;
end;
end;

10.3.2.3 Solution itrative
procedure tri_insertion_i(var liste:TListbox);
var i,j:integer;
candidat:string;
begin
for i:= 1 to liste.Items.Count-1 do
begin
candidat:=liste.Items[i];
j:=i;
while (j>0) and (liste.Items[j-1] > candidat) do
begin
liste.Items[j]:=liste.Items[j-1];
j:=j-1;
end;
liste.Items[j]:=candidat;
end;
end;
10.3.2.4 Exercice
Excutez pas pas les deux algorithmes en utilisant la liste suivante :
C;A;R;T;O;O;N.

page 80 de 84
10.3.3 Tri rapide
10.3.3.1 Introduction
Le tri rapide (ang. : Quicksort) est lalgorithme de tri le plus utilis. Il est rput pour sa vitesse
de tri qui pour des listes de grande taille est souvent bien suprieure celle dautres algorithmes
de tri. Nous allons dvelopper le tri rapide en plusieurs tapes.
10.3.3.2 Ide
Lalgorithme de tri va diviser la liste en deux parties. Ces parties qui ne sont pas forcment de
taille gale, sont alors tries sparment par le mme algorithme. Limportant dans cet
algorithme est la stratgie comment la liste est divise en deux sous-listes.
10.3.3.3 Dveloppement dune solution rcursive
Lide de base nous conduit un algorithme rcursif trs simple :
procedure tri_rapide_r(var liste:TListbox;g,d:integer);
var i:integer;
begin
if d>g then
begin
i:=division(liste,g,d);
tri_rapide_r(liste,g,i-1);
tri_rapide_r(liste,i+1,d);
end;
end;
Les paramtres g et d limitent la partie de la liste qui doit tre trie. Le premier appel de la
procdure de tri a comme paramtres lindice du premier et lindice du dernier lment de la
liste.
10.3.3.4 Division de la liste
Pour que cette procdure rcursive fonctionne correctement il faut que la fonction division
remplisse trois conditions :
1. Llment avec lindice i (indice qui est retourn comme rsultat) se trouve lendroit
dfinitif.
2. Tous les lments gauche de llment avec lindice i sont plus petits ou gaux celui-ci.
3. Tous les lments droite de llment avec lindice i sont plus grands ou gaux celui-ci.
Ces trois conditions nous amnent une situation trs agrable :
La premire nous dit que llment avec lindice i na plus besoin dtre dplac.
La deuxime implique quaucun lment de la sous-liste gauche ne sera dplac au-del de
llment avec lindice i.
La troisime implique quaucun lment de la sous-liste droite ne sera dplac avant llment
avec lindice i.
En plus on peut affirmer que les deux sous-listes obtenues de cette manire-ci peuvent tre tries
par la suite dune manire indpendante.
page 81 de 84
La fonction division se prsente de la manire suivante :
function division(var liste: TListbox;g,d:integer):integer;
var i,j : integer;
candidat :string;
begin
candidat:=liste.Items[d];
j:=d-1; i:=g;
while i<=j do
begin
if liste.Items[i]< candidat then i:=i+1
else if liste.Items[j]> candidat then j:=j-1
else begin echange(liste,i,j); i:=i+1 ; j:=j-1; end;
end;
echange(liste,i,d);
result:=i;
end;
Pour commencer, on choisit llment qui se trouve la fin de liste comme candidat. On va
dterminer la position dfinitive du candidat dans la liste et sarranger que tous les lments de
la liste qui se trouvent avant sont plus petits et tous ceux qui se trouvent aprs sont plus grands
que le candidat.
La boucle parcourt la liste en commenant par le dbut (if) jusquau premier lment suprieur
au candidat, ensuite (else if) elle parcourt la liste en commenant par la fin jusquau premier
lment infrieur au candidat. Ces 2 lments sont alors (else) changs et on recommence.
A la fin de la boucle le candidat est mis sa place dfinitive et lindice de cette place est rendu
comme rsultat de la fonction. On vrifie facilement quau cas o le candidat se trouvait sa
bonne place (lorsquil est le plus grand lment de la liste), alors i=d et le dernier change na
aucun effet.
10.3.4 Tri par fusion
10.3.4.1 Ide
Si lon dispose de deux listes tries, on peut assez facilement les fusionner
11
(mettre ensemble)
afin dobtenir une seule liste trie. Un tri par fusion utilisant cette approche peut tre
implmente de faon rcursive et de faon itrative. Les deux versions utilisent la mme
procdure fusion.
10.3.4.2 Fusion de deux liste tries
Lalgorithme de fusion utilise un tableau auxiliaire de chanes de caractres, de mme taille que
la liste trier. Ce tableau peut tre dclar globalement ; cela vite de redclarer le tableau
chaque appel de la procdure.
Les deux sous-listes fusionner se trouvent de faon conscutive dans la liste. Les paramtres g
et m sont les indices de dbut et de fin de la premire sous-liste, alors que la seconde sous-liste
commence lindice m+1 et se termine en d. Les deux sous-listes sont dabord copies dans le
tableau auxiliaire : la 1
re
de faon croissante et la 2
e
de faon dcroissante de sorte que les
lments les plus grands se trouvent au milieu. Ensuite la procdure commence comparer les

11
La fusion est en quelque sorte une gnralisation de linsertion o lon fusionne aussi deux listes tries, dont
lune nest compose que dun seul lment.
page 82 de 84
plus petits lments des deux-sous-listes (le plus gauche et le plus droite) et replace le plus
petit des deux dans la liste principale et ainsi de suite.
procedure fusion(var liste: TListbox; g,m,d: integer);
var i,j,k : integer;
tt : array[1..1000] of string; {mieux: dclarer tt globalement}
begin
for i:=g to m do tt[i]:=liste.Items[i];
for j:=m+1 to d do tt[d+m+1-j]:=liste.Items[j];
i:=g; j:=d;
for k:=g to d do
if tt[i]<tt[j]
then begin liste.Items[k]:=tt[i]; i:=i+1 end
else begin liste.Items[k]:=tt[j]; j:=j-1 end;
end;
10.3.4.3 Solution rcursive
Il suffit de diviser la liste en deux, de trier sparment les deux parties et de fusionner les deux
parties tries.

procedure tri_fusion_re(var liste: TListbox;g,d:integer);
var m:integer;
begin
if g<d then
begin
m:=(g+d) div 2;
tri_fusion_re(liste,g,m);
tri_fusion_re(liste,m+1,d);
fusion(liste,g,m,d);
end;
end;
10.3.4.4 Solution itrative
La version itrative commence par considrer des sous-listes de longueur 1 qui sont ensuite
fusionnes 2 2. Ensuite la liste nest compose que de sous-listes de longueur 2 dj tries.
Celles-ci sont encore fusionnes 2 2 et ainsi de suite. Dtape en tape la longueur des sous-
listes tries double (variable step). Toute la liste est trie lorsquil nexiste plus quune seule
grande sous-liste.
procedure tri_fusion_it(var liste: TListbox);
var i,m,step:integer;
begin
m:=liste.Items.Count;
step:=1;
i:=0;
while step<m do
begin
while (i+2*step-1)<m do
begin fusion(liste,i,i+step-1,i+2*step-1) ; i:=i+2*step; end;
if (i+step)<=m then fusion(liste,i,i+step-1,m-1);
{s'il reste une liste et une partie d'une 2e liste}
step:=step*2;
i:=0 ;
end;
end;
page 83 de 84
10.4 Les algorithmes de recherche
Les algorithmes de recherche ont pour but de dterminer lindice dun lment dune liste qui
rpond un certain critre. Si lon ne trouve pas llment, on retourne par convention 1.
Llment recherch encore appel cl, peut figurer plusieurs fois dans la liste. On suppose que
la liste nest pas vide.

10.4.1 Recherche squentielle
10.4.1.1 Ide
Il sagit de lalgorithme de recherche le plus simple qui puisse exister : on commence
examiner la liste ds le dbut jusqu ce quon ait trouv la cl. Lalgorithme donne lindice de
la premire occurrence de la cl. La liste ne doit pas tre trie.
10.4.1.2 Solution itrative
function recherche_seq_i(liste:TListbox;cle:string):integer;
var
index:integer;
begin
index:=0;
while (index <= liste.Items.Count-1) and (liste.Items[index]<>cle) do
index:=index+1;
if index <= liste.Items.Count-1 then result:=index
else result:=-1;
end;


10.4.2 Recherche dichotomique
10.4.2.1 Ide
La recherche dichotomique est trs rapide et utilise une mthode bien connue : Si par exemple,
vous devez chercher une localit dans lannuaire tlphonique, vous ne commencez pas la
premire page pour ensuite consulter une page aprs lautre, mais vous ouvrez lannuaire au
milieu pour ensuite regarder si la localit se situe dans la premire partie ou dans la deuxime
partie de lannuaire. Ensuite vous recommencez lopration, c d vous divisez de nouveau la
partie contenant la localit recherche en deux et ainsi de suite jusqu ce que vous ayez trouv
la localit. Lalgorithme de la recherche dichotomique utilise le mme procd :
On divise la liste en deux parties. On regarde si la cl correspond llment au milieu de la
liste. Si cest le cas on a termin, sinon on dtermine la partie qui contient la cl et on
recommence la recherche dans la partie contenant la cl. La liste ne doit pas forcment contenir
la cl, mais elle doit tre trie.
page 84 de 84

10.4.2.2 Solution rcursive
function dicho_r(liste:TListbox;cle:string;g,d:integer):integer;
var
milieu:integer;
begin
if g>d then result:=-1
else
begin
milieu:=(g+d) div 2;
if liste.Items[milieu] = cle then result:=milieu
else if cle<liste.Items[milieu] then
result:= dicho_r(liste,cle,g,milieu-1)
else
result:= dicho_r(liste,cle,milieu+1,d);
end;
end;


10.4.2.3 Solution itrative
function dicho_i(liste:TListbox;cle:string):integer;
var
milieu,g,d:integer;
begin
g:=0;
d:=liste.Items.Count-1;
while (cle<>liste.Items[milieu]) and (g<=d) do
begin
milieu:=(g+d) div 2;
if cle<liste.Items[milieu] then d:=milieu-1
else g:=milieu+1;
end;
if cle=liste.Items[milieu] then result:=milieu
else result:=-1;
end;

Vous aimerez peut-être aussi