Chapitre 20 - Types▲
Il est possible de créer de nouveaux types de variables sur Turbo Pascal 7.0. Il y a encore quelques décennies, un « bon » programmeur était celui qui savait optimiser la place en mémoire que prenait son programme, et donc la « lourdeur » des types de variables qu'il utilisait. Par conséquent, il cherchait toujours à n'utiliser que les types les moins gourmands en mémoire. Par exemple, au lieu d'utiliser un Integer pour un champ de base de données destiné à l'âge, il utilisait un Byte (1 octet contre 2). (voir chapitre 4 sur les types de variables). Il est donc intéressant de pouvoir manipuler, par exemple, des chaines de caractères de seulement 20 signes : String[20] (au lieu de 255 pour String, ça prend moins de place).
Les variables de types simples comme celles de types complexes peuvent être passées en paramètre à une procédure ou fonction.
Types simples▲
On déclare les nouveaux types simples dans la partie déclarative du programme, avant toute utilisation dans la déclaration de variables.
Syntaxe :
Type
nom_du_type = nouveau_type;
Exemples :
Type
Nom = String
[20
];
Type
Entier = Integer
;
Program
Exemple24;
Type
Chaine = String
[20
];
Var
Nom : Chaine;
Age : Byte
;
BEGIN
Write
('Entrez votre nom : '
);
ReadLn(Nom);
Write
('Entrez votre âge : '
);
ReadLn(Age);
WriteLn('Votre nom est : '
,Nom,' et votre âge : '
,Age);
END
.
Ce programme Exemple24 utilise un nouveau type appelé Chaine qui sert à déclarer la variable Nom.
Types intervalles▲
Les types intervalles sont très utilisés. Ils peuvent être de n'importe quel type scalaire. Un intervalle est forcément ordonné et continu.
Syntaxe :
Type
mon_type = borne_inf..borne_sup;
On doit obligatoirement avoir :
- borne_inf et borne_sup de n'importe quel type scalaire
- borne_inf <= borne_sup
Exemples :
Type
Binaire = 0
..1
;
Type
Alpha = 'A'
..'Z'
;
Type
Cent = 1
..100
;
Les instructions suivantes :
- Inc() (incrémentation de la variable passée en paramètre),
- Dec() (décrémentation de la variable passée en paramètre),
- Succ() (renvoie le successeur de la variable passée en paramètre),
- Pred() (renvoie le prédécesseur de la variable passée en paramètre),
- Ord() (renvoie l'index de la variable dans l'intervalle auquel elle appartient)
s'appliquent aux types intervalles, qu'ils soient de type nombre entier ou caractère et énumérés.
Exemple :
Program
Exemple31;
Const
Max = 100
;
Type
Intervalle = 1
..Max;
Var
x : Intervalle;
BEGIN
x := 1
;
{...}
if
not
(Succ(x) = Max) then
Inc(x);
{...}
END
.
Types énumérés▲
Un type énuméré est un type dont les variables associées n'auront qu'un nombre très limité de valeurs (au maximum 256 différentes possibles). La définition d'un type énuméré consiste à déclarer une liste de valeurs possibles associées à un type.
Program
Exemple32;
Type
Jours = (dim, lun, mar, mer, jeu, ven, sam);
Var
Today : Jours;
BEGIN
Today := mar;
Today := Succ(Today);
Inc(Today,2
);
case
Today of
dim : WriteLn('Dimanche'
);
lun : WriteLn('Lundi'
);
mar : WriteLn('Mardi'
);
mer : WriteLn('Mercredi'
);
jeu : WriteLn('Jeudi'
);
ven : WriteLn('Vendredi'
);
sam : WriteLn('Samedi'
);
else
WriteLn('autre, '
,Ord(today));
end
;
END
.
Dans ce programme Exemple32, il est déclaré un type Jours de type énuméré composé de 7 éléments représentant les jours de la semaine. Remarquez que les éléments sont uniquement des identifiants qui n'ont aucune valeur intrinsèque; on peut tout juste les repérer par leur index (l'ordre dans lequel ils apparaissent dans la déclaration, où le premier élément a le numéro 0 et le dernier : n-1). Tout d'abord, une affectation à l'aide de l' opérateur habituel := vers la variable Today. Puis on lui affecte son successeur dans la déclaration. Ensuite, on l'incrémente de 2. Et, selon sa valeur, on affiche à l'écran le jour de la semaine correspondant si cela est possible.
Remarque : La fonction Chr() (propre au type Char) ne s'applique pas aux types intervalles et énumérés.
Il est impossible d'utiliser les procédures Write(Ln) et Read(Ln) avec les variables de type énuméré.
Exemple :
Program
Exemple35;
Type
Couleurs = (red, yellow, green, black, blue);
Var
Color : Couleurs;
BEGIN
Color := red;
repeat
Inc(Color);
until
Color > green;
if
Color = black then
WriteLn('Noir'
);
END
.
Ce programme Exemple35 montre que, comme toute variable, Color - qui est de type énuméré - peut être sujette à des tests booléens. Ici, sa valeur est incrémentée dans une boucle Repeat qui ne s'arrête que lorsque Color atteint une valeur qui, dans le type énuméré, est supérieure à la valeur green. Ensuite un test If vient confirmer que la dernière valeur prise par Color (à laquelle on s'attendait au vu de la définition du type énuméré) est black.
Types structurés (enregistrements)▲
Un type structuré (ou enregistrement) est une structure de données consistant en un nombre fixé de composants, appelés champs. À la différence du tableau, ces composants ne sont pas obligatoirement du même type, et ne sont pas indexés.
La définition du type enregistrement précise pour chaque composant un identificateur de champ, dont la portée est limitée à l'enregistrement, et le type de ce composant.
Syntaxe :
Type
nom_du_type = Record
champ1 : type1;
champ2 : type2;
champ3 : type3;
end
;
Note : les champs sont placés dans un bloc Record...end ; et un champ peut lui-même être de type Record.
Syntaxe :
Type
nom_du_type = Record
champ1 : type1 ;
champ2 = Record
;
champ2_1 : type2;
champ2_2 : type3;
champ2_3 : type4;
end
;
end
;
On ne peut pas afficher le contenu d'une variable structurée sans passer par une syntaxe spécifiant le champ dont on veut connaître la valeur.
Note : les champs d'une variable de type structuré peuvent être de tout type (même tableau).
Program
Exemple25a;
Type
Descendance = 0
..15
;
Formulaire = Record
Nom : String
[20
];
Age : Byte
;
Sexe : Char
;
Nb_enfants : Descendance;
end
;
Var
Personne : Formulaire;
BEGIN
with
Personne do
begin
Nom := 'Etiévant'
;
Age := 18
;
Sexe := 'M'
;
Nb_enfants := 3
;
end
;
END
.
Program
Exemple25b;
Type
Descendance = 0
..15
;
Formulaire = Record
Nom : String
[20
];
Age : Byte
;
Sexe : Char
;
Nb_enfants : Descendance;
end
;
Var
Personne : Formulaire ;
BEGIN
Personne.Nom := 'Etiévant'
;
Personne.Age := 18
;
Personne.Sexe := 'M'
;
Personne.Nb_enfants := 3
;
END
.
Ces programmes Exemple25a et Exemple25b sont pratiquement identiques. Ils utilisent tous deux une variable Personne de type Formulaire qui comprend quatre champs : Nom, Age, Sexe et Nb_enfants. L'utilisation de ces champs se fait ainsi : variable.nom_du_champ (Exemple25b). Lorsqu'on les utilise à la chaîne (Exemple25a), on peut faire appel à with.
Program
Exemple25c;
Type
Bornes_Jour = 1
..31
;
Bornes_Mois = 1
..12
;
Bornes_An = 1900
..2000
;
Date = Record
Jour : Bornes_Jour;
Mois : Bornes_Mois;
An : Bornes_An;
end
;
Type
Formulaire = Record
Nom : String
[20
];
Date_naissance : Date;
end
;
Var
Personne : Formulaire;
BEGIN
with
Personne do
begin
Nom := 'Etiévant'
;
with
Date_naissance do
begin
Jour := 21
;
Mois := 10
;
An := 1980
;
end
;
end
;
END
.
Program
Exemple25d;
Type
Bornes_Jour = 1
..31
;
Bornes_Mois = 1
..12
;
Bornes_An = 1900
..2000
;
Formulaire = Record
Nom : String
[20
];
Date_naissance : Record
Jour : Bornes_Jour;
Mois : Bornes_Mois;
An : Bornes_An;
end
;
end
;
Var
Personne : Formulaire;
BEGIN
with
Personne do
begin
Nom := 'Etiévant'
;
with
Date_naissance do
begin
Jour := 21
;
Mois := 10
;
An := 1980
;
end
;
end
;
END
.
Là aussi, les programmes Exemple25c et Exemple25d sont pratiquement identiques. Ils utilisent tous deux une variable Personne de type Formulaire qui comprend deux champs : Nom et Date_naissance, qui elle-même est de type structuré et comprenant les champs Jour, Mois et An.
Enregistrements conditionnels▲
Lors de la création d'un enregistrement (type structuré), il est quelquefois nécessaire de pouvoir, en fonction d'un champ, décider de la création d'autres champs de tel ou tel type.
Une telle déclaration s'effectue grâce à la syntaxe Case of que l'on connaissait déjà .
Syntaxe :
Type
type_enumere = (element1, element2, ... elementN);
mon_type = Record
champ1 : type_enumere;
case
champ2 : type_enumere of
element1 : (champ3 : type3);
element2 : (champ4 : type4; champ5 : type5; ... champM : typeM);
...
elementN : ( );
end
;
Type
mon_type = Record
case
champ1 : Integer
of
0
: (b1 : Integer
);
1000
: (b2 : Single
);
...
end
;
Le principe est que, suivant la valeur d'un champ fixe, on va procéder à la création d'un ou plusieurs champs.
Program
Exemple30a;
Const
Nmax = 1
;
Type
Materiaux = (metal, beton, verre);
Produit = Record
Nom : String
[20
];
case
Matiere : Materiaux of
metal : (Conductivite : Real
);
beton : (Rugosite : Byte
);
verre : (Opacite : Byte
; Incassable : Boolean
);
end
;
Tab = Array
[1
..Nmax] of
Produit;
Procedure
affichage(prod : produit) ;
Begin
with
prod do
begin
WriteLn('Produit '
, nom);
case
Matiere of
metal : WriteLn('Conductivité : '
,Conductivite);
beton : WriteLn('Rugosité : '
,Rugosite);
verre : begin
WriteLn('Opacité : '
,Opacite);
if
Incassable then
WriteLn('Incassable'
);
end
;
end
;
end
;
End
;
Var
x : Tab;
i : Integer
;
BEGIN
with
x[1
] do
begin
Nom := 'Lampouille'
;
Matiere := verre;
Opacite := 98
;
Incassable := True
;
end
;
for
i := 1
to
Nmax do
Affichage(x[i]);
END
.
Il est absolument nécessaire de remplir le champ qui conditionne le choix des autres champs avant de remplir les champs qui sont soumis à condition.
Sinon, il est renvoyé des résultats absurdes.
Les résultats sont absurdes parce que les champs variables occupent la même place en mémoire, et que la valeur d'un type n'est que rarement totalement compatible avec les valeurs d'un autre type.
Program
Exemple30b;
Type
Toto = Record
case
i : Integer
of
1
: ( );
2
: (a:Real
);
3
: (x, y : String
);
end
;
Var
x : Toto;
BEGIN
x.i := 2
;
x.a := 2
.23
;
WriteLn(x.a);
x.i := 3
;
x.x := 'Castor'
;
WriteLn(x.x);
END
.
Ce dernier programme Exemple30b montre l'utilisation du type Integer, dont la valeur dans le programme conditionne l'existence d'autres champs.