Cours Pascal
Cours Pascal
Cours Pascal
Cours
Edouard Thiel
6
6 6 6 6 7 7 7 8 8 8 9 10 11 11 11 12 12 13 13 14 14 15 16 17
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
II
Procdures e
1 Procdure sans param`tre e e 1.1 Principe . . . . . . . . . . . . 1.2 Appels . . . . . . . . . . . . . 1.3 Variables locales . . . . . . . . 1.4 Porte des variables . . . . . . e 1.5 Eet de bord . . . . . . . . . 2 Procdure paramtre e e e 2.1 Pseudo-passage de param`tres e 2.2 Paramtrage . . . . . . . . . . e 2.3 Comment ca marche . . . . . 2.4 Bons rexes . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
18 18 19 19 20 20 20 20 21 22 23
III
24
Cours
Deug 1 Mass MA, 1997 a 2004 ` 1 Instruction compose e 2 Les branchements 2.1 Le test boolen if . . . . . e 2.2 Slection de cas avec case e 3 Les boucles 3.1 La boucle while . . . . . . 3.2 La boucle repeat . . . . . 3.3 La boucle for . . . . . . . 3.4 Choix de la boucle . . . .
3 24 24 25 26 27 27 28 29 31
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
IV
Fonctions
1 Fonction sans param`tre e 1.1 Principe . . . . . . . . . . . . . 1.2 Appel . . . . . . . . . . . . . . 1.3 Variables locales . . . . . . . . . 2 Fonction avec param`tres e 2.1 Procdure vs fonction . . . . . . e 2.2 Passage de types enregistrement 3 Fonction avec plusieurs rsultats e 4 Gestion derreurs
32
32 . . . . . . . . . . . . . . . . . 32 . . . . . . . . . . . . . . . . . 32 . . . . . . . . . . . . . . . . . 32 33 . . . . . . . . . . . . . . . . . 33 . . . . . . . . . . . . . . . . . 34 34 36
Tableaux
1 Le type array 1.1 Principe . . . . . . . . . . . . . 1.2 Contrle des bornes . . . . . . . o 1.3 Recopie . . . . . . . . . . . . . 2 Super tableaux 2.1 Tableaux a plusieurs dimensions ` 2.2 Tableaux de record . . . . . . . 3 Le type string 3.1 Principe . . . . . . . . . . . . . 3.2 Oprateurs sur les strings . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
38 38 39 40 40 40 41 42 42 43
VI
Fichiers squentiels e
1 Le clavier et lcran e 1.1 Achage avec write 1.2 Lecture avec read . . 2 Fichiers de disque 2.1 Notions gnrales . . e e 2.2 Fichiers de texte . . . 2.3 Fichiers dlements . e 2.4 Gestion des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
44 44 45 47 47 48 49 50
Edouard Thiel
52
52 . . . . . . . . . . . . . . 52 . . . . . . . . . . . . . . 53 54 . . . . . . . . . . . . . . 54 . . . . . . . . . . . . . . 55 56 . . . . . . . . . . . . . . 57 . . . . . . . . . . . . . . 58 . . . . . . . . . . . . . . 59 . . . . . . . . . . . . . . 59 60 . . . . . . . . . . . . . . 60 . . . . . . . . . . . . . . 60 . . . . . . . . . . . . . . 60 . . . . . . . . . . . . . . 61 61
Cours
Edouard Thiel
Premiers programmes
Le programme bonjour
Un programme est une suite dinstructions, certaines tant des mots cls. e e Ce programme ache la cha de caract`res Bonjour a lcran : ne e ` e
PROGRAM bonjour; BEGIN writeln (Bonjour); END.
Le compilateur est un logiciel qui lit (analyse) un programme et le traduit en code machine, directement excutable par le processeur de lordinateur. e
1.2
On place un {commentaire} dans un programme au-dessus ou a cot dune ins` e truction. Le commentaire nest pas pris en compte a la compilation. Il sert a rendre le ` ` programme plus clair a la lecture, a noter des remarques, etc : ` `
{ Edouard Thiel - 21/01/2003 } PROGRAM bonjour; BEGIN { Affiche Bonjour a lcran } ` e writeln (Bonjour); END.
1.3
Une variable est une zone dans la mmoire vive de lordinateur, dote dun nom et e e dun type. Le nom de la variable permet daccder au contenu de la zone mmoire ; e e le type spcie la nature de ce qui peut tre stock dans la zone mmoire (entier, e e e e rel, caract`re, etc). e e On a coutume de reprsenter une variable par une bo ; dessous on met le nom, e te au dessus le type, et dans la bo le contenu. te Exemple avec une variable de nom a et de type entier :
PROGRAM var_entiere; VAR a : integer; BEGIN a := 5; writeln (valeur de a = , a); END. { Dclaration } e { Affectation } { Affichage : a = 5 }
Cours
La structure de ce programme est en 3 parties : le nom du programme, la partie dclarations, et le corps du programme, qui est une suite dinstructions. e La partie dclaration cre les variables (les bo e e tes) ; leur contenu est indtermin e e (on met un ? dans chaque bo te). La taille de la zone mmoire de chaque variable e est adapte au type (par exemple 1 octet pour un caract`re, 4 octets pour un entier, e e etc).
1.4
La trace dun programme est obtenue en plaant des writeln pour que le proc gramme ache les valeurs des variables a lexcution. Cela sert pour mettre au point ` e un programme en TP. Le tableau de sortie dun programme est un tableau avec une colonne par variable, o` lon crit lvolution des variables pendant le droulement du programme. u e e e Demand en TD et examen. e
1.5
Identicateur
Sert a donner un nom a un objet. ` `
Syntaxe On appelle lettre un caract`re de a..z ou A..Z ou _. e On appelle digit un caract`re de 0..9. e Un identicateur Pascal est une suite de lettres ou de digit accols, commenant e c par une lettre. Exemples x, y1, jour, mois, annee, NbCouleurs, longueur_ligne. Remarques Il ny a pas de dirence entre minuscules et majuscules. e On na pas le droit de mettre daccents, ni de caract`res de ponctuation. e Un identicateur doit tre dirent des mots cls (begin, write, real, . . .) e e e On se sert des identicateurs pour : le nom du programme, les noms de variables, les noms de constantes, les noms de types.
Edouard Thiel
Types prdnis e e
Un type dcrit un ensemble de valeurs et un ensemble doprateurs sur ces valeurs. e e
3.1
Entier sign en complment a deux sur 16 ou 32 bits, selon machine et compilae e ` teur : 16 pour Turbo Pascal, 32 pour Delphi. Sur 16 bits, a valeur dans 32 768 . . . + 32 767 (215 . . . + 215 1). ` Sur 32 bits, a valeur dans 2 147 483 648 . . . + 2 147 483 647 (231 . . . + 231 1). ` Oprateurs e abs(x) pred(x) succ(x) odd(x) sqr(x) + x - x x + y x - y x * y x / y x div y x mod y Remarques Attention, les oprateurs /, div et mod, produisent une erreur a lexcution si e ` e y est nul. Lorsquune valeur (ou un rsultat intermdiaire) dpasse les bornes au cours e e e de lexcution, on a une erreur appele dbordement arithmtique. e e e e sur les entiers : valeur absolue de |x|. x 1. x + 1. true si x est impair, false sinon. le carr de x. e identit. e signe oppos. e addition. soustraction. multiplication. division, fournissant un rsultat de type rel. e e dividende de la division enti`re de x par y. e reste de la division enti`re, avec y non nul. e
3.2
Leur domaine de dnition dpend de la machine et du compilateur utiliss. e e e On code un rel avec une certaine prcision, et les oprations fournissent une e e e valeur approche du rsultat dit juste . Il faut donc se mer : e e e Sous Delphi, writeln(0.3); ache 0.2999999... Ce nest pas un bug ; simplement, 0.3 nest pas reprsentable en base 2. En eet, en base 2 il scrit 0, 0 1001 : e e base 10 0, 3 0, 6 1, 2 0, 4 0, 8 1, 6 base 2 0, 0 1 0 0 1
Cours
Exemples de real 0.0 ; -21.4E3 (= 21, 4 103 = 21400) ; 1.234E-2 (= 1, 234 102 ) Oprateurs sur un argument x rel : abs(x), sqr(x), +x, -x. e e Si lun au moins des 2 arguments est rel, le rsultat est rel pour : x - y, x + y, e e e x * y. Rsultat rel que largument soit entier ou rel : x / y (y doit tre non nul) ; e e e e fonctions sin(x), cos(x), exp(x), ln(x), sqrt(x) (square root, racine carre). e Fonctions prenant un argument rel et fournissant un rsultat entier : trunc(x) e e (partie enti`re), round(x) (entier le plus proche). Si le rsultat nest pas reprsene e e table sur un integer, il y a dbordement. e
3.3
Le jeux des caract`res comportant les lettres, les digits, lespace, les ponctuations, e etc, est cod sur un octet non sign. e e Le choix et lordre des 256 caract`res possible dpend de la machine et de la e e langue. Sur PC, on utilise le code ASCII, o` A est cod par 65, B par 66, a u e par 97, par 32, { par 123, etc. Le code ascii est organis comme suit : de 0 ` 31, sont cods les caract`res e a e e de contrle (7 pour le signal sonore, 13 pour le saut de ligne, etc). De 32 ` 127, o a sont cods les caract`res et ponctuations standards et internationaux. Enn de 128 e e ` 255, sont cods les caract`res accentus propres a la langue, et des caract`res a e e e ` e semi-graphiques. Les oprateurs sur les chars sont : e ord(c) numro dordre dans le codage ; ici code ascii . e chr(a) le rsultat est le caract`re dont le code ascii est a. e e succ(c) caract`re suivant c dans lordre ascii chr(ord(c)+1) e prec(c) caract`re prcdent c dans lordre ascii. e e e Remarque Il y a erreur a lexcution si le caract`re nexiste pas. ` e e Exemple
PROGRAM caracteres; VAR c, d : char; a : integer; BEGIN c := F; a := ord(c); { 70 } writeln (Le code ascii de , c, est , a); a := 122; c := chr(a); { z } writeln (Le caractere de code ascii , a, est , c); c := j; d := succ(c); { k } writeln (Le caractere suivant , c, est , d); END.
10
Edouard Thiel
Exercice Acher les caract`res de code ascii de 32 a 255 ( sur cran et sur e e imprimante, les rsultats sont parfois dirents). e e Divers On peut remplacer chr(32) par #32, mais pas chr(i) par #i. Le caract`re apostrophe se note . e Une suite de caract`res telle que Il y a est une chane de caract`res ; il sagit e e dun objet de type string, que lon verra plus loin.
3.4
Utilis pour les expressions logiques. e Deux valeurs : false (faux) et true (vrai). Oprateurs boolens : not (ngation), and (et), or (ou). e e e Exemple
{ Declaration } petit, moyen, grand : boolean; { Instructions } petit := false; moyen := true; grand := not (petit or moyen);
e Table de vrit de ces oprateurs e e x true true false false y true false true false not x false false true true x and y true false false false x or y true true true false
Oprateurs de comparaison (entre 2 entiers, 2 rels, 1 entier et 1 rel, 2 chars, 2 e e e boolens) : e <, >, <=, >=, = (galit, a ne pas confondre avec lattribution :=), <> (dirent). e e ` e Le resultat dune comparaison est un boolen. e On peut comparer 2 boolens entre eux, avec la relation dordre false < true. e En mmoire, les boolens sont cods sur 1 bit, avec 0 pour false et 1 pour e e e true. De l` les relations dordre. Les oprateurs boolens not, and, or sapparentent a e e approximativement a (1 x), , +. `
Cours
11
4
4.1
Dclarations e
Constantes
Une constante est dsigne par un identicateur et une valeur, qui sont xs en e e e dbut de programme, entre les mots cls CONST et VAR. e e La valeur ne peut pas tre modie, et ne peut pas tre une expression. e e e Syntaxe identificateur = valeur_constante; ou identificateur : type = valeur_constante; Dans la premi`re forme, le type est sous-entendu (si il y a un point, cest un rel, e e sinon un entier ; si il y a des quotes, cest un caract`re (un seul) ou une cha de e ne caract`res (plusieurs). e Exemple
PROGRAM constantes; CONST faux = false; entier = 14; reel = 0.0; carac = z; chaine = hop; pourcent : real = 33.3; VAR { variables } BEGIN { instructions } END.
{ constantes NOMMEES }
4.2
Variables et aectation
Une variable reprsente un objet dun certain type ; cet objet est dsign par un e e e identicateur. Toutes les variables doivent tre dclares apr`s le VAR. e e e e Syntaxe identificateur : type ; On peut dclarer plusieurs variables de mme type en mme temps, en les sparant e e e e par des virgules (voir exemple ci-dessous). ` A la dclaration, les variables ont une valeur indtermine. On initialise les e e e variables juste apr`s le BEGIN (on ne peut pas le faire dans la dclaration). e e Utiliser la valeur dune variable non initialise est une erreur grave ! e Exemple
VAR a, b, c : integer; BEGIN { Partie initialisation }
12
Edouard Thiel
Lopration identificateur := expression; est une aectation. On na pas e le droit dcrire id1 := id2 := expr , ni expr := id ni expr1 := expr2 . e
Expressions
Une expression dsigne une valeur, exprime par composition doprateurs applie e e qus a des oprandes, qui sont : des valeurs, des constantes, des variables, des appels e ` e a fonction ou des sous-expressions. ` Exemple . Etant donn une variable x, une constante max et une fonction cos(), e chaque ligne contient une expression :
5 x + 3.14 2 * cos(x) (x < max) or (cos(x-1) > 2 * (x+1))
5.1
Syntaxe
Certains oprateurs agissent sur 2 oprandes : e e operande1 operateur_binaire operande2 et dautres agissent sur 1 oprande : e operateur_unaire operande Les oprateurs binaires sont : e oprateurs de relation e oprateurs additifs e oprateurs multiplicatifs e
Les oprateurs unaires sont : e oprateurs de signe e + oprateur de ngation not e e Les parenth`ses sont un oprateur primaire, elles peuvent encadrer tout oprande. e e e Une fonction est aussi un oprateur primaire, elle agit sur loprande plac entre e e e parenth`ses a sa droite. Certaines fonctions ont plusieurs param`tres, spars par e ` e e e des virgules.
Cours
13
5.2
Une expression doit tre bien forme pour que lon puisse trouver sa vae e leur. Par exemple, 3 * a - true nest pas bien forme, et la compilation Pascal e chouera. e Dans la partie 3, Types prdnis, on a dj` dit quels oprateurs sont applicables e e ea e sur quels types. Mais il y a encore dautres r`gles, dont le simple bon-sens ! e Lexpression bien forme a un type, qui dpend des r`gles dvaluation de lexe e e e pression. Exemple Soit r un rel, i un entier, e une constante enti`re, c un caract`re. Lexpression e e e (round(r+1) > (i/e)) or (c < a) est bien forme, et sont type est boolen comme on le montre ici : e e boolen e boolen e entier boolen e entier entier car. car. rel entier e ( round( r + 1 ) > ( i / e ) ) or ( c < a ) Remarque Le fait quune expression est bien forme nimplique pas que son valuation est e e sans erreur, ce qui peut tre le cas ici si e est nul. e rel e rel e
5.3
R`gles dvaluation e e
Lexpression a + b * c est value a + (b * c) et non pas (a + b) * c : ceci e e parce que le * est prioritaire par rapport a +. ` On classe les dirents oprateurs par ordre de priorit, les oprateurs de plus e e e e forte priorit tant raliss avant ceux de plus faible priorit. ee e e e Lorsque deux oprateurs sont de priorit gale, on value de gauche a droite. Par e ee e ` exemple a + b - c est valu (a + b) - c, et non pas a + (b - c). e e Voici la table des priorits classes par ordre dcroissant, les oprateurs sur une e e e e mme ligne ayant une priorit gale. e ee () fonction() + - not * / div mod and + - or = <> < <= >= > primaire unaire multiplicatif additif relation
14
Edouard Thiel
Remarque Est-ce que lexpression a < b or c <= d est bien forme ? Quel est son type ? e Rponse : non ! Ecrire une telle expression boolenne sans parenth`ses est une e e e erreur classique. En eet dans la table de priorits, loprateur or a une priorit plus leve que e e e e e les oprateurs < et <=, et donc lexpression sera value a < (b or c) <= d , ce e e e qui est faux. Lexpression bien forme est ici (a < b) or (c <= d) . e
Nouveaux types
On a vu les types pr-dclars boolean, integer, real et char. e e e Nous verrons par la suite comment crer de nouveau types. Nous commenons e c par les plus simples, le type intervalle et le type numr. e ee
6.1
Type intervalle
Cest un sous-ensemble de valeurs conscutives dun type hte. e o Syntaxe N..M o` N et M sont des constantes du mme type, et sont les bornes infrieures et supu e e e rieures de lintervalle, N et M inclus. Exemple
VAR pourcentage : 0 .. 100; digit : 0 .. 9; reponse : false .. true; { le type hote est integer } { le type hote est char } { le type hote est boolean }
Remarques Il faut imprativement que le type hte soit cod sur un entier (sign ou non, e o e e sur un nombre de bits quelconque). On dit alors que ce type hte est un type o ordinal. Ainsi les types integer, char et boolean sont des types ordinaux. Seul un type ordinal admet les oprateurs pred, succ et ord (le prcdent, le e e e successeur et le numro dordre dans le codage). e Par contre le type real nest pas ordinal, et donc on ne pas crer un type e intervalle avec des rels, il ny a pas de notion de rels conscutifs . e e e Un autre cas de type non ordinal est le type string pour les cha nes de caract`res, qui nest pas cod sur un mais sur plusieurs entiers. On ne peut donc pas e e dclarer aaa..zzz. e
Cours
15
Bonne habitude Utiliser des constantes nommes pour borner les intervalles : de la e sorte on pourra consulter ces valeurs pendant le programme, et ces bornes ne seront crites quune seule fois. e Exemple
CONST PMin = 0; PMax = 100; VAR pourcentage : PMin .. PMax; BEGIN writeln (Lintervalle est , PMin, .. , PMax); END.
6.2
Type numr e e e
Il est frquent en programmation que lon aie a distinguer plusieurs cas, et que e ` lon cherche a coder le cas a laide dune variable. ` ` Exemple
VAR feux : 0..3; { rouge, orange, vert, clignotant } BEGIN { ... } if feux = 0 then Arreter else if feux = 1 then Ralentir else if feux = 2 { ... } END.
Ceci est tr`s pratique mais dans un programme un peu long cela devient rapidee ment dicile a comprendre, car il faut se souvenir de la signication du code. ` Do` lintrt dutiliser un type numr, qui permet de donner un nom aux u ee e e e valeurs de code :
VAR feux : (Rouge, Orange, Vert, Clignotant); BEGIN { ... } if feux = Rouge then Arreter else if feux = Orange then Ralentir else if feux = Vert { ... } END.
En crivant cette ligne, on dclare en mme temps : e e e la variable feux, de type numr (toujours code sur un entier), e ee e et les constantes nommes Rouge, Orange, Vert et Clignotant. e
16
Edouard Thiel
` A ces constantes sont attribues les valeurs 0, 1, 2, 3 (la premi`re constante prend e e toujours la valeur 0). On ne peut pas choisir ces valeurs soi-mme, et ces identicateurs ne doivent e pas dj` exister. ea Lintrt nest pas de conna ces valeurs, mais davoir des noms explicites. ee tre Le type numr tant cod sur un entier, il sagit dun type ordinal et on peut : e eee e utiliser les oprateurs pred, succ et ord (exemple : pred(Orange) est Rouge, e succ(Orange) est Vert, ord(Orange) est 1). dclarer un type intervalle a partir dun type numr (exemple : Rouge..Vert). e ` e ee
6.3
Dclarer un type e
Crer un type, cest bien, mais le nommer, cest mieux. On dclare les noms de e e types entre les mots cls TYPE et VAR. e Syntaxe nom_du_type = type; Exemple
TYPE couleurs_feux_t = (Rouge, Orange, Vert, Clignotant); VAR feux : couleurs_feux_t;
De la sorte couleurs_feux_t est un nom de type au mme titre que integer ou e char. Exemple complet
PROGRAM portrait; CONST TailleMin = 50; { en cm } TailleMax = 250; TYPE taille_t = TailleMin .. TailleMax; couleurs_t = (Blond, Brun, Roux, Bleu, Marron, Noir, Vert); cheveux_t = Blond .. Roux; yeux_t = Bleu .. Vert; VAR taille_bob, taille_luc : taille_t; cheveux_bob, cheveux_luc : cheveux_t; yeux_bob, yeux_luc : yeux_t; BEGIN taille_bob := 180; cheveux_bob := Brun; yeux_bob := Noir; END.
Remarque Observez bien les conventions dcriture direntes que jai employes e e e pour distinguer les constantes des types et des variables ; cela aussi aide a la lecture. `
Cours
17
6.4
Type enregistrement
Il sagit simplement de regrouper des variables V1, V2, . . . de dirents types T1, e T2, . . . dans une variable a tiroirs . ` Syntaxe
Record V1 : T1; V2 : T2; { ... } End;
Soit r une variable de ce type ; on acc`de aux dirents champs de r par r.V1, e e r.V2, . . . Reprenons lexemple du programme portrait.
{ ... } TYPE { ... } personne_t = Record taille : taille_t; cheveux : cheveux_t; yeux : yeux_t; End; VAR bob, luc : personne_t; BEGIN bob.taille := 180; bob.cheveux := Brun; bob.yeux := Noir; luc := bob; END.
e Remarque La seule opration globale sur un enregistrement est : recopier le contenu de r2 dans r1 en crivant : r2 := r1; e Ceci est quivalent (et plus ecace) que de copier champ a champ ; en plus on ne e ` risque pas doublier un champ. Il y a une condition : les 2 variables doivent tre exactement du mme type. e e Intrt de ce type ee Il permet de structurer tr`s proprement des informations qui vont ensemble, de les e recopier facilement et de les passer en param`tres a des procdures (on y reviendra). e ` e Remarque gnrale e e Lorsquon cre un type T2 a partir dun type T1, ce type T1 doit dj` exister ; e ` ea donc T1 doit tre dclar avant T2. e e e
18
Edouard Thiel
II. Procdures e
Une procdure est un sous-programme. Ecrire des procdures permet de dcouper e e e un programme en plusieurs morceaux. Chaque procdure dnit une nouvelle instruction, que lon peut appeler en tout e e endroit du programme. On peut ainsi rutiliser le code dun sous-programme. e Lorsquon dcoupe un probl`me en terme de procdures, puis quon implmente e e e e ces procdures, on fait ce quon appelle une analyse descendante : on va du plus e gnral au dtail. e e e
1
1.1
Il sagit simplement de donner un nom a un groupe dinstructions. ` Ensuite, lappel de ce nom a divers endroits du programme provoque a chaque ` ` fois lexcution de ce groupe dinstructions. e Exemple
PROGRAM exemple1; VAR x, y, t : integer; { Declaration de la procedure Echange_xy } PROCEDURE Echange_xy; BEGIN { Corps de la procedure } t := x; x := y; y := t; END; BEGIN { Programme principal } x := 3; y := 4; writeln (x, , y); Echange_xy; { 1er appel de la procedure } writeln (x, , y); Echange_xy; { 2eme appel de la procedure } writeln (x, , y); END.
34 43 34
Le nom de la procdure est un indenticateur. e On dclare toute procdure avant le BEGIN du programme principal. e e
Cours
19
1.2
Appels
On peut tr`s bien appeler une procdure P1 depuis une procdure P2, mais il faut e e e que la procdure P1 aie t dclare avant la procdure P2. e ee e e e Exemple donnant le mme rsultat. e e
PROGRAM exemple2; VAR x, y, t : integer; PROCEDURE Affiche_xy; BEGIN writeln (x, , y); END; PROCEDURE Echange_xy; BEGIN t := x; x := y; y := t; Affiche_xy; END; BEGIN x := 3; y := 4; Affiche_xy; Echange_xy; Echange_xy; END.
Remarque On peut aussi appeler une procdure depuis elle-mme : cest la rcursivit, que e e e e lon ntudiera pas dans ce module. e
1.3
Variables locales
Les objets du programme qui ne sont utiles que dans la procdure peuvent tre e e dnis dans les dclarations locales de la procdure. e e e Exemple Reprenons exemple1 et changeons t :
PROGRAM exemple3; VAR x, y : integer; PROCEDURE Echange_xy; VAR t : integer; { Declaration locale } BEGIN t := x; x := y; y := t; END; BEGIN { ... } END.
Une variable dclare localement nexiste que pendant lexcution de la procdure, e e e e et ne sert que a cette procdure. ` e Le programme principal na jamais acc`s a une variable locale de procdure. e ` e Une procdure na jamais acc`s a une variable locale dune autre procdure. e e ` e Amliore la lisibilit du programme. e e
20
Edouard Thiel
1.4
Les variables dclares dans le VAR du programme principal sont appeles variables e e e globales. Elles existent pendant toute la dure du programme et sont accessible de e partout. Une variable locale a une procdure P, portant le mme nom x quune variable ` e e globale, masque la variable globale pendant lexcution de P. e Exemple
PROGRAM exemple4; VAR x : integer; PROCEDURE Toto; VAR x : integer; BEGIN x := 4; writeln (toto x = , x); END; BEGIN x := 2; writeln (glob x = , x); Toto; writeln (glob x = , x); END.
Ce programme ache
1.5
Eet de bord
On est dans une procdure P et on veut modier une variable x locale a P. e ` Il existe dj` une variable globale ayant le mme nom x. ea e On oublie de dclarer la variable locale x au niveau de P. e ` A la compilation tout va bien ! ` A lexcution, P modie le x global alors que le programmeur ne lavait pas e voulu. Consquence : le programme ne fait pas ce quon voulait, le x global a lair de e changer de valeur tout seul !
2
2.1
Procdure paramtre e e e
Pseudo-passage de param`tres e
Ecrivons une procdure Produit qui calcule z = xy. e
Cours
21
Remarques Lcriture est un peu lourde. e Il faut savoir que la procdure communique avec les variables x, y, z. e Cela interdit de se servir de x, y, z pour autre chose que de communiquer avec la procdure ; sinon gare aux eets de bord ! e Deux sortes de param`tres : donnes et rsultats. e e e
2.2
Paramtrage e
La solution lgante consiste a dclarer des param`tres a la procdure : ee ` e e ` e [ Dire que cest quiv a 2.1 ; mettre les progs cte a cte ] e ` o ` o
PROGRAM exemple5bis; VAR a, b, c, d : real; PROCEDURE Produit (x, y : real; var z : real); BEGIN z := x * y; END; BEGIN write (a b ? ); readln (a, b); Produit (a, b, c); Produit (a-1, b+1, d); writeln (c = , c, d = , d); END. { passage de } { parametres } { parametres }
22
Edouard Thiel
2.3
Comment ca marche
` A lappel, on donne des param`tres dans les parenth`ses, spars par des virgules, e e e e et dans un certain ordre (ici a puis b puis c). Lexcution de la procdure commence ; la procdure reoit les param`tres et e e e c e identie chaque param`tre a une variable dans le mme ordre (ici x puis y puis z). e ` e [ Dessiner des ches a x , b y , c z ] e Les types doivent correspondre ; ceci est vri a la compilation. e e` Il y a deux sorte de passage de param`tres : le passage par valeur et le passage e par rfrence. ee Passage par valeur : a lappel, le param`tre est une variable ou une expression. ` e Cest la valeur qui est transmise, elle sert a initialiser la variable correspondante ` dans la procdure (ici x est initialis a la valeur de a et y a la valeur de b). e e` ` Passage par rfrence : a lappel, le param`tre est une variable uniquement ee ` e (jamais une expression). Cest ladresse mmoire (la rfrence) de la variable e ee qui est transmise, non sa valeur. La variable utilise dans la procdure est en fait e e la variable de lappel, mais sous un autre nom (ici z dsigne la mme variable e e (zone mmoire) que a). e Cest le mot-cl var qui dit si le passage se fait par valeur (pas de var) ou par e rfrence (prsence du var). ee e Pas de var = donne ; prsence du var = donne/rsultat. [ dessiner une double e e e e che c z ] e Erreurs classiques Mettre un var quand il nen faut pas : on ne pourra pas passer une expression en param`tre. e Oublier le var quand il en faut un : la valeur calcule ne pourra pas sortir e de la procdure. e Exemples derreurs a lappel de Produit (a-1, b+1, d); ` PROCEDURE Produit (var x : real; y : real; var z : real); ne compile pas a cause du param`tre 1, o` une variable est attendue et cest une ` e u expression qui est passe. e PROCEDURE Produit (x, y, z : real); produit une erreur a lexcution : d ne reoit jamais le rsultat z car il sagit de 2 ` e c e variables distinctes. Porte des variables : e dans Exemple5bis, les param`tres x, y, z de la procdure Produit sont des vae e riables locales a Produit. `
Cours
23
Leur nom nest donc pas visible de lextrieur de la procdure. e e Attention : redclarer un param`tre comme variable locale erreur a la come e ` pilation. Exemple :
PROCEDURE Produit (x, y : real; var z : real); VAR t : real; { dclaration dune var locale : permis } e x : real; { redclaration dun param`tre : interdit } e e BEGIN z := x * y; END;
2.4
Bons rexes e
Le seul moyen pour une procdure de communiquer avec lextrieur, cest a dire e e ` avec le reste du programme, ce sont les variables globales et les param`tres. e Il faut toujours viter soigneusement les eets de bords. Le meilleur moyen est de e paramtrer compl`tement les procdures, et dviter la communication par variables e e e e globales. Les variables de travail tels que compteur, somme partielle, etc doivent tre locales e a la procdure, surtout pas globale. ` e Prendre lhabitude de prendre des noms de variables dirents entre le proe gramme principal et les procdures : on dtecte plus facilement a la compilation e e ` les eets de bords. Chaque fois que lon appelle une procdure, on vrie particuli`rement le bon e e e ordre des param`tres et la correspondance des types. La compilation est tr`s poine e tilleuse sur les types, mais par contre elle ne dtecte pas les inversions de param`tres e e de mme type. e
24
Edouard Thiel
III.
Instruction compose e
Une instruction spcie une opration ou un encha e e nement doprations a excuter e ` e sur des objets. Les instructions sont spares par des ; et sont excutes squentiellement, ceste e e e e a-dire lune apr`s lautre, depuis le BEGIN jusquau END. nal. ` e Instruction dj` vues ea a := 5 writeln (Bonjour) readln (x) ma_procedure (parametres) Plus gnralement Soient I1, I2, etc, des instructions. e e On fabrique dans la suite de nouvelles instructions : if expr then I1 while test do I1 etc Il est possible de regrouper lencha nement I1; I2; I3; en une instruction unique en lencadrant entre un begin et un end begin I1; I2; I3; end Intrt On veut faire I1 puis I2 dans un if. ee aectation achage lecture appel procdure e
if B then I1 ; I2 ;
(on met des accolades sur les instructions). ` Dans la 1ere forme, I2 ne fait pas partie du if, dans la 2nde oui.
Les branchements
Etant donn une expression et plusieurs instructions, la valeur de lexpression va e dterminer laquelle de ces instructions excuter. e e En Pascal il y a 2 types de branchements, le if et le case.
Cours
25
2.1
Le test boolen if e
Linstruction ci-dessous prend 2 formes, elle signie si . . . alors . . . sinon. Syntaxe if B then I1; if B then I1 else I2; B est une expression boolenne, I1 et I2 sont des instructions. e Lexpression B est value ; si elle est vraie, alors I1 est excute, sinon I2 est e e e e excute. e e Remarque On peut se passer de else en nemployant que des if then, mais cest moins ecace, et on peut facilement se tromper : lexemple suivant ne donne pas les mmes rsultats ! e e
a := 1; { sans else } if a = 1 then a := 2; if a <> 1 then a := 3; { avec else } if a = 1 then a := 2 else a := 3;
R`gles e Il ny a jamais de ; avant le else . Le else se rapporte toujours au dernier then rencontr. e Probl`me Dans la deuxieme forme, comment supprimer linstruction Ib ? e On ne peut pas simplement supprimer la ligne else Ib, car alors le else if B3 se rapporterait a then Ia. ` On ne peut pas non plus rajouter un ; car il y a un else apr`s. e La solution consiste a protger if B2 then Ia; dans un begin end : ` e
if B1 then begin if B2 then Ia; end else if B3 then Ic else Id;
26
Edouard Thiel
Remarque Il faut faire tr`s attention aux tests multiples, imbriqus ou non, et tre e e e tr`s rigoureux dans lcriture. La r`gle est dindiquer entre {} le cas prcis dans e e e e lequel on se trouve.
{ forme 1 } if B1 then { B1 } I1 else if B2 then { !B1 et B2 } I2 else if B3 then { !B1 et !B2 et B3 } I3 else { !B1 et !B2 et !B3 } Iautre; { forme 2 } if B1 then if B2 then { B1 et B2 } Ia else { B1 et !B2 } Ib else if B3 then { !B1 et B3 } Ic else { !B1 et !B3 } Id;
2.2
Syntaxe
Cette instruction signiant choix selon permet dexcuter lune des instructions e Ix selon le cas E. E est une expression ordinale (dont le type est un entier, un caract`re, un boolen, e e ou un numr, mais pas un rel ni une cha de caract`res). Les Cx sont des e ee e ne e constantes ordinales du mme type que E. e Comment ca marche E est valu. Ensuite, est recherche parmi les valeurs possibles e e e Cx, laquelle est gale a E. Linstruction correspondante Ix est alors excute. Sinon, e ` e e linstruction apr`s le else (sil y en a un) est excute. e e e On peut donner une liste de constantes, ou des intervalles de constantes. Attention, chaque valeur possible ne doit tre reprsente quune fois au plus e e e (sinon il y a erreur a la compilation). Par exemple, on ne peut pas faire des intervalles ` se chevauchant, comme 3..6 et 5..10, les cas 5 et 6 tant reprsents 2 fois. e e e Lexemple donn ci-dessus est quivalent a une forme en if then else imbriqus. e e ` e
V := if V else else else else E; { evalue une seule fois au debut } = C1 then Ia if V = C2 then Ib if (V = C3) or (V = C4) then Ic if (V >= C5) and (V <= C6) then Id Iautre;
Cours
27
On prf`re la forme avec le case, qui est plus lisible et plus ecace. ee Exercice Rcrire lexemple sur les feux du I.6.2, (Type numr) avec un case. ee e e e Exemple complet Ecrire un programme qui lit un caract`re, puis classe ce caract`re comme espace, e e lettre, digit ou autre.
PROGRAM caractere; TYPE nat_t = (Espace, Lettre, Digit, Autre); VAR nat : nat_t; { nature } c : char; BEGIN write (Rentrez un caractere :); readln(c); { analyse de c } case c of a..z, A..Z, _ : 0..9 : : else end; { case c }
:= := := :=
{ affichage de nat } case nat of Espace : writeln (Espace); Lettre : writeln (Lettre); Digit : writeln (Digit); Autre : writeln (Autre); else { case nat } writeln (Erreur case nat : , ord(nat), non prevu); end; { case nat } END.
Bonnes habitudes Apr`s le else et le end, marquer en commentaire quils se rapportent au case. e Faire acher un message derreur apr`s le else : aide a la mise au point du e ` programme.
3
3.1
Les boucles
La boucle while
Cette instruction signie tant que. Elle permet de rpter lexcution dune inse e e truction de boucle I :
28
Edouard Thiel
Syntaxe while B do I; B est une expression boolenne. e () B est value. Si B est vraie, alors I est excute, et on recommence depuis e e e e (). Remarques Les variables de lexpression B doivent tre initialises avant le while, pour que e e au premier passage B puisse tre valu. e e e Le while continue de boucler tant que B nest pas faux. Pour viter une boucle e innie, qui plante le programme, il faut obligatoirement que dans I il y aie une sous-instruction rendant B faux a un moment donn. ` e Exemple Programme calculant la somme des nombres de 1 a 100. `
PROGRAM Somme; VAR s, k : integer; BEGIN s := 0; k := 1; while k <= 100 do begin s := s + k; k := k + 1; end; writeln (s); END.
3.2
La boucle repeat
Cette instruction signie rpter . . . jusqu` . Elle permet comme le while de e e a rpter lexcution dune instruction de boucle I : e e e Syntaxe repeat I; until B; B est une expression boolenne. e () I est excute, puis B est value. Si B est vraie, alors on sarrte, sinon on e e e e e recommence depuis ().
29
Linstruction I est excute au moins une fois. e e Le test B tant valu apr`s I, B peut tre aect dans I. Pour le while il faut e e e e e e avoir initialis B avant. e Pas besoin dencadrer un groupe dinstructions par un begin end, le repeat until joue dj` ce rle. ea o Exemple Le while de Somme scrit avec un repeat : e
s := 0; k := 1; repeat s := s + k; k := k + 1; until k > 100;
3.3
La boucle for
Cette instruction signie pour. Elle permet de rpter lexcution dune instruce e e tion de boucle I : Syntaxe for k := E1 to E2 do I; k est le compteur de boucle, E1 et E2 sont les bornes infrieures et suprieures. e e E1 et E2 sont des expressions ordinales, du mme type que la variable k. e E1 et E2 sont dabord values, puis k prend la valeur E1. () Si k <= E2, alors I e e est excute, puis k est incrment de 1, et on recommence depuis (). e e e e Pour avoir une boucle dcroissante, on crit e e for k := E2 downto E1 do I; On peut crire une boucle for k := E1 to E2 do I; avec un while : e
k := E1; { init de k } m := E2; { on evalue E2 une fois pour toutes } while k <= m do begin I; k := k+1; end;
30
Edouard Thiel
Remarques Linstruction de boucle I nest pas excute du tout si E1 > E2. e e Modier pendant la boucle la valeur de E1 ou E2 na pas deet. Il est totalement interdit de modier la valeur du compteur k dans le corps de la boucle. Lincrment de 1 nest pas modiable (contrairement au Basic avec step). e ` A la n de lexcution de la boucle, la variable k redevient indtermine : elle e e e a une valeur qui dpend du compilateur. Par exemple sous Delphi, elle vaut e E2+1, et sous Turbo Pascal 7.0, elle vaut E2. Exemple dapplication des r`gles : dire la valeur ache e e
a := 5; for i := a to a+10 do a := a*2; writeln(a);
[ cest 10240 ]
Variante
for i := 1 to 10 do for j := 1 to 10 do begin write (i*j : 3); if j = 10 then writeln; end;
Cours
31
3.4
Choix de la boucle
La r`gle est simple (lapprendre par cur) : e Si le nombre ditrations est connu a priori, alors on utilise un for. e Sinon : on utilise le repeat (quand il y a toujours au moins une itration), ou le e while (quand le nombre ditrations peut tre nul). e e
32
Edouard Thiel
IV. Fonctions
Une fonction est une procdure qui renvoie un rsultat, de mani`re a ce quon e e e ` puisse lappeler dans une expression. Exemples y := cos(x) + 1; c := chr(x + ord(0));
1
1.1
Syntaxe
La nouveaut par rapport a une procdure est que lon sort le rsultat de la e ` e e fonction nom_fonction en crivant une aectation sur son nom. e Attention nom_fonction nest pas une variable, et a lintrieur de la fonction il ne faut ` e surtout pas lutiliser dans une expression, car cela provoquerait un appel rcursif. e Une fonction doit toujours avoir un rsultat (i.e on ne peut pas le laisser indtere e min). e
1.2
Appel
PROGRAM ex1; VAR x : type_resultat; { ici dclaration de la fonction } e BEGIN { appel fonction et stockage du rsultat dans x } e x := nom_fonction; END.
1.3
Variables locales
FUNCTION nom_fonction : type_resultat; VAR locales : types_locales; BEGIN { ... } nom_fonction := expression; { du type type_resultat } END;
Cours
33
Bonne habitude Passer par une variable locale res : on fait ce quon veut de res dans la fonction, et a la n de la fonction on crit nom_fonction := res; ` e
FUNCTION nom_fonction : type_resultat; VAR res : type_resultat; BEGIN { ... dans le corps, on fait ce quon veut de res ...} { on dit que le rsultat est res } e nom_fonction := res; END;
Syntaxe
Tout ce que lon a dit sur le paramtrage des procdures reste valable pour les e e fonctions.
2.1
Procdure vs fonction e
Exemple du produit.
PROGRAM exemple5ter; VAR a, b, c, d : real; PROCEDURE Produit (x, y : real; var z : real); BEGIN z := x * y; END; | | | | | | FUNCTION Produit (x, y : real) : real; VAR res : real; BEGIN res := x * y; Produit := res; END;
BEGIN write (a b ? ); readln (a, b); Produit (a, b, c); Produit (a-1, b+1, d); | | c := Produit (a, b); d := Produit (a-1, b+1);
34
Edouard Thiel
2.2
Exemple On veut savoir si un couple damis est assorti. On xe les r`gles suivantes : e le couple est assorti si ils ont moins de 10 ans dcart, ou si le mari est ag et riche. e e
PROGRAM assorti; TYPE humain_t = Record age, taille : integer; riche : boolean; End; couple_t = Record homme, femme : humain_t; nb_enfant : integer; End; FUNCTION difference_age (h, f : humain_t) : integer; VAR res : integer; BEGIN res := abs (h.age - f.age); difference_age := res; END; FUNCTION couple_assorti (c : couple_t) : boolean; VAR res : boolean; BEGIN res := false; if difference_age (c.homme, c.femme) < 10 then res := true; if (c.homme.age > 75) and c.homme.riche then res := true; couple_assorti := res; END; VAR amis : couple_t; BEGIN { ... } write (Ce couple avec , amis.nb_enfant, enfant(s) est ); if couple_assorti (amis) then writeln (assorti.) else writeln (non assorti.); END.
Il est frquent que lon crive une fonction qui renvoie un boolen qui dit si tout e e e sest bien pass, tandis que les vrais rsultats sont passs dans les param`tres. e e e e Exemple Une fonction qui prend une lettre, la met en majuscule ou renvoie une erreur si le caract`re nest pas une lettre. e
FUNCTION maj_lettre ( lettre : char; var maj : char ) : boolean;
VAR res : boolean; BEGIN { init } maj := lettre; res := true; { pas derreur }
Cours
35
case lettre of a .. z : maj := chr(ord(lettre) - ord(a) + ord(A)); A .. Z, _ : ; { rien } else res := false; end; { case lettre } maj_lettre := res; END;
Autre avantage : on fait tous les achages et messages derreur en dehors de la fonction. Exemple [ non vu en cours faute de temps ]
i=b i+k i=a cos (ik)
On veut calculer
x+y cos (xy)
On crit dabord une fonction calc qui renvoie un boolen qui dit si le calcul de e e a pu se faire, tandis que le rsultat numrique est pass en param`tre z. e e e e
FUNCTION calc ( x : integer; y : real; var z : real ) : boolean; VAR ok : boolean; d : real; BEGIN ok := true; { init pas derreur } d := if d then else cos (x-y); = 0.0 ok := false { division par 0 } z := (x+y) / d; { resultat numerique }
36
Edouard Thiel
Exercice Modier la fonction somme pour que elle renvoie un boolen disant que tous les e calculs de la somme ont pu se faire, tandis que le rsultat numrique est pass en e e e param`tre. e Adapter le programme principal appelant somme.
Gestion derreurs
[ non vu en cours, tombe un peu a plat .. ] `
On veut gnraliser lusage de fonctions renvoyant un code derreur, et dont les e e rsultats sont passs en param`tres. e e e Soient F1, F2, etc, de telles fonctions renvoyant un boolen. e Soit ok un boolen. e Soient I1, I2, etc, des instructions. Considrons la squence dinstruction suivante e e
I1; ok := I2; ok := I3; ok := I4; { ...
On veut excuter ce traitement, mais linterrompre ds quil y a une erreur. e e On devrait normalement crire : e
Cours
37
I1; if F1 ( ... ) then begin I2; if F2 ( ... ) then begin I3; if F3 ( ... ) then begin I4; { ... } end; end; end;
Cest lourd, on se perd rapidement dans tous ces begin end. Il est beaucoup simple dcrire e
I1; ok := F1 ( ... ); if ok then begin I2; ok := F2 ( ... ); end; if ok then begin I3; ok := F3 ( ... ); end; if ok then begin I4; { ... } end;
38
Edouard Thiel
V. Tableaux
Les tableaux permettent de manipuler plusieurs informations de mme type, de e ere ` eme ` eme ` leur mettre un indice : la 1 info, la 2 info, . . ., la i info, . . . Ils sont stocks en mmoire centrale comme les autres variables, contrairement e e aux chiers qui sont stocks sur le disque. e Une proprit importante des tableaux est de permettre un acc`s direct aux donee e nes, grce a lindice. e a ` On appelle souvent vecteur un tableau en une dimension.
1
1.1
Le type array
Principe
Syntaxe array [ I ] of T I tant un type intervalle, et T un type quelconque. e Ce type dnit un tableau comportant un certain nombre de cases de type T, e chaque case est repre par un indice de type I. ee Exemple
TYPE vec_t = array [1..10] of integer; VAR v : vec_t;
` A la dclaration, le contenu du tableau est indtermin, comme toute variable. e e e On acc`de a la case indice i par v[i] (et non v(i)). e ` Pour mettre toutes les cases a 0 on fait `
for i := 1 to 10 do v[i] := 0;
Remarque Lintervalle du array peut tre de tout type intervalle, par exemple 1..10, e a..z, false..true, ou encore un intervalle dnumrs Lundi..Vendredi. e ee On aurait pu dclarer vecteur comme ceci (peu dintrt) : e ee
TYPE interv = 1..10 ; vec_t = array [ interv ] of integer;
Cours
39
1.2
Il est en gnral conseill de reprer les bornes de lintervalle avec des constantes e e e e nommes : si on dcide de changer une borne, cela est fait a un seul endroit dans le e e ` programme. Lcriture prconise est donc e e e
CONST vec_min = 1; vec_max = 10; TYPE vec_t = array [vec_min..vec_max] of integer;
R`gle 1 e Il est totalement interdit dutiliser un indice en dehors de lintervalle de dclarae tion, sinon on a une erreur a lexcution. ` e Il faut donc tre tr`s rigoureux dans le programme, et ne pas hsiter a tester si e e e ` un indice i est correct avant de se servir de v[i]. ` Exemple Programme demandant a rentrer une valeur dans le vecteur.
CONST vec_min = 1; vec_max = 10; TYPE vec_t = array [vec_min..vec_max] of integer; VAR v : vect_t; i : integer; BEGIN write (i ? ); readln(i); if (i >= vec_min) and (i <= vec_max) then begin write (v[, i, ] ? ); readln(v[i]); end else writeln (Erreur, i hors intervalle , vec_min, .., vec_max); END.
R`gle 2 Le test dun indice i et de la valeur en cet indice v[i] dans la mme e e expression sont interdits. Exemple
if (i >= vec_min) and (i <= vec_max) and (v[i] <> -1) then ... else ...;
Une expression est toujours value en intgralit ; donc si (i <= vec_max), le e e e e test (v[i] <> -1) sera quand mme eectu, alors mme que lon sort du vecteur ! e e e Solution : sparer lexpression en 2. e
if (i >= vec_min) and (i <= vec_max) then if (v[i] <> -1) then ... else ... else ... { erreur hors bornes } ;
40
Edouard Thiel
1.3
Recopie
En Pascal, la seule opration globale sur un tableau est : recopier le contenu dun e tableau v1 dans un tableau v2 en crivant : v2 := v1; e Ceci est quivalent (et plus ecace) que e for i := vec_min to vec_max do v2[i] := v1[i]; Il y a une condition : les 2 tableaux doivent tre exactement de mmes types, i.e e e issus de la mme dclaration. e e
TYPE vecA = array [1..10] of char; vecB = array [1..10] of char; VAR v1 : vecA; v2 : vecA; v3 : vecB; BEGIN v2 := v1; { legal car meme type vecA } v3 := v1; { illegal, objets de types <> vecA et vecB }
Super tableaux
Quelques types un peu plus complexes a base de tableaux, et de combinaisons ` entre types.
2.1
Exemple : dimension 1 = vecteur ; dimension 2 = feuille excel ; dimension 3 = classeur excel [ faire petit schma ]. e On peut crer des tableaux a plusieurs dimensions de plusieurs mani`res : e ` e Faire des schmas e v1 : array [1..10] of array [1..20] of real Tableau de 10 lments, chaque lment tant un tableau de 20 rels. ee ee e e On acc`de a llment dindice i dans 1..10 et j dans 1..20 par v1[i][j]. e ` ee v2 : array [1..10, 1..20] of real Tableau de 10 20 rels. e On acc`de a llment dindice i dans 1..10 et j dans 1..20 par v2[i,j]. e ` ee Exemple Mise a 0 du tableau v2. `
VAR v2 : array [1..10, 1..20] of real; i, j : integer; BEGIN for i := 1 to 10 do for j := 1 to 20 do v2[i,j] := 0.0; END.
Cours
41
2.2
Tableaux de record
On peut crer des tableaux denregistrements, et des enregistrements qui contiennent e des tableaux.
PROGRAM Ecole; CONST MaxEleves = 35; MaxNotes = 10; TYPE note_t = array [1..MaxNotes] of real; eleve_t = Record age, nb_notes : integer; notes : note_t; moyenne : real; End; classe_t = array [1..MaxEleves] of eleve_t; VAR c : classe_t; nb_eleves, i, j : integer; BEGIN { ... } for i := 1 to nb_eleves do begin writeln (Eleve n., i); writeln ( age : , c[i].age); write ( notes :); for j := 1 to c[i].nb_notes do write ( , c[i].notes[j]); writeln; writeln ( moy : , c[i].moyenne); end; END.
On a comme dhabitude le droit de faire une copie globale entres variables du mme type : e
VAR c1, c2 : classe_t; e : eleve_t; i, j : integer; BEGIN { copie globale de type classe_t } c2 := c1; { echange global de type eleve_t } e := c1[i]; c1[i] := c1[j]; c1[j] := e; END.
42
Edouard Thiel
BEGIN { ... } for i := 1 to nb_eleves do begin writeln (Eleve n., i); affi_eleve (c[i]); end; END.
affi_eleve(e) ne connait pas le numro de ll`ve ; lappelant, lui, connait le e ee numro, et lache avant lappel. e On peut encore crire une procdure affi_classe : e e
PROCEDURE affi_classe (c : classe_t ; nb : integer); VAR i : integer; BEGIN for i := 1 to nb do begin writeln (Eleve n., i); affi_eleve (c[i]); end; END; BEGIN { ... } affi_classe (c, nb_eleves); END.
Le type string
On code une cha de caract`re telle que bonjour dans un objet de type ne e string.
3.1
Principe
Syntaxe string [m] o` m est une constante enti`re donnant le nombre maximum de caract`res pouvant u e e tre mmoriss. Exemple : e e e
VAR s : string[80]; BEGIN s := Le ciel est bleu.; writeln (s); END.
Codage Ayant dclar s : string[80], comment sont cods les caract`res ? e e e e En interne, Pascal rserve un array [0..80] of char. e Le premier caract`re est s[1], le deuxi`me est s[2], etc. e e La longueur courante de la cha est cod dans la case 0 ( ord(s[0])). ne e
Cours
43
Remarque Aecter une cha plus longue que lespace rserv a la dclaration est une ne e e ` e erreur. Comme la longueur courante est code sur un char, elle est limite a 255. e e `
3.2
a := a := b a := c + d length(a)
CONST VAR
BEGIN s1 := veuillez ; s2 := s1 + Slogan; writeln (s2 = , s2, ); writeln (Longueur courante de s2 : , length(s2) ); write (Indices des l dans s2 : ); for i := 1 to length(s2) do if s2[i] = l then write(i, ); writeln; END.
e Comparaison entre 2 string : les oprateurs =, <>, <, >, <=, >=, sont utilisables, et le rsultat est un boolen. e e La comparaison se fait selon lordre lexicographique du code ASCII. e Exemple Soit b un boolen ; b est-il vrai ou faux ?
b b b b := := := := A la vanille < Zut; bijou < bidon; Bonjour = bonjour; zim boum > attends !; { { { { vrai } faux, cest > car j > d } faux, cest < car B < b } faux, cest < car < a }
44
Edouard Thiel
Le clavier et lcran e
Le clavier et lcran sont grs comme des chiers particuliers : ce sont des chiers e ee texte, toujours ouverts et sans n ; ils sont dsigns par les variables prdnies input e e e e et output (dont on ne se sert quasiment jamais).
1.1
La procdure write() permet dacher un ou plusieurs param`tres. writeln() e e fait la mme chose puis rajoute un saut de ligne. e Trois critures quivalentes : e e
writeln (a, b, c, d); write (a, b, c, d); writeln; write(a); write(b); write(c); write(d); writeln;
ache :
12|A|TRUE|2.300000E+01|toto
Formatter limpression des variables 1) Soit v un entier, un boolen, un caract`re ou un string. e e write(v:8) dit a write dacher v sur au moins 8 caract`res. ` e Si le nombre de caract`res (signe ventuel compris) est > 8, v est compl`tement e e e ach ; si il est < 8, des espaces sont rajouts a gauche pour complter. e e ` e
Cours
45
Ainsi writeln (e:5, |, c:3, |, b:5, |, s:6); 12| A| TRUE| toto ache : 2) Soit r un rel. e write(r:10); dit a write dacher r en notation scientique, sur au moins 10 ` caract`res, signes de la mantisse et de lexposant compris. e Cette fois cest dabord le nombre de chires apr`s la virgule qui change de 1 a e ` 10, puis au besoin des espaces sont ajouts a gauche. e ` De plus le dernier chire de la mantisse ache est arrondi. e
r := 2 / 3; writeln (r:8, |, r:10, |, r:18 );
ache :
6.7E-01| 6.667E-01|
6.6666666667E-01
3) Autre formattage de r rel. e write(r:8:4); dit a write dacher r en notation simple, sur au moins 8 ca` ract`res, dont 4 chires apr`s la virgule (le dernier tant arrondi). e e e Ainsi writeln (r:8:4); ache : 0.6667 Bilan Le formattage permet daligner des chires. Ne pas oublier de mettre des espaces autour des variables pour que le rsultat e ne soit pas tout aglutin et illisible. e On ne peut acher que des types simples.
1.2
La procdure read() permet de lire un ou plusieurs param`tres. readln() fait e e la mme chose puis fait un readln; e Trois critures quivalentes : e e
readln (a, b, c, d); read (a, b, c, d); readln; read(a); read(b); read(c); read(d); readln;
Remarques ` A lexcution dune de ces lignes, on peut rentrer les donnes en les sparant e e e par des espaces, des tabulations ou des retours chariot . Il faut que les donnes lues correspondent au type attendu de chaque variable, e sinon il y a une erreur a lexcution. ` e Le comportement de read() et readln; tant complexe, regardons plus en dtail e e se qui se passe a lexcution. ` e
46
Edouard Thiel
Lutilisateur tape une srie de caract`res, avec de temps a autres des retours e e ` chariot . Pendant la frappe, les caract`res sont stocks dans un buer (une mmoire e e e tampon) ; a chaque , le contenu du buer est envoy au programme Pascal ` e (y compris le ). De son ct, read(v); lit une donne dans le buer, ou attend le buer suivant. oe e Le read(v); attend donc quand on na pas tap de , e ou quon a tap une ligne vide, e ou que toutes les donnes dans le buer ont dj` t lues. e eaee readln; attend le prochain , puis vide le buer. Attention les donnes non e lues dans le buer sont alors perdues pour de futurs read(). Exemple
VAR a, b, c, d : integer; BEGIN readln (a, b); { = read(a); read(b); readln; } readln (c, d); writeln (Lu : , a, , b, , c, , d); END.
Essais :
1 2 3 4 Lu : 1 2 3 4 1 2 3 4 Lu : 1 2 3 4 idem
12 34 Lu : 1 2 3 4
Le mme programme avec read (a, b, c, d); readln; e 12 34 Lu : 1 2 3 4 idem 123 456 Lu : 1 2 3 4 5 et 6 perdus
produit :
Remarque Le type des objets lus a une grande importance pour read(). Dans notre programme exemple, voici ce qui se passe si on dclare les 4 variables e en char : VAR a, b, c, d : integer; VAR a, b, c, d : char; 1 2 3 4 1 2 3 4 Lu : 1 2 3 4 Lu : 1 2 Remarque
Cours
47
On ne peut faire un read() que sur un entier, un rel, un caract`re ou une cha e e ne de caract`res ; on ne peut pas faire un read() sur un boolen. e e Algorithme de lecture dune suite de caract`res taps au clavier, se terminant par e e un . Option on ache le code ASCII de chaque caract`re. e
CONST CarFin = .; VAR c : char; BEGIN read(c); while c <> CarFin do begin writeln (c, , ord(c)); read(c); end; readln; END.
{ premier caract`re } e { option } { caract`re suivant } e { lu a la fin du while } ` { vide buffer et retour chariot }
t 116 13 10 Ciao.bye
C i a o
67 105 97 111
Fichiers de disque
Les chiers de disque permettent de stocker des informations de mani`re permae nente, sur une disquette ou un disque dur. Ces informations persistent mme lorsque lordinateur est teint. e e Linconvnient est que ces donnes ne sont pas en mmoire vive ; on ny acc`de e e e e pas directement, comme cest le cas avec un vecteur. En fait on va lire ou crire des donnes une a une sur le disque, tant donn quil e e ` e e sagit de chiers squentiels. e
2.1
Notions gnrales e e
Sur un disque, un chier a un nom, par exemple a :\mass\tp4.pas On peut coder ce nom dans un string, par exemple nomf. Dans un programme qui doit manipuler ce chier, il faut une variable pour le dsigner, par exemple f. e Droulement des oprations e e a) Dclarer la variable f e f : text ; ou f : file of qqchose ;
48
Edouard Thiel
b) Assigner la variable f au chier de nom nomf assign (f, nomf) ; c) Ouvrir le chier f pour pouvoir y lire ou y crire les donnes e e reset (f) ; ou rewrite (f) ; d) Lire ou crire des donnes e e read (f, donnee) ; ou write (f, donnee) ; e) Quand on a ni, on ferme le chier close (f) ; Lecture ou criture e On ouvre un chier soit en lecture, soit en criture. On ne peut pas faire les deux e en mme temps. e En lecture : on fait reset(f); puis des read(f, ...); Si le chier nexiste pas, il y a une erreur. En criture : on fait rewrite(f); puis des write(f, ...); e Si le chier nexiste pas, un rewrite le cre. Si il existe dj`, le rewrite lcrase, e ea e cest-`-dire que lancien contenu est dnitivement perdu. a e Fin du chier En lecture, avant de faire un read, il faut tester si il y a encore quelque chose a ` lire ; on na pas le droit de faire un read si la n du chier est atteinte. La fonction eof(f) retourne true si la n du chier est atteinte. Deux familles de chiers On distingue les chiers de texte des chiers dlments. ee
2.2
Fichiers de texte
Les chiers de textes sont les chiers que vous pouvez diter, comme par exemple e vos chiers pascal. Dclaration e
VAR f c s x r : : : : : text; char; string[255]; integer; real;
Lecture read (f, c); lit un caract`re dans f. e readln (f, s); lit une ligne compl`te dans f (toujours readln sur un string). e read (f, x); lit un entier dans f. On peut de la mme mani`re lire un rel. e e e Ecriture
Cours
49
write (f, c) ; crit un caract`re dans f. e e write (f, s); crit le string dans f. Pour passer a la ligne on fait writeln(f); e ` write (f, x, ); crit un entier dans f. On peut de la mme mani`re crire e e e e un rel ou un boolen. Il vaut mieux rajouter un espace (ou un retour chariot) e e apr`s chaque donne pour que lors dune relecture ultrieure, les donnes ne soit pas e e e e accoles en un bloc illisible. e write (f, r:8:2); crit un rel formatt dans f. e e e Morale En lecture comme en criture, la manipulation des chiers texte se passe tr`s e e naturellement, de la mme faon que la lecture au clavier ou lcriture a lcran. e c e ` e Tous les algorithmes de lecture vus en TD (Horner, compter les LE) sont directement applicables sur les chiers texte. En fait, le clavier et lcran sont tout simplement considrs comme des chiers e ee texte, les chiers input et output.
2.3
Fichiers dlements e
Les chiers dlments sont des copies de la mmoire vive, les lments tant tous ee e ee e du mme type. e Le type dlment peut tre un type simple, un enregistrement, un tableau, etc. ee e Dclaration e
TYPE element_t = record age : integer; majeur : boolean; end; VAR f : file of element_t; e : element_t;
Lecture read (f, e); lit un lment dans f. On ne fait jamais de readln. ee Ecriture write(f, e); crit un lment dans f. On ne fait jamais de writeln. e ee Schmas types e Mettre un vecteur vec de nb lments dans un chier. ee
VAR vec : array [1..vmax] of element_t; nb, i : integer; BEGIN assign (f, nomf); rewrite (f); for i := 1 to nb do write (f, vec[i]);
50
Edouard Thiel
2.4
Louverture dun chier peut provoquer une erreur, qui plante le programme. Par exemple, si on veut ouvrir un chier en lecture, ce chier doit exister. Si on veut crer un chier, le chemin du chier doit tre valide. e e Chaque compilateur fournit sa propre mthode pour viter un plantage. Sous e e Delphi et sous Turbo Pascal, on encadre reset ou rewrite entre 2 options de compilations spciales : e {$I-} dsactive temporairement le contrle des entres/sorties e o e {$I+} le rtablit. e Juste apr`s on regarde si il y a eu une erreur en testant la variable IoResult. e e Exemple En criture
BEGIN assign (f, nomf); {$I-} rewrite (f); {$I+} ok := IoResult = 0; if not ok then writeln (Erreur cration fichier , nomf) e else begin ... write (f, ...); ... close (f); end; END;
Exemple En lecture
Cours
BEGIN assign (f, nomf);
51
{$I-} reset (f); {$I+} ok := IoResult = 0; if not ok then writeln (Erreur lecture fichier , nomf) else begin ... while not eof(f) do begin read (f, ...); ... end; ... close (f); end; END;
Remarque On peut aussi utiliser IoResult dans la lecture au clavier, en encadrant read entre {$I-} et {$I+}. Par exemple lorsquon attend un rel et quune lettre est tape, le programme, e e au lieu de planter, dtectera lerreur et pourra redemander une frappe. e
52
Edouard Thiel
Soit v un vec_t de vn lments (1 vn VMax). ee On veut crire une fonction boolenne qui dit si un entier x se trouve dans le e e tableau v.
1.1
On parcourt le tableau et on sarrte d`s que x est trouv ou que la n du tableau e e e est atteinte. Premi`re implmentation e e
FUNCTION cherche1 (v : vec_t; vn, x : integer) : boolean; VAR i : integer; BEGIN i := 1; while (i <= vn) and (v[i] <> x) do i := i+1; cherche1 := i <= vn; END;
On sort du while dans deux situations : Si i > vn, on a parcouru tout le tableau sans trouver x. Sinon i <= vn et v[i] = x : on a trouv x. e On ne peut donc pas crire comme rsultat cherche1 := v[i] = x puisque i e e peut sortir du tableau ; cest pourquoi on crit cherche1 := i <= vn. e Il y a un probl`me : dans le while, lexpression (i <= vn) and (v[i] <> x) e est toujours compltement value, mme si le premier terme est faux. e e e e En eet, le and ne signie pas et sinon , comme dans dautres langages. La consquence est que si x nest pas dans v, a la derni`re itration on valuera e ` e e e (vn+1 <= vn) and (v[vn+1] <> x) et on sortira du vecteur ! ! Implmentation a viter absolument. e `e Deuxi`me implmentation avec un boolen e e e On va dcomposer le test dans le while. e
Cours
53
FUNCTION cherche2 (v : vec_t; vn, x : integer) : boolean; VAR i : integer; continuer : boolean; BEGIN i := 1; continuer := true; while continuer do if i > vn then continuer := false else if v[i] = x then continuer := false else i := i+1; cherche2 := i <= vn; END;
Troisi`me implmentation e e
FUNCTION cherche3 (v : vec_t; vn, x : integer) : boolean; VAR i : integer; BEGIN i := 1; while (i < vn) and (v[i] <> x) do { i < n strict } i := i+1; cherche3 := v[i] = x; END;
On sort toujours du while avec i <= vn, donc on ne sort jamais du tableau. Par contre pour le rsultat, il faut changer le test, et on a le droit dcrire e e cherche3 := v[i] = x. e e Le cot Le vecteur v tant non tri, il faut u vn itrations si x v. e vn/2 itrations en moyenne si x v. e
1.2
Lorsquon parle de vecteur tri, on suppose toujours que les vecteurs sont tris e e par ordre croissant : i, v[i] v[i + 1]. On parcourt le tableau et on sarrte d`s que : e e x est trouv e ou la n du tableau est atteinte ou v[i] > x : ca veut dire que tous les lments qui suivent seront plus grands ee que x, inutile de continuer. On peut adapter facilement la mthode 3 : e
FUNCTION cherche4 (v : vec_t; vn, x : integer) : boolean; VAR i : integer; BEGIN i := 1;
54
Edouard Thiel
strict }
Le cot Le vecteur v tant tri, il faut en moyenne vn/2 itrations, que x appartienne u e e e ou non a v. `
La dichotomie
Prenons lexemple du correcteur orthographique dans un traitement de texte, utilis pour corriger une lettre. e Le dictionnaire du correcteur contient tous les mots de la langue, orthographis e de toutes les faons possibles, soit par exemple 1 million dentres. c e Avec la recherche squentielle sur un dictionnaire tri, il faudra donc en moyenne e e 500 000 itrations pour trouver un mot ! e Mettons que le texte a corriger fasse 2000 mots. Il faudra donc 2000 500 000 = 1 ` milliard ditrations pour corriger le texte ! e Sachant quen plus, la comparaison de deux mots est nettement plus lente que la comparaison de 2 entiers, la correction va durer plusieurs jours ! ! Cest tout a fait ` inacceptable. Pour acclrer les choses, on va sinspirer du jeu des 1000 francs. ee
2.1
Jeu1 Lordinateur choisit un prix secret entre 1 et 1000 F, et le joueur doit le deviner en un nombre minimum de coups.
PROCEDURE jeu1 (secret : integer); VAR n, essai : integer; continuer : boolean; BEGIN continuer := true; n := 1; while continuer do begin write (Essai , n, : ); readln (essai); if essai < secret then writeln (+) else if essai > secret then writeln (-) else begin writeln (Gagn en , n, coups); e continuer := false; end; n := n+1; end; END;
Ce qui nous intresse cest la stratgie du joueur : admettons que secret = 326. e e
Cours Essai 500 250 375 312 343 328 321 324 326
Deug 1 Mass MA, 1997 a 2004 ` Rponse e + + + + Gagn e Intervalle possible 1500 250500 250375 312375 312343 312328 321328 324328
55
La solution est trouve en seulement 9 coups ! e Cest le principe de la dichotomie : on a un intervalle de possibilits, et a chaque e ` itration on rduit de moiti la taille de cet intervalle. e e e De la sorte, le nombre maximum ditration est log2 vn, cest a dire 10 pour vn = e ` 1000, de 20 pour vn = 1 million. e Jeu2 La rciproque : lutilisateur choisit un prix secret entre 1 et 1000 F, et lordinateur doit le deviner en un nombre minimum de coups. Le programme va donc grer un intervalle de possibilits, cest-`-dire un dbut et e e a e une n, proposer le milieu de lintervalle, puis changer lintervalle en fonction de la rponse. e La recherche dichotomique consiste a faire la mme chose sur les indices, et est ` e donc tr`s performante : sur lexemple du correcteur orthographique, il faudra 20 e itrations pour trouver un mot, donc 40 000 itrations pour corriger tout le texte, ce e e qui est quasiment instantann. e
2.2
Recherche dichotomique
La dichotomie se fait toujours sur un vecteur tri. e Cela consiste a considrer une certaine plage de recherche inf..sup sur le vecteur, ` e plage que lon rduit dun facteur 2 a chaque itration. e ` e Au dpart, la plage de recherche est tout le vecteur. e ` A une itration donne, on a une plage [inf..sup] e e et son milieu est m := (inf + sup) div 2. On a donc la subdivision : [inf..m-1], [m], [m+1..sup]. Soit v[m] = x et on a ni. Soit v[m] < x, donc x [inf..m] et la nouvelle plage sera [m+1..sup]. Soit v[m] > x, donc x [m..sup] et la nouvelle plage sera [inf..m-1]. On implmente lalgorithme avec un boolen trouve. e e
56
Edouard Thiel
Remarque Le fait de prendre m-1 ou m+1 nest pas une simple optimisation, mais est essentiel pour que lalgorithme se termine. Le cot Il faut u log2 vn itrations si x v. e log2 vn itrations au plus si x v. e On peut amliorer lecacit dans le cas o` x v : e e u
BEGIN trouve := false; if (v[1] <= x) and (x <= v[vn]) then begin inf := 1; sup := vn; while {...} end; cherche6 := trouve; END;
Soit v[1..vn] un vecteur non tri. Nous voulons construire un vecteur w[1..vn] e qui contienne les mme lments que v, et qui soit tri. e ee e Il existe de tr`s nombreuses mthodes de tris, qui sont plus ou moins faciles a e e ` implmenter, et dont certaines sont nettement plus ecaces que dautres. e Dans certaines mthodes on peut se passer du second vecteur w, en travaillant e directement sur v o` seront permuts des lments. u e ee
Cours
57
3.1
La mthode consiste a slectionner des minimums successifs dans v, et a les ranger e ` e ` au fur et a mesure dans w. ` Au dpart on recherche quel est le max. e ` A chaque pas : on cherche min(v) on le met au bout de w on le remplace dans v par max(v) e Exemple Trier dans lordre alphabtique les lettres du mot ETABLES. Le max est la lettre T. i 1 2 3 4 5 6 7 v ETABLES ETTBLES ETTTLES TTTTLES TTTTLTS TTTTTTS TTTTTTT indice du min dans v 3 4 1 6 5 7 ni w tri e A AB ABE ABEE ABEEL ABEELS ABEELST v apr`s e remplacement ETTBLES ETTTLES TTTTLES TTTTLTS TTTTTTS TTTTTTT
FUNCTION maximum (v : vec_t; vn : integer) : char; VAR i : integer; m : char; BEGIN m := v[1]; for i := 2 to vn do if v[i] > m then m := v[i]: maximum := m; END; FUNCTION ind_min (v : vec_t; vn : integer) : integer; VAR i, j : integer; BEGIN j := 1; for i := 2 to vn do if v[i] < v[j] then j := i: ind_min := j; END; PROCEDURE tri_remplacement ( VAR max : char; i, j : integer; BEGIN { recherche du max } max := maximum (v,vn); v : vec_t; vn : integer; var w : vec_t );
58
Edouard Thiel
Le cot u Les performances sont faibles : il y a environ vn2 comparaisons, et 2, 5 vn aectations en moyenne. Par exemple si vn = 1000, on aura 1 000 000 de comparaisons et 2500 aectations.
3.2
Dans la mthode prcdente, la place occupe est double ; on peut viter de crer e e e e e e un nouveau vecteur en travaillant directement sur v. Principe On est a ltape i. ` e Supposons dj` tri v[1..i-1], et non trait v[i..vn]. ea e e On cherche le min dans v[i..vn] On le permute avec v[i]. Maintenant v[1..i] est tri. e Exemple Trier les lettres du mot ETABLES. i 1 2 3 4 5 6 7 v tri / e non trait e /ETABLES A/TEBLES AB/ETLES ABE/TLES ABEE/LTS ABEEL/TS ABEELS/T indice du min 3 4 3 6 5 7 lettres a ` permuter E et A T et B non T et E non T et S ni v apr`s e permutation A/TEBLES AB/ETLES ABE/TLES ABEE/LTS ABEEL/TS ABEELS/T ABEELST/
Le cot u Les performances sont meilleures que le tri par remplacement : il y a environ vn2 / 2 comparaisons, et vn / 2 permutations en moyenne. Par exemple si vn = 1000, on aura 500 000 comparaisons et 1500 aectations.
Cours
59
3.3
Tri ` bulles a
Cest une variante du tri par permutation, un peu moins ecace ; il y a une version optimise qui est un peu meilleure que le tri par permutation. e ` e Principe On est a ltape i. Supposons dj` tri v[1..i-1], et non trait v[i..vn]. ea e e On parcourt v[i..vn] en descendant et, chaque fois que deux lments consee e cutifs ne sont pas dans lordre, on les permute. En n de parcours le min de v[i..vn] se retrouve dans v[i]. Maintenant v[1..i] est tri. e Le nom du tri a bulles vient de ce que a chaque tape i, les lments les plus ` ` e ee lgers remontent vers la surface, sont transports a gauche. e e ` On constate aussi que a chaque tape, lordre gnral est accru. ` e e e Tri a bulles optimis ` e Si lors dune tape i, aucune permutation na lieu, cest que [i..vn] est dj` e ea dans lordre, et le tri est ni. boolen apermute ou encore mieux, indice dp de derni`re permutation. e e
3.4
Cette mthode consiste a construire un vecteur dindices ind, o` lon calcule la e ` u position que devrait avoir chaque lment pour que le vecteur soit tri. ee e Exemple Rsultat sur le tri des lettres du mot ETABLES. e i v ind w
PROCEDURE tri_comptage (
1 E 3 A
2 T 7 B
3 A 1 E
4 B 2 E
5 L 5 L
6 E 4 S
7 S 6 T
VAR i, k : integer; ind : array [1..VMax] of integer; BEGIN { init } for i := 1 to vn do ind[i] := 1; { construit ind } for i := 1 to vn-1 do for k := i+1 to vn do if v[k] < v[i] then ind[i] := ind[i]+1 else ind[k] := ind[k]+1;
60
Edouard Thiel
Le cot u La place occupe est importante (3 vecteurs). e Le nombre de comparaisons est constant (vn (vn 1)/2). Cest du mme ordre e que le tri par permutation ou a bulles non optimis. ` e Il y a tr`s peu daectations (vn) ; cela est tr`s intressant si les lments de vn e e e ee sont lourds , par exemple des strings ou des records tris sur un champ. e
On regarde comment insrer ou supprimer un lment de v, en conservant lordre e ee ou non des lments. ee
4.1
Si on veut insrer x a une autre position, cest que lon consid`re que le vecteur e ` e est tri avec un certain ordre (croissant, dcroissant, dapparition, etc). e e
4.2
On veut insrer x a la position i dans v, avec 1 i vn. e ` On doit dcaler v[i..vn] vers la droite : e
if vn < VMax then begin vn := vn+1; for j := vn downto i+1 do v[j] := v[j-1]; v[i] := x; end;
{ en descendant }
4.3
On veut supprimer llment v[i], avec 1 i vn. ee Si lordre des lments dans v est indirent, on place llment de queue dans le ee e ee trou.
v[i] := v[vn]; vn := vn-1; { si i = vn, ca ne fait rien }
Cours
61
4.4
` e Principe On est a ltape i. Supposons dj` tri v[1..i-1], et non trait v[i..vn]. ea e e On pose x = v[i]. La case i est disponible. On cherche k tel que v[k-1] x < v[k]. On ins`re x a la position k dans v[1..i-1], ce qui oblige a dcaler dabord e ` ` e v[k..i-1] vers v[k+1..i] ; le trou en i est bouch. e Maintenant v[1..i] est tri et v[i+1..vn] est non trait. e e Exemple Trier les lettres du mot ETABLES. Au dpart, on consid`re que v[1..1] est tri ; on va donc insrer les lments e e e e ee suivants, de 2 a vn. ` i 2 3 4 5 6 7 Implmentation du tri e
PROCEDURE tri_insertion ( var v : vec_t; vn : integer); VAR i : integer; BEGIN for i := 2 to vn do insrer_tri (v, i); e e END;
lettre a ` insrer e T A B L E S
Implmentation de linsertion e
62
Edouard Thiel
Optimisation de la recherche du point dinsertion La recherche du point dinsertion k peut se faire squentiellement ; mais on a tout e intrt a employer une recherche dichotomique, bien plus ecace. ee `
FUNCTION posit_ins ( var v : vec_t; i : integer; x : type_element) : integer; VAR inf, sup, m : integer; BEGIN { le cas des extrmits } e e if x < v[1] then posit_ins := 1 else if v[i-1] <= x then posit_ins := i else begin { init dichotomie : les cas 1 et i sont dj` traits } e a e inf := 2; sup := i-1; { recherche position m tel que v[m-1] <= x < v[m] } { : variante de la dichotomie habituelle, } { sans le boolen trouve e } while inf < sup do begin m := (inf + sup) div 2; if v[m] <= x then inf := m+1 else sup := m; end; posit_ins := sup; end; END;
Le cot u Mthode nettement plus ecace que les autres pour vn grand : e La recherche dichotomique sur v[1..i] est en log 2 i. Linsertion dans v[1..i] coute en moyenne i/2. Le cot total est donc vn (log2 i + i/2). u 2 Par exemple avec vn = 1000, le cot est de 10 000, contre 500 000 pour les autres u tris.