Vous êtes sur la page 1sur 30

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Introduction au langage Pascal

Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Contents
1 Commenons par un petit exemple... c 2 La partie des dclarations e 2.1 Les dirents types de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 2.2 Les oprations qui prservent le type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e e 2.3 Les oprations qui rendent un type boolean . . . . . . . . . . . . . . . . . . . . . . . . . . e 3 La partie algorithme 3.1 Interface avec lutilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Les aectations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Contrle de ux o 4.1 Excution conditionnelle . . . . . . e 4.2 Les blocs dinstructions . . . . . . 4.3 Les boucles sur des types numrs e e e 4.4 Les boucles while et repeat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 4 4 4 5 6 6 6 7 7 8 9 11 13 13 13 14 15 15 15 15 16 17 17 17 17 19 21 21 22 22 23 24 28 30

5 Dautres types 5.1 Types numrs non standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e e e 5.2 Les types intervalles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Linstruction CASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Les 6.1 6.2 6.3 6.4 tableaux Les tableaux de tableaux . Les types de tableaux . . Les cha nes de caract`res . e Les constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 Fonctions et procdures e 7.1 Introduction . . . . . . . . . . . . . . . 7.2 Dclaration des fonctions, ranement e 7.3 Les procdures . . . . . . . . . . . . . e 7.4 Les fonctions . . . . . . . . . . . . . .

8 Algorithmes rcursifs e 8.1 Des exemples bien connus . . . . . . . . . . . . . . . . 8.2 Arrt dune fonction rcursive . . . . . . . . . . . . . . e e 8.2.1 Le probl`me . . . . . . . . . . . . . . . . . . . . e 8.2.2 Graphe de dpendance dune fonction rcursive e e 8.2.3 Fonctions mutuellement dnies . . . . . . . . e 8.2.4 Taille en mmoire lors dun calcul rcursif . . . e e 9 Conclusion : Forme dun programme Pascal

Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Commenons par un petit exemple... c


REAL;

PROGRAM circonference; VAR rayon, circonference :

BEGIN readln(rayon); circonference:=rayon*2*3.1416 ; writeln(rayon,circonference); END. Ce programme demande a un utilisateur de taper un nombre, et il rend ce nombre et la circonfrence e dun cercle dont ce nombre est le rayon. Ce nest pas trop compliqu. On peut tout de suite identier e les parties les plus importantes. Il y a dabord le squelette du programme : PROGRAM ... ; (* Calcul de la circonference dun cercle *) VAR .... ; BEGIN ... END. 1. La partie PROGRAM...; sert ` donner un nom au programme ; a 2. la partie (*...*) sert ` donner des commentaires. Ils sont essentiels pour comprendre ce que fait a un programme. Ils ne sont pas facultatifs ; 3. la partie VAR...; sert ` dclarer les variables dont on aura besoin plus tard ; a e 4. la partie BEGIN ... END. contient ce que le programme fait. Cest la partie qui contient lalgorithme. Elle se termine par un point .. Cest la partie algorithme du programme. On va maintenant voir plus en dtail ces direntes parties. Je ne reviens pas sur le nom du proe e gramme.

Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

2
2.1

La partie des dclarations e


Les dirents types de base e
REAL;

VAR rayon, circonference :

On dclare que dans lalgorithme, on utilise deux variables, quon appelle rayon et diametre. En e plus, on dclare que ces deux variables sont de types REAL. Cela signie quon pourra les utiliser un peu e comme des nombres rels. Mais il y a dautres types qui sont dnis : e e 1. le type integer. Il sagit du type des nombres qui sont des entiers relatifs ; 2. le type boolean. Il sagit du type des boolens. Ces variables ne peuvent prendre que 2 valeurs, e TRUE (vrai) ou FALSE (faux) ; 3. le type char. Il sagit du type qui contient les caract`res. Une variable de ce type peut avoir la e valeur A, b, 7,... Le 7 dune variable de type char est un caract`re. Il nest pas question de e faire des oprations dessus ! e

2.2

Les oprations qui prservent le type e e

On utilise le type dune expression pour savoir quelles oprations on peut appliquer. e Sur les types de nombres, on a toujours +, -, et *. Question : que signie 3/5 ? (division euclidienne ou relle ?) e On voit que la division ne voudra pas dire la mme chose pour les integer et pour les real. e Pour les integer, on utilise la division euclidienne. Autrement dit, on spare en reste et en partie e entiere. Par exemple, 17 = 3 5 + 2. Sur les entiers, on dnit les 2 oprations div et mod, qui auront e e pour valeur : 1. 17 mod 3 a pour valeur 2 ; 2. 17 div 3 a pour valeur 5. Pour les real, on utilise le symbole standard de division, /. Il ny a pas de surprises. Il est possible de faire des oprations mlant des real et des integer. Dans ce cas, les deux oprandes sont considrs e e e e e de type real. Sur les caract`res, il ny a pas doprations possibles. Mais ils sont cods dans le code ASCII. Il faut e e e faire attention, car tous les caract`res ny sont pas, il ny en a que 256. Lintrt est quil est possible de e e e passer dun entier entre 0 et 255 ` un caract`re, en utilisant la fonction CHR. Par exemple, on a : a e CHR(67) prend la valeur C ; CHR(51) prend la valeur 3. Sur les boolens, on a les oprations classiques de logique, AND, OR, NOT, ainsi que lopration XOR. e e e

Exercice : Donner une expression utilisant x, y, not , and et or qui rend le mme rsultat que lopration x e e e xor y.

Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

x\y false true

false false true x OR y

true true true

x\y false true

false false false x AND y

true true true

x not x false true true false not x

x\y false true

false true false true true false x XOR y

Figure 1: les oprations boolennes e e

2.3

Les oprations qui rendent un type boolean e

Il y a ii toutes les oprations de comparaison <, >, <=, >= et <> (dirent). On compare entre elles c e e deux expressions dun mme type, si ce type peut tre ordonn. Il est aussi possible de comparer des e e e expressions de type real avec des expressions de type integer. Pour les caract`res, on utilise lordre du e code ASCII. Par exemple : CHR(60) < CHR(49) rend false ; 3.5 >= 3 rend true ; 3.0 <> 3 rend false.

Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

