CSI 3525 - Groupe de discussion #2

Initiation a Pascal

    1. Introduction

Concu dans les annees 70, Pascal est un des premiers descendants d'Algol 60 a rencontrer un veritable succes, en particulier dans le domaine de l'Education. C'est ainsi que jusqu'au debut des annees 90, il sera le langage le plus utilise dans les universites. Un des avantages de Pascal est sa relative fiabilite, en particulier grace a un controle de types assez etendu. Il s'agit par ailleurs d'un langage imperatif classique avec la plupart des structures du genre, ce qui en fait un langage encore relativement utilise pour decrire des algorithmes, meme si, en pratique, l'avenement des langages orientes objets correspond au declin progressif du Pascal. Les eleves ayant deja utilise un langage imperatif n'auront en principe aucun probleme a comprendre la syntaxe du Pascal, ce cours est juste destine a exposer la formalisation.

      2. Structure d'un programme en Pascal

Un programme en Pascal se presente de la facon suivante :

program nom_du_programme(input,output);

begin
________ ;
________ ;
________
end.

Les mots cles input et output designent les entrees et sorties standard (le clavier et l'ecran), c'est ici que l'on specifiera que l'on veut travailler sur des fichiers particuliers. Les mots reserves begin et end designent le debut et la fin d'un groupement logique (ici le corps du programme). Entre les deux, les lignes se terminent en principe par un point virgule sauf cas particuliers (comme la derniere ligne avant end). On signale au compilateur que l'on est arrive a la fin du programme par un point.

Les commentaires sont places entre les caracteres (* et *).

3. Types de donnees

Les types de donnees utilises en Pascal sont les suivants :
- integer : entier entre -32768 et 32767
- byte : un octet, traite comme un entier entre 0 et 255
- real : reel entre E-38 et E38
- boolean : booleen, code sur un bit et pouvant prendre les valeurs true ou false
- char : caractere
- shortint : entier court entre -128 et 127
- word : entier entre 0 et 65535
- longint : entier entre -2 147 483 648 et 2 147 483 647
- single : reel a 7 chiffres significatifs
- double : reel a 15 chiffres significatifs
- extended : reel a 19 chiffres significatifs
- comp : entier entre -E18 et E18
Bien entendu, seuls les premiers types sont utilises tres couramment.

La declaration se fait avant le begin signalant le debut du bloc logique, au debut du programme et de la facon suivante :
var nom_de_la_variable : type_de_la_variable ;
Par exemple :
var i : integer ;
ou eventuellement une declaration multiple :
var i,j : integer ;
x : real ;

On peut egalement declarer des constantes au meme endroit dans le programme :
const PI=3.14159;

4. Types enumeres

Cette fonctionnalite de Prolog rentre dans le cadre de l'accentuation du controle de types. La possibilite de definir ses propres types permet de limiter un certain nombre de bugs a la phase de compilation. La syntaxe est la suivante :

type mon_type = (type1,type2,type3,...);
(* cette ligne se place avant la declaration des variables *)

Par exemple, on peut definir un type couleur :

type couleur = (rouge,jaune,bleu,vert,gris);
var col : couleur;

Les types enumeres permettent ensuite de faire un certain nombre d'operations basees sur l'ordre de la declaration. Dans notre exemple, le compilateur affecte un numero a chaque couleur. La couleur 0 est rouge, la couleur 1 est bleu, ainsi de suite...
D'ou les resultats suivants :
- ord(col) donne son ordre dans l'enumeration (si col = bleu, ord(col) = 2)
- pred(col) donne l'element precedent dans l'enumeration (si col = bleu, pred(col) = jaune)
- succ(col) donee le successeur dans l'enumeration (si col = bleu, succ(col) = vert)

Il est egalement possible de definir des sous-types :

type couleurs_froides = bleu..gris;

5. Tableaux et chaines de caracteres

On declare les tableaux de la facon suivante :

type tableau = array[1..50] of integer; pour un tableau de 50 entiers qu'il faudra ensuite instancier :
var mon_tableau : tableau;

On accede alors a son i-eme element de la facon suivante : cetab[i].

Les chaines de caracteres sont creees de la meme facon, en utilisant le mot reserve packed qui indique que les differents caracteres du tableau sont groupes :

type mot = packed array [1..10] of char;
var mot1 = mot;

La declaration de matrices necessite juste l'ajout d'une dimension :

type matrice = array[1..10,1..10] of integer; (* pour une matrice de 100 entiers. *)

6. Structures

Les structures sont realisees en utilisant une declaration de type avec le mot record. Imaginons une structure personne contenant le prenom et l'age d'un individu :

type personne = record
prenom : mot;
age : integer;
end;
var jean : personne;
(* pour cet exemple, il faut bien entendu avoir declare le type mot avant *)

On accede ensuite aux differents champs de deux manieres differentes :
- par un point : jean.prenom = 'jean '; (* on rajoute des espaces pour arriver aux 10 caracteres requis par la structure mot *)
jean.age = 20;
- par le mot with :
with jean do
prenom = 'jean ';
age = 20;
end;

7. Procedures et fonctions

Elles sont declarees au debut du programme. Une procedure realise une partie d'un programme alors qu'une fonction est destinee a renvoyer une variable.

program nom_du_programme(input,output);
var_______;

procedure proc(i:integer,lettre:char);
var _____;
begin
________ ;
________ ;
________
end;

function fonc(i,j:integer) : integer; (* declare que la sortie de la fonction est un entier *)
var _____;
begin
________ ;
________ ;
fonc := ________ (* la derniere ligne indique la valeur a renvoyer en instanciant fonc *)
end;

begin (* on retrouve ici le bloc logique correspondant au programme principal *)
________ ;
________ ;
________
end.

8. Entrees/Sorties

Les commandes de lecture et d'ecriture sont :
- write/writeln pour ecrire (en principe a l'ecran). S'utilise ainsi, si i est un entier valant 5 :
writeln('La valeur de l'entier i est ',i); ce qui affiche :
La valeur de l'entier i est 5
et revient a la ligne. write a les memes proprietes sans le retour a la ligne final.
Noter le caractere <14> qui permet d'effacer l'ecran (writeln('<14>');)
- read/readln pour lire. S'utilise ainsi pour demander la valeur de l'entier i :
readln(i);
On attend alors que l'utilisateur tape un entier suivant d'un retour a la ligne.
Pour les mots (de type packed array), un seul readln suffit pour lire tous les caracteres.

Pour utiliser un fichier, il faut le declarer au debut du programme - il s'agit d'une variable a part entiere :

program nom_du_programme(input,fichier);
var fichier : file of char; (* On peut aussi utiliser le mot text a la place de file of char *)

Par la suite, les commandes sont differentes suivant que l'on veuille utiliser le fichier en lecture ou en ecriture :
reset(fichier,nom_du_fichier); prepare la lecture.
rewrite(fichier,nom_du_fichier); prepare l'ecriture.
Ne pas confondre les deux arguments : le premier est de type file et designe le fichier lui-meme, le second est de type string (ou packed array of char) et designe juste le nom du fichier. Enfin, on utilise write/writeln/read/readln comme precedemment, en mentionnant simplement le fichier en premier argument :
w
riteln(fichier,'La valeur de l'entier i est ',i);
Les caracteres speciaux EOLN (end of line) et EOF (end of file) sont souvent utiles dans la lecture de fichiers. Enfin, pour fermer un fichier, on utilise l'instruction :
close(fichier);

9. Boucles et branchements conditionnels

Les instructions decrites ici sont typiques des langages imperatifs. Elles ne presentent donc aucune difficulte de comprehension particuliere.

if cond then (* Dans la condition cond, on peut utiliser les operateurs de comparaisons standard : =, <> (different), >, <, >= et <= *)
begin
________ ;
________ ;
________
end
else
begin
________ ;
________ ;
________
end;

Pour eviter l'imbrication de multiples blocs logiques if, on utilise parfois l'instruction case (qui dirige en fonction de la valeur d'une variable, dans notre exemple, un entier i) :

case i of
1 : ________; (* Noter l'absence de begin *)
2 : ________;
3 : ________;

N : ________;
else (* Contrairement a ce que j'ai dit en cours, la derniere condition est introduite par else dans la plupart des *)
___________ (* versions de Pascal et non par otherwise *)
end;

Enfin, on retrouve egalement les boucles classiques :

for i := 1 to N do while cond do
begin begin
________ ; ________ ;
________ ; ________ ;
________ ________
end; end;

Par rapport a la question qui m'a ete posee en cours, dans la boucle for, l'incrementation de i est automatique (et d'une unite) a chaque tour de boucle mais il est possible de faire des operations sur la variable i a l'interieur de la boucle. Ainsi, placer l'instruction i := i +1 juste avant le end aura pour effet de ne faire tourner la boucle que pour les i impairs, par exemple.

10. Pointeurs

Cette section est un complement par rapport a ce que j'ai dit en cours et une rapide introdution aux pointeurs. Comme en C, un pointeur designe une adresse qui indique ou dans la memoire trouver la variable. Ainsi, on declare de la facon suivante un pointeur sur un entier :

type pointeur = ^integer;

var ptr : pointeur;

Ensuite, on l'utilise dans le programme en l'initialisant par new et en le detruisant par dispose :

begin
new(ptr);
ptr^ := 10; (* Pour acceder a l'entier pointe *)
________;
________;
dispose(ptr)
end.

Le pointeur nul s'ecrit nil.


Ces bases devraient vous suffire pour comprendre un programme simple ecrit en Pascal.
Pour toutes questions ou remarques, n'hesitez pas : rigouste@site.uottawa.ca .