La partie algorithme

Il sagit de la partie o` est dni lalgorithme. On va ltudier un peu plus en dtail. Cette partie est u e e e compose dinstructions qui sont spares par des point-virgules. e e e readln(rayon); circonference:=rayon*2*3.1416 ; writeln(rayon,circonference); Il est obligatoire de mettre le point-virgule entre chaque instruction. Le dernier point-virgule, lui, nest pas obligatoire. Le mettre revient ` ajouter une instruction vide. Il faut noter quon peut mettre a autant dintructions vides ` la suite quon le dsire. a e

3.1

Interface avec lutilisateur


readln(rayon); ... writeln(rayon,circonference);

Les deux commandes :

servent ` interagir avec lutilisateur du programme. a readln est utilise pour ligne une donne entre par lutilisateur, et quil valide en appuyant sur la e e e touche return. Lutilisateur doit donner une valeur qui correspond au type attendu. Si ce nest pas le cas, le programme sarrte. Quelques exemples de valeurs possibles : e pour un integer : 3, 5, 17, . . . mais pas 3.5 ou A ; pour un real : 4, 3.5, 45.74e 1, .07, . . . mais toujours pas A ; pour un boolean : il nest pas possible de les demander directement ` lutilisateur. Par contre, il a est toujours possible de les crire ; e pour les char : 3, A, , `,. . . , mais pas AA. e

3.2

Les aectations

Il reste une derni`re instruction ` voir, laectation : e a circonference:=rayon*2*3.1416 ; ` Cette instruction est dnie par :=. A droite de ce signe, il y a une expression : e ...:=rayon*2*3.1416 ` qui rend une valeur de type real. A gauche de ce signe circonference:=... il y a le nom dune variable de mme type, real. Cette instruction stocke la valeur ` droite dans la e a variable ` gauche. Lorsque, ` droite, on utilise la variable rayon, on va en fait utiliser la derni`re valeur a a e qui a t stocke dans cette variable. ee e Il faut noter deux choses :
Yannick Chevalier

il y a un risque derreur si on utilise une variable dans laquelle rien na t stock. Il faut toujours ee e vrier quil y a une valeur de stocke dans la variable avant de lutiliser ; e e les types ` gauche et ` droite de laectation doivent toujours tre les mmes, sauf si ` droite cest a a e e a une expression de type integer, et a gauche une variable de type real. `

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

4
4.1

Contrle de ux o
Excution conditionnelle e

On veut faire un programme qui donne, en sortie, la valeur absolue dun nombre que donne lutilisateur. Ce nombre est a priori de type real. Ce qui donne le squelette suivant pour ce programme : Program valeur absolue ; (* Ce programme calcule la valeur absolue dun nombre donne par un utilisateur. Les variables sont assez explicites *) nombre,valeurabsolue : real; begin writeln(De quel nombre voulez-vous la valeur absolue ?); readln(nombre); (* calcul de la valeur absolue *) writeln(La valeur absolue de ,nombre, est ,valeurabsolue); end. Il reste ` savoir comment calculer la valeur absolue. On sait que : a si nombre >= 0, la valeur absolue de nombre est nombre ; si nombre < 0, la valeur absolue de nombre est loppos de nombre. e Il y a une instruction, en Pascal, qui agit comme le si. Cest linstruction : if expr bool then inst e expr bool est une expression boolenne quon commence par calculer. Si elle vaut true, alors on excute linstruction inst. Sinon, on ne fait rien (cest comme si on avait utilis une instruction vide). Le e e programme devient : Program valeur absolue ; (* Ce programme calcule la valeur absolue dun nombre donne par un utilisateur. Les variables sont assez explicites. On utilise deux conditionnelles. *) Var nombre,valeurabsolue : real; begin writeln(De quel nombre voulez-vous la valeur absolue ?); readln(nombre); if (nombre >= 0) then valeurabsolue:=nombre ; if (nombre < 0) then valeurabsolue:=-nombre ; writeln(La valeur absolue de ,nombre, est ,valeurabsolue); end. Pour calculer la valeur absolue, on peut aussi utiliser la construction IF...THEN...ELSE.... Cette construction prend une expression de type boolean, et deux instructions. le programme excute la e premi`re si lexpression de type boolean vaut true, et la deuxi`me si lexpression vaut false : e e if expr bool then inst1 else inst2
Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Le programme devient alors : Program valeur absolue ; (* Ce programme calcule la valeur absolue dun nombre donne par un utilisateur. Les variables sont assez explicites On nutilise plus quune conditionnelle *) Var nombre,valeurabsolue : real; begin writeln(De quel nombre voulez-vous la valeur absolue ?); readln(nombre); if (nombre >= 0) then valeurabsolue:=nombre else valeurabsolue:=-nombre ; writeln(La valeur absolue de ,nombre, est ,valeurabsolue); end. On ne peut pas ajouter de point-virgules apr`s linstruction : e valeurabsolue:=nombre car on na le droit de mettre quune seule instruction apr`s le then et apr`s le else. Le point-virgule e e qui suit linstruction valeurabsolue:=-nombre signie la n de linstruction if...then...else....

4.2

Les blocs dinstructions

Cette limitation ` une seule instruction est tr`s vite gnante. Heureusement, on peut regrouper des a e e instructions qui vont ensemble en une seule instruction, quon appelle un bloc dinstructions. On regroupe les instructions avec la construction : begin inst1 ; . . . ; instn end Bien s r, la suite dinstruction peut tre vide, ou ne contenir que des instructions vides, ou encore u e tre une suite normale dinstructions. En reprenant le programme de calcul de valeur absolue, on a e maintenant :

Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Program valeur absolue ; (* Ce programme calcule la valeur absolue dun nombre donne par un utilisateur. Les variables sont assez explicites On illustre ici lutilisation de blocs dinstructions. *) Var nombre,valeurabsolue : real; begin writeln(De quel nombre voulez-vous la valeur absolue ?); readln(nombre); if (nombre = 0) then begin valeurabsolue:=nombre; writeln(Le nombre entr est positif,); e writeln(donc il est gal ` sa valeur absolue) e a end else begin valeurabsolue:=-nombre ; writeln(Le nombre entr est ngatif,); e e writeln(donc il est gal ` loppos de sa valeur absolue) e a e end; writeln(La valeur absolue de ,nombre, est ,valeurabsolue); end.

4.3

Les boucles sur des types numrs e e e

On parle de type numr pour dsigner un type dans lequel on peut donner tous les lments les uns ` e e e e ee a la suite des autres. Pour linstant, on en a vu deux, le type integer et le type char, mais on en verra dautres dans la suite du cours. Exercice : Acher toutes les lettres de A ` E (une lettre par ligne) a Pour rsoudre cet exercice, une premi`re mthode est dcrire le programme suivant : e e e e Program lettresAE; (* On ache les lettres de A ` E, une par ligne... a On na pas besoin de dclarer de variables. e *) begin writeln(A); writeln(B); writeln(C); writeln(D); writeln(E) end. On peut faire la mme chose en utilisant linstruction : e for < variable > := < minimum > to < maximum > do < instruction >

Yannick Chevalier

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

linstruction sera excute pour toutes les valeurs de la variable entre le minimum et le maximum e e dans lordre croissant. On appelle la variable indice de la boucle. Bien s r, cette instruction peut tre u e un bloc... Utilisons cette nouvelle construction : Program lettresAEboucle; (* On ache les lettres de A ` E, en utilisant une a boucle. *) Var lettre : char; begin for lettre := A to E do writeln(lettre) end. Exercice : Ecrire tous les mots de exactement 3 lettres cris avec les lettres de A ` E. e a Cette fois-i, ce serait un peu long dcrire les lignes ` la main (il y en a 125). c e a Program motstroislettres; (* On ache les mots de trois lettres en utilisant trois boucles les unes dans les autres. Il y a une boucle pour la premi`re e lettre, une pour la deuxi`me, une pour la troisi`me. e e *) Var lettre1, lettre2, lettre3 : char; begin for lettre1 := A to E do for lettre2 := A to E do for lettre3 := A to E do writeln(lettre1,lettre2,lettre3) end. Les boucles for sont utiles mais il faut prendre quelques prcautions quand on les utilise : e

1. il ne faut jamais changer la valeur de lindice dune boucle dans linstruction. Si il le faut, on utilisera une autre variable qui prend la valeur de lindice ; 2. La valeur de lindice est limite ` linstruction de la boucle. Cest une variable e a muette.

Ne pas suivre la premi`re r`gle peut donner un programme valide (qui marche bien), mais il y a des e e risques derreurs et il est possible de rendre le programme incomprhensible. Par exemple, que fait la e boucle for suivante :

Yannick Chevalier

10

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Program mauvaiseboucle; (* Exemple de programme o` on change le valeur de u lindice ` lintrieur dune boucle for a e *) Var lettre1, lettre2, lettre3 : char; begin for lettre1 := A to E do begin writeln(lettre1); lettre1:= A end.

end

Ces boucles sont ` utiliser d`s quil faut faire un mme traitement plusieurs fois sur un domaine ni, a e e et connu ` lavance. Mais il peut arriver quon ne sache pas, au dpart, combien de fois il faudra faire un a e traitement. Dans ce cas, il faut utiliser une autre construction.

4.4

Les boucles while et repeat

Un cas classique est le calcul dun point o` une fonction sannule par la mthode de Newton. On sarrte u e e d`s quon trouve une valeur dont limage est susament proche de 0. Mais on ne sait pas, au dpart, e e combien de ditration il faudra faire. e Calcul du zro dune fonction par la mthode de Newton e e a) Choisir une valeur x0 dans lintervalle [A, B] b) Tant que |f (xn )| > , calculer : xn+1 = xn f (xn ) f (xn )

f(x n )

xn

xn+1
Yannick Chevalier

Figure 2: Calcul de xn+1 en fonction de xn : on calcule xn+1 comme le point dintersection de la tangente en (xn , f (xn )) ` la courbe y = f (x) avec la droite dquation y = 0 a e Chaque fois quon doit faire un calcul tant quune condition est vrie, on utilise une boucle while : e e while < condition > do < instruction >

11

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Lorsquon utilise cette boucle, le programme fera, dans cet ordre : 1. (a) tester si la condition est vraie ; (b) si elle est vraie, faire linstruction, sinon, passer ` linstruction suivante. a 2. (a) tester si la condition est vraie ; (b) si elle est vraie, faire linstruction, sinon, passer ` linstruction suivante. a 3. ... Bien s r, il y a des cas o` on ne sortira jamais de la boucle (penser ` une fonction qui ne sannule u u a pas). Il nexiste pas de moyen gnral permettant dassurer quon sortira de la boucle. Il faut donc tre e e e s r quon sarrtera un jour avant de commencer une telle boucle. u e Il existe une autre instruction qui fait presque la mme chose : e repeat < instruction1; . . . ; instructionN > until < condition > Il y a quelques dirence entre cette construction et la construction while : e on remarque quil peut y avoir, dans ce cas, plusieurs instructions. Il nest donc pas utile dutiliser un bloc begin...end; On commence par faire les instructions avant de tester la condition. Et on recommence jusqu` a ce que cette condition soit vraie (dans la boucle while , on recommence tant que la condition est vraie).

Yannick Chevalier

12

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Dautres types

Un type dni un ensemble dobjets, les lments de ce type. Pour linstant, on a vu ce quon pourrait e ee appeler les types mathmatiques. Ce sont ceux qui sont dnis en Pascal. Mais on a aussi vu le type e e char, qui sapplique ` des objets nayant pas de fortes proprits. a ee On va voir quon peut ajouter des types ` ceux dnis par dfaut dans Pascal. Cela permet plus de a e e prcision dans le nommage des variables. e

5.1

Types numrs non standards e e e

Lexemple classique est celui des jours de la semaine. Pour les utiliser dans un programme Pascal, on peut faire une table : lundi = 0 mardi = 1 ... et de dclarer les variables qui contiendront des jours de la semaine comme des entiers. Mais Pascal e nous ore beaucoup mieux, puisquil permet de dnir le type JOUR, un peu comme il existe dj` le e ea type entier : TYPE jour = (lundi,mardi, mercredi,jeudi,vendredi,samedi,dimanche) Cest ce quon appelle un type numr : on peut donner la liste des valeurs possibles les unes apr`s e e e e les autres. Les autres types numrs dj` dnis sont les boolean, les char, mais aussi les integer. e e e ea e Tous ces types se comportent comme des entiers, et la dclaration quon a faite plus haut est traduite e sous la forme lundi = 0, mardi = 1 et ainsi de suite. Lavantage est quil existe des fonctions dnies sur e tous les types numrs : e e e la fonction ORD, qui donne le numro dans la liste de dclaration (ord(mardi)=1, on commence ` e e a 0) ; les fonctions SUCC et PRED, qui donnent le successeur et le prdcesseur dans la liste : succ(mardi) e e = mercredi, pred(samedi)=vendredi. Attention, pred(lundi) et succ(dimanche) ne sont pas dnis. On ne sait pas ce quils valent ; e les oprateurs de comparaison ; e les boucles for ; Il faut faire attention, les fonctions readln et writeln ne marchent pas avec ces types.

5.2

Les types intervalles

` A partir de lexemple du type jour, on maintenant besoin davoir tous les jours de travail. On peut dnir (apr`s avoir dni le type jour) le type jourtravail. Ce sont les jours entre lundi et vendredi e e e (dans lintervalle [lundi, vendredi]). On note les intervalles avec ... On peut alors dclarer les jours e de travail : type jourtravail=lundi..vendredi
Yannick Chevalier

On peut aussi dnir les minuscules : e type minuscule =a..z ou toute autre sorte de type...

13

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

5.3

Linstruction CASE

Souvent, avec les types numrs, on veut faire un traitement qui dpend de la valeur. Pour cela, on e e e e peut bien s r utiliser des instruction if , mais cela ` tendance ` rendre le programme plus lourd que u a a ncessaire. Lorsquon veut fair eun traitement par cas, il y a une instruction beaucoup plus pratique, e linstruction case : CASE <expression> OF listedecas1 : instruction1 ; listedecas2 : instruction2 ; ... listedecasN : instructionN On a une liste de un cas : plusieurs types : une instruction spare par des ;. Les listedecas peuvent tre de e e e

1. une valeur, par exemple mardi ; 2. une liste de valeurs, spares par des virgules. Pour reprendre lexemple prcdent, on peut choisir e e e e samedi,lundi ; 3. un intervalle : jeudi..samedi. Exercice : Faire un programme qui prend un caract`re un entre, et qui dit si ce caract`re est une lettre minuscule, e e e majuscule, un chire ou autre chose.

Yannick Chevalier

14

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Les tableaux

Il sagit de la construction la plus importante dans un langage de programmation. Sans les tableaux, on ne peut pas faire grand chose. Un tableau sert ` rassembler des valeurs du mme type, et ` les organiser a e a pour pouvoir acc`der ` chaque valeur. En mathmatiques, cest la mme chose que des vecteurs ou des e a e e matrices. Un tableau, cest une suite de cases contenant des valeurs. Pour dnir un tableau, il faut deux choses : e 1. son domaine, qui indique comment on peut acc`der aux cases ; e 2. le type des valeurs quil contient. Par exemple, on peut dnir un tableau qui contient le nombre dheures de cours pour chaque jour e de la semaine : Var horaires = Array [lundi..vendredi] of integer; Mais on aurait aussi pu crire (toujours avec les dnitions prcdentes) : e e e e Var horaires = Array [jourstravail] of integer; On utilise ensuite chaque case du tableau comme une variable : horaires[mercredi]:=5 cours:=horaires[lundi] etc.

6.1

Les tableaux de tableaux

Le type de la valeur contenue dans le tableau peut aussi tre un tableau. Par exemple, si on veut dnir e e une matrice 3x3 : Var matrice : Array [1..3] of Array [1..3] of real Ce qui peut aussi scrire : e Var matrice : Array [1..3,1..3] of real Dans les deux cas, on acc`de ` llment (1,2) avec matrice[1,2]. On peut aussi acc`der ` la deuxi`me e a ee e a e ligne, avec matrice[2], mais on ne peut pas acc`der ` la deuxi`me colonne... e a e

6.2

Les types de tableaux

On peut aussi dnir des types de tableaux. Par exemple, avec les matrices, cest mieux de dnir des e e types matrices et vecteurs, et ensuite des variables ayant ces types : Type vecteur : Array [1..3] of real; matrice : Array [1..3,1..3] of real; Var u,v : vecteur ; M : matrice ; ...
Yannick Chevalier

6.3

Les cha nes de caract`res e

Une cha de caract`res est un tableau de caract`res. On peut lire et crire des cha ne e e e nes de caract`res e avec les fonctions readln et writeln. Il faut penser ` prendre un tableau susament grand pour quil a puisse contenir tout ce que va taper lutilisateur.

15

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

6.4

Les constantes

Dans lexemple prcdent, on prenait des matrices de type 3x3, avec des vecteurs de dimension 3. Si on e e veut changer la dimension de 3 en 4, cela peut tre pnible de rechercher partout dans le programme les e e 3 qui correspondent ` la dimension de lespace, et de remplacer tous ces 3 par des 4. a Une mthode rapide est de dnir une constante. Il sagit dun nom qui sera remplac dans tout le e e e programme par la valeur quon lui donne. ce nest pas une variable, il nest donc pas possible de changer la valeur de cette constante. Si on rassemble toutes les dclarations vues jusquii (dautres arrivent), la e c partie dclaration dun programme Pascalressemble ` : e a Const dimension = 3 ; pi = 3.1415; message = Bienvenue.; Type vecteur = Array [1..dimension] of real; matrice : Array [1..dimension,1..dimension] of real; Var u,v : vecteur ; M : matrice ;

Yannick Chevalier

16

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

7
7.1

Fonctions et procdures e
Introduction

Les constructions quon va maintenant voir servent ` regrouper plusieurs instructions. Cela est partica uli`rement intressant dans les cas suivants : e e pour des morceaux de programmes quon va devoir faire plusieurs fois, en dirents endroits du e programme ; pour des morceaux de programmes quon veut isoler du reste, soit pour des raisons de clart, soit e pour pouvoir les changer plus facilement. On a dj` vu et utilis, au cours des exercices ou dans le cours, les fonctions SQRT, SIN, les procdures ea e e writeln, readln,... Dans tous ces cas, on est juste intress par le rsultat du bloc dinstruction, pas par e e e la mani`re de trouver ce rsultat. Un autre exemple est la fonction div. On peut faire plusieurs blocs e e dinstructions dirents pour obtenir le rsultat, mais ce rsultat sera toujours le mme (tant quil ny a e e e e pas derreurs).

7.2

Dclaration des fonctions, ranement e

Un dernier intrt des procdures et des fonctions est lutilisation pour la construction de programmes e e e par ranement. Par exemple, si on veut crire un programme qui calcule le dterminant dune matrice e e 3x3 donne par lutilisateur : e Program Calcul de determinant; Const dimension = 3 ; pi = 3.1415; message = Bienvenue.; Type vecteur = Array [1..dimension] of real; matrice : Array [1..dimension,1..dimension] of real; Var u,v : vecteur ; M : matrice ; det : oat ; (* dclarations des fonctions et procdures *) e e begin Entrer matrice(M); det:=Calcul determinant(M); writeln(le dterminant de cette matrice est ,det) e end. On va voir comment dclarer les fonctions et les procdures, mais on voit quon peut tout de suite e e avoir un programme qui marche en faisant une procdure qui crit Bonjour et une fonction qui renvoie e e toujours 1 (ou 0...). Dans le cadre dun long travail, il est toujours utile de commencer ` crire ses a e fonctions, mme si elles rendent une valeur qui na aucun sens. Cela permet de vrier, tape par tape, e e e e que tout marche bien.

7.3

Les procdures e
Yannick Chevalier

On utilise des procdures pour regrouper des instructions dont le but nest pas de rendre un rsultat de e e type char, boolean, integer,real. On dclare une procdure avec : e e

17

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Procedure <nom de la procedure> (<liste darguments>); Var liste ; begin liste dinstruction end; Les arguments de la procdure donnent des noms et des types aux valeurs avec lesquelles la procdure e e est appele. Par exemple, dans le cas prcdent, la procdure prend un argument de type matrice. Le nom e e e e quon donne ` largument est celui quon utilisera pour cette valeur lors de lutilisation de la procdure. a e Les variables qui sont dclares dans linstruction Var ne peuvent tre utilises que pendant linstruction. e e e e Elles nont pas de valeurs en dehors de la procdure. e Par exemple, si on veut faire une procdure qui ache n astrisques, o` n est donn par ailleurs, on e e u e a: Procedure ligne (n:integer); Var i:integer ; begin for i:= 1 to n do write(*);(* ache sans aller ` la ligne*) a writeln(* va ` la ligne *) a end; Le passage des arguments, lors de lappel de la procdure, se fait normalement par valeur. Cela signie e que la valeur des arguments est donne ` la procdure pour son excution, mais pas leur nom. Pour e a e e voir la dirence, il faut faire des petites bo : e tes
function f(a,b:integer):integer;

...
x:=11; y:=f(x,17); ... on met la valeur de x dans la variable a

on met la valeur 17 dans la variable b

function f(a,b:integer):integer; begin f:=a+b end;

function f(a,b:integer):integer;

...
x:=11; y:=f(x,17); ...

on met le rsultat dans le nom de la fonction, puis on termine la fonction et enfin on met la valeur de f dans la variable y.

Figure 3: Schma de la recopie des arguments lors dun appel par valeur e

Heureusement, il y a la possibilit dappeler la procdure avec le nom de la variable. Dans ce cas, les e e changements qui seront faits ` lintrieur de la procdure changeront aussi la variable a lextrieur de la a e e ` e procdure. Cest ce qui permet la procdure Entrer Matrice vue plus haut. Pour cela, il faut prciser e e e quon veut la variable, et pas uniquement sa valeur : Procedure Entrer matrice (Var M:matrice); Var i,j:integer ; begin (* instructions *) end;;

Yannick Chevalier

18

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Dans ce cas, lappel de la procdure se fait suivant le schma ci-dessous : e e

var mat : matrice; procedure f(M : matrice); begin Dans le corps de la procdure f, M est un alias pour la matrice mat

...

f(mat) ... end.

procedure f(var M:matrice); begin

...
var mat : matrice; procedure f(M : matrice); begin

...

M[1,1]:=1;

end;

...

f(mat) ... end.

on fait un changement de M, donc on va changer la matrice mat qui est en dehors de la procdure.

Figure 4: Schma du renommage des variables lors dun appel par nom e

Il y a donc un renommage des variables entre lintrieur et lextrieur de la procdure. Mais cest e e e juste la possibilit dappeler la mme variable avec un alias, qui sera toujours le mme, mme lorsque les e e e e variables entre dirents appels changent. e

7.4

Les fonctions

Cest essentiellement la mme chose, mis ` part quune fonction rend une valeur dun type simple (donc e a pas de tableau). Il faut : 1. prciser le type de la valeur retourne par la fonction ; e e 2. il doit y avoir une instruction qui donne cette valeur. On utilise la dclaration suivante : e Function <nom de la fonction> (arguments):type; Var liste ; begin; ... <nom de la fonction>:= . . . ; end; Exercice : Ecrire un programme qui demande en entre 2 matrices 3x3, et qui calcule leur somme, et qui ache le e rsultat. e 1. de quelles procdures a-t-on besoin ? e 2. lesquelles modient leurs arguments ? 3. crire ces procdures. e e

Yannick Chevalier

19

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Yannick Chevalier

20

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

8
8.1

Algorithmes rcursifs e
Des exemples bien connus

En mathmatiques, on prouve facilement que le pgcd de deux entiers positifs (et non-nuls) a et b, cest : e aussi le pgcd de a et b a si a > b (on peut changer les rles de a et b) ; e o cest a si a = b. Partant de l`, on a vu quon pouvait faire une fonction qui calcule le pgcd de 2 nombres : a Function pgcd(a,b :integer):integer; (* fonction qui calcule le pgcd de a et b*) begin if (a < 0) then a:=-a; if (b < 0) then b:=-b; if (a = 0) then pgcd:=b else if (b = 0) then pgcd:=b else while (a <> b) do if (a < b) then b:=b-a else a:=a-b; pgcd:=a; end; On a dj` vu cette fonction, mais elle sloigne un peu de la proprit mathmatique, puiquelle utilise ea e ee e une boucle, alors quil ny a pas ditration dans la proprit. e ee Ce nest pas le seul cas o` on utilise une boucle l` o` il ny en a pas ` priori. On peut aussi prendre u a u a le cas de la fonction factorielle, dnie pour un entier n 0 : e 0! = 1 ; (n + 1)! = (n + 1).n!. La fonction qui calcule la factorielle dun entier n positif peut scrire : e Function factorielle(a :integer):integer; Var temp,indice : integer; (* fonction qui calcule la factorielle de a *) begin temp :=1; for indice:=1 to a do temp:=temp*indice; factorielle:=temp ; end; On a donc l` encore utilis une boucle (une boucle for cette fois). Ces deux exemples ont un point a e commun :

Yannick Chevalier

21

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

La valeur de la fonction est dnie par une autre valeur de la fonction e

Par exemple, la valeur de pgcd(6, 51) est dnie comme tant gale ` la valeur de pgcd(6, 45). De e e e a mme, la valeur de 7! est dnie comme tant gale ` la valeur de 6! multiplie par 7. e e e e a e En mathmatique, si on a une suite dont les valeurs sont dnies en fonction dautres valeurs de la e e suite, on parle de suites rcurrentes. Et les suites sont des fonctions de N dans R ! e

En informatique, cest pareil. On parle de fonction rcurrente pour dsigner une fonction e e dont la valeur est dnie par rapport ` une autre valeur de la fonction. e a

En pascal, cest tr`s facile dcrire des fonctions rcursives. Par exemple, pour le calcul du pgcd, on e e e peut dnir la fonction suivante, qui prend uniquement des entiers strictement positifs en entre : e e Function pgcd(a,b :integer):integer; (* fonction qui calcule le pgcd de a et de b * de mani`re rcursive *) e e begin if (a = b ) then pgcd := a else if (a > b) then pgcd:= pgcd(a-b,b) else pgcd:= pgcd(a,b-a) end; De la mme mani`re, on peut calculer la factorielle dun entier a de mani`re rcursive : e e e e Function factorielle(a :integer):integer; (* fonction qui calcule la factorielle de a * de mani`re rcursive *) e e begin if (a=0) then factorielle:=1 else factorielle:=a*factorielle(a-1); end;

8.2
8.2.1

Arrt dune fonction rcursive e e


Le probl`me e
Yannick Chevalier

La question quon peut se poser est la suivante. Si La valeur de la fonction en un point est dnie par e rapport ` la valeur de la fonction en un autre point, quest-ce qui empche le calcul de ne pas sarrter ? a e e La rponse est assez simple : rien, si on ne fait pas dhypoth`ses supplmentaires. Par exemple, on e e e peut dnir la fonction tcaf, quon note ? : e 0? = 1 ;

22

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

n? = n (n + 1)?. Regardons un peu ce qui se passe. Si on veut calculer 0?, la valeur est donne tout de suite, et cest e 1. Essayons maintenant de calculer 1?. On a : 1? = 1 2? = 1 2 3? = 1 2 3 4? = . . . Ca ne terminera jamais ! On voit mme que pour un entier n strictement positif, cette fonction ne e donnera jamais de valeur. Par contre, on peut remarquer que la fonction tcaf est bien dnie pour tous e les entiers 0. Et quil se passe la mme chose que pour la fonction factorielle, qui elle ne sera pas dnie e e pour les entiers ngatifs. e Cest assez compliqu, aussi on va essayer dy voir un peu plus clair. e 8.2.2 Graphe de dpendance dune fonction rcursive e e

Pour calculer 2!, il faut connaitre 1!

Pour calculer 4!, il faut connaitre 3!

Pour calculer 1!, il faut connaitre 0!

Pour calculer 3!, il faut connaitre 2!

...Et on connait 0!, car : 0! = 1


Figure 5: Graphe de dpendance des arguments de la fonction factorielle pour n = 4 e

On voit quon a une suite qui dcro et qui est toujours positive. Thor`me de mathmatiques : toute e t, e e e suite dcroissante et minore converge. Et si une suite qui ne prend que des valeurs enti`res converge, e e e alors, au bout dun moment, elle est stationnaire (on ne bouge plus). Faire le raisonnement. Et si elle est strictement dcroissante, alors on est oblig de sarrter. e e e Autrement dit, si, dans les appels dune fonction rcursive, on trouve une quantit enti`re qui est toue e e jours positive et strictement dcroissante, alors cette fonction donnera toujours une valeur (on sarrtera e e au bout dun moment). Le probl`me est que cette quantit nest pas toujours vidente, comme dans le e e e cas de la fonction factorielle. On a utilis, sans le savoir, le graphe de dpendance des appels dune fonction rcursive. e e e Construction du graphe de dpendance e Pour donner ce graphe, il faut tracer, pour la valeur dun argument, des ches qui vont de cette e valeur vers les valeurs des arguments dont on a besoin. Si, en partant dun point, les chemins, en suivant ces ches, est ni, le calcul de la valeur de ce point terminera. e On peut reprendre lexemple de la fonction pgcd, en regardant ce qui se passe pour pgcd(7,4). Cette fois-ci, comme il y a deux arguments, on se place dans le plan : On a bien limpression que ca va toujours sarrter, mais ni a, ni b ne sont strictement dcroissants. e e Ii, on a toujours a + b qui est strictement dcroissant, jusqu` ce quon sarrte. c e a e

Yannick Chevalier

23

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

: signifie on a besoin de connaitre... pour connaitre ... (10,8) (18,8)

(2,2) (4,2)

(6,2)

(8,2)

a
Figure 6: Graphe de dpendance des arguments de la fonction pgcd pour (7,4) e

R`gle de programmation : Lorsquon utilise une fonction rcursive, il faut toue e jours mettre en commentaire la quantit qui est strictement dcroissante. e e

Exercice : p On dnit Cn pour un entier n 0 et 0 p n par : e


n 0 si p = 0 ou p = n, Cn = Cn = 1 ; p1 p p sinon, Cn = Cn1 + Cn1 .

1. Le graphe de dpendance doit-il tre trac sur une droite ou sur un plan ? e e e
2 2. tracer le graphe de dpendance pour C4 . e

8.2.3

Fonctions mutuellement dnies e

On consid`re le cas de deux suites numriques (un )nN et (vn )nN , et on suppose quelles sont dnies e e e lune par rapport ` lautre : a u0 = 1 un+1 = f (un , vn ) v0 = 1 vn+1 = g(un , vn ) On peut calculer les valeurs de ces suites de mani`re na e ve. Il sut de remarquer quune suite est une fonction des entiers vers les nombres rels : e

Yannick Chevalier

24

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

(* dclaration des fonctions f et g *) e Function u(n:integer):real; (* fonction qui calcule un *) (* n dcroit ` chaque appel de u et v *) e a begin if (n = 0) then u:= 1 else u:=f(u(n-1),v(n-1)) end; Function v(n:integer):real; (* fonction qui calcule vn *) (* n dcroit ` chaque appel de u et v *) e a begin if (n = 0) then v:= 1 else v:=g(u(n-1),v(n-1)) end; On commence par regarder si ce calcul est possible en faisant un graphe de dpendance. Par exemple, e pour n = 3, on a besoin : 1. pour calculer u3 , il faut dabord calculer u2 et v2 ; 2. pour calculer u2 , il faut dabord calculer u1 et v1 ; 3. pour calculer v2 , il faut dabord calculer u1 et v1 ; 4. pour calculer u1 , il faut dabord calculer u0 et v0 ; 5. pour calculer v1 , il faut dabord calculer u0 et v0 ; 6. on conna les valeurs de u0 et v0 . t On peut maintenant tracer le graphe de dpendance 7. On utilise 2 couleurs pour les appels ` la e a fonction u et ` la fonction v : a On voit sur ce graphe que toutes les ches vont vers la gauche (n dcro strictement). On peut e e t vrier, sur la formule, que n est strictement dcroissant entre chaque appel ` la fonction u ou ` la e e a a fonction v. Mais il y a un probl`me : dans la dclaration de la fonction u, on utilise la fonction v qui nest pas e e encore dnie ` ce moment. On peut alors dcider de changer lordre de dclaration de u et v, mais dans e a e e ce cas, ce sera dans la fonction v quil y aura un probl`me : la fonction u ne sera pas dclare. e e e Il faut regarder dun peu plus pr`s, car on navait pas ce probl`me pour une fonction simplement e e rcursive, qui est simplement dnie ` partir delle-mme. On commence par un peu de vocabulaire : e e a e En-tte de e la fonction Function u(n:integer):real; (* fonction qui calcule un *) (* n dcro ` chaque appel des fonctions u et v *) e t a

Yannick Chevalier

25

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Un

Figure 7: Graphe de dpendance entre les appels e begin if (n = 0) then u:= 1 else u:=f(u(n-1),v(n-1)) end;

Corps de la fonction

Et les en-ttes sont utiliss de la mani`re suivante : e e e

En Pascal, une fonction ou une procdure est dclare ` partir du moment o` e e e a u son en-tte est dclar. e e e
Yannick Chevalier

Donc, pour rsoudre notre probl`me avec les fonctions u et v, il sut de procder de la mani`re e e e e suivante : 1. on dclare len-tte de la fonction v ; e e

26

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

2. on crit la fonction u ; e 3. on crit le corps de la fonction v. e Il ne reste plus quun petit probl`me ` rsoudre : comment dire ` Pascal que le corps de la fonction e a e a v doit tre reli ` len-tte qui a t dclar bien avant ? e ea e ee e e Pour cela, on prcise, lors de la dclaration de len-tte, quon donnera le corps de la fonction plus e e e loin : Function u(n:integer):real; Forward Et lors de la dclaration du corps de la fonction, on rappelle juste le nom de la fonction quon est en e train de dnir : e Function v; (* fonction qui calcule vn *) (* n dcroit ` chaque appel de u et v *) e a begin if (n = 0) then v:= 1 else v:=g(u(n-1),v(n-1)) end; On ne rappelle que le nom. Les arguments de la fonction sont dj` dnis. Si des variables sont ea e utilises dans le corps de la fonction, cest lors de la dclaration du corps de la fonction quon les marque, e e pas lors de la dclaration de len-tte. Le programme pour calculer les suites u et v devient : e e

Yannick Chevalier

27

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Program CalculRecursif; (* calcul de 2 suites mutuellements rcursives *) e (* Il nest pas ncessaire de calculer des variables *) e (* dclaration des fonctions f et g *) e Function f(x,y:real):real; (* par exemple *) f:=x/y; Function g(x,y:real):real; (* par exemple *) g:=sqrt(x*y); (* dclaration des fonctions suite *) e Function v(n:integer):real; Forward ;(* en-tte de la fonction v *) e Function u(n:integer):real; (* fonction qui calcule un *) (* n dcroit ` chaque appel de u et v *) e a begin if (n = 0) then u:= 1 else u:=f(u(n-1),v(n-1)) end; Function v; (* fonction qui calcule vn *) (* n dcroit ` chaque appel de u et v *) e a begin if (n = 0) then v:= 1 else v:=g(u(n-1),v(n-1)) end; begin writeln(u(30) vaut,u(30)); end. 8.2.4 Taille en mmoire lors dun calcul rcursif e e

p On reprend un calcul simple, celui des coecients binomiaux Cn . On a dj` vu en cours une fonction ea rcursive qui permet de les calculer, et on a vu en TD comment les calculer en utilisant une boucle for . e On peut se demander Quelle mthode est la meilleure ? e

Yannick Chevalier

28

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Une fois quon est habitu ` leur criture, les algorithmes rcursifs sont beaucoup plus simple que les ea e e algorithmes utilisant des boucles, car il ny a plus besoin de soccuper des initialisations de compteur, ni de chercher une mani`re de calculer qui nest pas contenue dans la dnition de la fonction. e e

Utiliser des fonctions rcursives, cest donc minimiser le risque de taper une erreur. e

Cest pour cette raison que les langages utilisant ces fonctions sont tr`s utiliss pour crire de gros e e e programme, o` il est surtout important de ne pas faire derreurs. Linconvnient, cest que pour calculer u e 6 C12 , par exemple, on va rduire ce calcul a une grande somme dont tous les termes valent 1. Autrement e ` dit, on va devoir garder en mmoire plus de 1000 variables qui attendent leur valeur pour faire ce calcul, e alors quen reprenant le programme vu en TD, cela se fait en une cinquantaine de variables direntes. e Et ce foss grandit quand on prend des nombres plus grands. e Il est alors possible quun calcul prenne tellement de temps avec un algorithme rcursif quon prf`re e ee parfois utiliser un calculer itratif. Dans lexemple de calcul de suite qui vient dtre donn, il nest pas e e e certain que la mani`re rcursive de calculer termine pour 30, alors quune suite de cette taille a t tra ee e e ee t jusquau rang 1000 en TD, en faisant une boucle for .

Yannick Chevalier

29

UNIVERSITE HENRI POINCARE - NANCY I, 2000/2001

Deug TI 1A

Conclusion : Forme dun programme Pascal

Les langages de programmation sont donns par des grammaires, qui attendent des mots ou de signes e spciaux. Il nest pas question ii daller tr`s loin dans cette grammaire, mais juste de donner la forme e c e que doit avoir un programme Pascal lorsquon suit la grammaire Pascal. La forme gnrale dun programme Pascal est : e e Program nom du programme ; Dclarations ; e begin <liste dinstruction>; end. Dans les dclarations, on met dans cet ordre : e 1. les dclarations de constantes ; e 2. les dclarations de type ; e 3. les dclaration den-tte de fonctions et de procdures ; e e e 4. les dclarations de fonctions et procdures. e e

Yannick Chevalier

30