Types de données définis par l'utilisateur
Au lieu de limiter un programme à l'utilisation de types de données prédéfinis, le QuickPascal vous permet de créer vos propres types de données personnalisés étant pertinents pour le programme en cours.
Un type de données ordinal est une collection de valeurs où chaque valeur (à l'exception de la première) a une valeur unique la précédant et (à l'exception de la dernière) une valeur unique la suivant. Boolean, Char, Integer et LongInt sont des exemples de types de données ordinales. Avec QuickPascal, vous pouvez créer vos propres types ordinaux en utilisant des types énumérés et des types de sous-gamme.
Un type de données énuméré contient une série de valeurs ordinales uniques définies. Vous pouvez y penser en termes d'entier, mais au lieu d'une intervalle de nombres, vous désignez une intervalle de vos propres valeurs. Un type de données de sous-intervalle est créé en spécifiant les premier et dernier éléments d'un type ordinal existant. Le type peut être l'un des types ordinaux Pascal standard ou un type énuméré de votre propre création.
Outre les types d'énumération et de sous-intervalle, vous pouvez également créer un type d'ensemble. Un ensemble contient jusqu'à 255 valeurs uniques d'un type ordinal existant.
Types de données énumérés
Les types de données énumérés consistent en une liste ordonnée d'identificateurs uniques. Les identificateurs peuvent être n'importe quoi, des voitures aux jours de la semaine. Un type de données énuméré est défini simplement en listant les identificateurs composant le type.
La syntaxe d'un type énuméré est :
TYPE ListName = (Identifier [, Identifier...]) |
Le QuickPascal affecte des numéros aux identificateurs de la liste Le premier élément de la liste est affecté de 0, le second de 1, et ainsi de suite, jusqu'à un maximum de 65 535 valeurs. Il s'agit de la représentation interne QuickPascal. Vous vous référez normalement à une valeur par son nom. Un exemple de type de données énumérées est :
- Type
- japanese_cars=(Honda,Isuzu,Nissan,Toyota);
L'utilisation des valeurs affectées aux éléments dans les listes énumérées est illustrée dans cette instruction :
Cela place nissan, avec une valeur de 2, dans la variable rental_car. Il peut arriver que vous souhaitiez que le premier élément d'une liste ait une valeur différente de zéro. Vous pouvez y parvenir en déclarant un faux identificateur comme premier élément :
- TYPE
- place=(null, first, second, third, fourth);
Cela fournit un ordre numérique plus naturel pour les éléments de la liste.
Le QuickPascal fournit deux procédures et cinq fonctions pour manipuler les types de données énumérés. Les routines prédéfinies sont First, Last, Succ, Pred, Inc, Dec et Ord.
La fonction First
La fonction First renvoie le premier élément de n'importe quel type ordinal. La fonction reçoit un type ordinal et renvoie une valeur du même type.
L'exemple suivant vous montre comment utiliser First :
- Program enums;
- Type
- my_type = -5..5;
- greek = (alpha, beta, gamma, delta, epsilon);
- subgreek = gamma..epsilon;
-
- BEGIN
- WriteLn('Type ':20, 'First(Type)':20,' Last(Type)':20);
- WriteLn;
- WriteLn('Integer':20, First(Integer):20, Last(Integer):20);
- WriteLn('LongInt':20, First(LongInt):20, Last(LongInt):20);
- WriteLn('ShortInt':20,First(ShortInt):20, Last(ShortInt):20);
- WriteLn('Word':20, First(Word):20, Last(Word):20);
- WriteLn('Char(ord)':20,Ord(First(Char)):20,Ord(Last(Char)):20);
- WriteLn('Boolean':20, First(Boolean):20, Last(Boolean ):20);
- WriteLn('my_type':20, First(my_type):20, Last(my_type ):20);
- WriteLn('greek(ord)':20,Ord(First(greek)):20,Ord(Last(greek)):20);
- WriteLn('subgreek(ord)':20,Ord(First(subgreek)):20,Ord(Last(subgreek)):20);
- END.
En Turbo Pascal, on utilise plutôt la fonction Low pour obtenir le même résultat que fonction First.
La fonction Last
La fonction Last renvoie le dernier élément de tout type ordinal. La fonction reçoit un type ordinal et renvoie une valeur du même type. L'exemple précédent montre comment utiliser la fonction Last.
En Turbo Pascal, on utilise plutôt la fonction High pour obtenir le même résultat que fonction Last.
La fonction Succ
La fonction Succ renvoie le successeur ou l'élément suivant d'une valeur énumérée.
Exemple d'appel de fonction | Type ordinal | Résultat |
---|---|---|
Succ(second) | place | third |
Succ(isuzu) | japanese_cars | nissan |
Succ(15) | Integer | 16 |
Succ('a') | Char | 'b' |
Succ(False) | Boolean | True |
Les types ordinaux standard et définis par l'utilisateur peuvent être utilisés avec cette fonction.
Si la vérification d'intervalle {$R+} est définie, une erreur d'exécution se produit si vous essayez d'affecter un élément au-delà du dernier de la liste. Vous pouvez éviter ce problème en utilisant la fonction Last pour vérifier si l'élément est le dernier de la liste.
La fonction Pred
La fonction Pred renvoie le prédécesseur ou l'élément précédent d'une valeur énumérée.
Exemple d'appel de fonction | Type ordinal | Résultat |
---|---|---|
Pred(isuzu) | japanese_cars | honda |
Pred(second) | place | first |
Pred(12) | Integer | 11 |
Pred('b') | Char | 'a' |
Pred(True) | Boolean | False |
Les types de données énumérés standard et définis par l'utilisateur peuvent être utilisés avec cette fonction.
Si la vérification de plage {$R+} est définie, une erreur d'exécution se produit si vous essayez d'affecter un élément précédant le premier dans la liste. Vous pouvez éviter une erreur en utilisant la fonction First pour vérifier si l'élément est le premier dans la liste.
La procédure Inc
La procédure Inc fournit une forme abrégée de la fonction Succ. Lors de l'appel de la procédure, la variable lui étant transmise est incrémentée du nombre d'éléments spécifiés.
Par exemple, au lieu d'utiliser la fonction Succ comme suit :
la procédure Inc pourrait être utilisée comme :
- Inc(status, 2);
Si aucun paramètre d'incrémentation n'est spécifié, la variable est incrémentée de un :
- Inc(status);
La fonction Last doit être utilisée pour éviter des résultats imprévisibles lors de l'incrémentation d'éléments.
La procédure Dec
La procédure Dec est une alternative à la fonction Pred. Lors de l'appel de la procédure, la variable qui lui est transmise est décrémentée du nombre d'éléments spécifiés.
Par exemple, au lieu d'utiliser la fonction Pred comme suit :
la procédure Dec pourrait être utilisée comme :
- Dec(status,2);
Si aucun paramètre de décrémentation n'est spécifié, la variable est décrémentée de un :
- Dec(status);
La fonction First doit être utilisée pour éviter des résultats imprévisibles lors de la décrémentation d'éléments.
La fonction Ord
La fonction Ord renvoie le nombre ordinal d'un élément énuméré. Étant donné que chaque élément énuméré est unique, vous n'avez pas besoin de mentionner le type de données énuméré auquel l'élément appartient. Les valeurs ordinales commencent à zéro.
Exemple d'appel de fonction | Type ordinal | Résultat |
---|---|---|
Ord(first) | place | 1 |
Ord(toyota) | japanese_cars | 3 |
Ord('a') | Char | 97 |
Ord(False) | Boolean | 0 |
La fonction Ord accepte à la fois les constantes d'énumération et les variables. Les types de données énumérés standard et définis par l'utilisateur peuvent être utilisés avec la fonction.
Types de sous-intervalle
Parfois, seuls quelques éléments d'un type de données existant sont nécessaires. Au lieu de déclarer un nouveau type de données, le Pascal vous permet de définir un sous-intervalle d'un type de données standard ou énuméré.
Par exemple, dans un programme de notation, la variable test_score enregistre des notes comprises entre 0 et 100. Au lieu de créer un nouveau type de données pour la variable, une sous-intervalle Integer est déclarée avec une valeur minimale de 0 et une valeur maximale de 100.
Vous pouvez définir des sous-intervalles des types ordinaux suivants :
- Entiers
- Caractères
- Énumérations
Pour déclarer un type de sous-intervalle, identifiez le SubrangeName et définissez la première et la dernière valeur de l'intervalle, reliées par deux points, comme indiqué dans la syntaxe ci-dessous :
SubrangeName = FirstValue..LastValue |
FirstValue et LastValue doivent être des constantes du même type, avec FirstValue comme prédécesseur de LastValue. C'est-à-dire :
Les types de sous-intervalle ont deux objectifs utiles :
- Si l'intervalle d'un type doit être modifiée, une seule modification de la déclaration est nécessaire.
- Le QuickPascal vérifie automatiquement l'intervalle affectée aux variables de type sous-intervalle, avec les limitations suivantes :
- La vérification de l'intervalle doit être activée avec la directive du compilateur {$R+}. Cela peut être fait au début du programme, ou activé ({$R+}) et désactivé ({$R-}) autour d'une instruction où une variable de sous-gamme est utilisée. Lorsque la vérification de l'intervalle est activée, le QuickPascal génère une erreur d'exécution si une valeur en dehors de la sous-intervalle est affectée à une variable de type sous-plage.
- Le QuickPascal ne vérifie l'intervalle que dans les instructions d'affectation directe. Il ne vérifie pas les valeurs en dehors de l'intervalle dans les variables de contrôle de boucle ou les instructions de lecture/écriture.
Intervalles d'entiers
Les sous-intervalles d'entiers définissent une intervalle de valeurs entières valides. Voici quelques exemples de sous-intervalle d'entiers simples :
- Type
- screen_columns=1..80;
- die_faces=1..6; { valeurs sur les faces des dés }
- days=1..31; { maximum 31 par mois }
- months=1..12; { 12 mois/an }
- years=1900..2099; { les années que DOS connaît }
- seconds=0..59;
- minutes=0..59;
- hours=0..23;
Des identificateurs constants peuvent définir les sous-intervalles. Les exemples comprennent :
L'ajout de constantes améliore la lisibilité et simplifie les limites de sous-intervalle. Par exemple, si vous développez un programme utilisant la vidéo EGA, vous devez afficher 43 lignes par écran. Les variables de type screen_rows doivent être comprises dans l'intervalle 1..43. Tout ce qui est nécessaire est de changer la constante max_row à 43 à un endroit.
Le QuickPascal autorise les expressions dans la définition des intervalles. Voici des exemples de déclarations incluant des expressions constantes :
Sous-intervalles de caractères
Les sous-intervalles de caractères définissent une intervalle de valeurs Char acceptables. Les exemples comprennent :
Toute intervalle de caractères ASCII peut être définie dans une sous-intervalle. Notez l'utilisation des fonctions Succ et Pred dans le dernier exemple pour définir les six caractères ASCII entre 'Z' et 'a'.
Sous-intervalle d'énumération
Les sous-intervalles d'énumération limitent l'intervalle des valeurs énumérées autorisées. Un exemple est :
- TYPE
- vehicles=(Volkswagen, honda, toyota, corvette, porsche, ferrari, suburban, blazer, bronco);
- economy_cars=Volkswagen..toyota;
- sports_cars=corvette..ferrari;
Le type economy_cars est une sous-gamme avec les valeurs légales de Volkswagen, honda et toyota. De même, le type sports_cars n'a que les valeurs énumérées corvette, porsche et ferrari.
Ensembles
Les ensembles sont des types de données structurés et définis par l'utilisateur. En mathématiques, un ensemble est une collection non ordonnée d'éléments. Le concept d'ensemble est le même dans QuickPascal. Un ensemble ne contient que des valeurs uniques. Par exemple, si A, B et C étaient contenus dans un ensemble et que vous y ajoutiez B, l'ensemble ne contiendrait toujours que A, B et C, et non A, B, B et C. Les ensembles sont utiles pour contenant une collection d'attributs ou déterminant si un élément est membre d'un groupe particulier.
La syntaxe pour déclarer un ensemble est :
SetName=SET OF OrdinalType |
Le paramètre OrdinalType est une intervalle ordonnée de valeurs. Les membres de l'OrdinalType doivent être tous du même type et peuvent être des éléments uniques ou une sous-intervalle. L'OrdinalType ne peut pas avoir plus de 256 valeurs possibles. Cela limite les ensembles aux types prédéfinis Boolean, Char et Byte et restreint l'utilisation des types Word, Integer et LongInt.
Par exemple, un programme peut déclarer qu'un ensemble de lettres majuscules et de voyelles est :
Une fois que vous avez déclaré un ensemble, l'opérateur IN peut être utilisé pour tester la présence ou l'absence d'un élément spécifié. Par exemple, dans ces déclarations :
Le mot réservé IN renvoie un résultat TRUE si ch est un membre de l'ensemble, et FALSE s'il ne l'est pas.
Déclarer des types d'ensembles
Les ensembles peuvent être déclarés avec une variété de types. Sont inclus :
- Types ordinaux prédéfinis de Boolean, Char et Byte :
- Sous-intervalle de types prédéfinis (soit directement comme premier ensemble, soit indirectement comme dernier) :
- Types énumérés :
- Variables :
- Var
- fast_trans:four_wheels;
- lower_letters:lo_case;
- numl,num2:byte_bits;
- Constantes et constantes typées :
Les constantes d'ensemble de caractères sont utiles pour représenter des ensembles fixes de caractères utilisés dans les sélections de menu. Par exemple, si vous avez un menu avec les sélections suivantes :
Add Change Delete Print View Store Recalloù les lettres majuscules sont des touches de raccourcis utilisées pour sélectionner rapidement une option de menu, la constante typée correspondante ressemblerait à ceci :
Affectation d'éléments d'ensemble à des variables
Pour affecter des éléments d'ensemble à une variable d'ensemble, utilisez les crochets :
SetVariable:=[SetElements] |
Si aucun élément d'ensemble n'est présent, la variable d'ensemble se voit attribuer un ensemble vide (SetVariable := []). Les variables d'ensemble peuvent être initialisées de cette manière.
Un ensemble peut être construit à partir d'une liste d'éléments uniques, d'une sous-intervalle ou d'une combinaison des deux. Des exemples d'affectation d'éléments d'ensemble à des variables sont :
Opérateur SET
Bien que les éléments individuels d'un ensemble ne soient pas directement accessibles, une variété d'opérateurs est disponible pour tester l'appartenance et manipuler l'ensemble dans son ensemble.
Ces opérateurs offrent des méthodes puissantes et flexibles de création de nouveaux ensembles avec des éléments d'ensembles existants. Les opérateurs d'ensemble pris en charge par QuickPascal incluent :
- Opérateurs relationnels
- Opérateur IN
- Opérateur d'union d'ensemble
- Opérateur de différence d'ensemble
- Opérateur d'intersection d'ensemble
Opérateurs relationnels
Divers opérateurs relationnels sont disponibles pour tester l'appartenance à un ensemble. En fonction de la condition d'une expression, l'opérateur renverra True ou False.
Le tableau suivant affiche la liste des opérateurs relationnels fonctionnant sur des ensembles, avec A et B comme exemples d'ensembles.
Expression | Renvoie TRUE si |
---|---|
A = B | A et B sont identiques. |
A <> B | Au moins un élément de A n'est pas dans B, ou au moins un élément de B n'est pas dans A. |
A <= B | Tous les éléments de A sont dans B. |
A >= B | Tous les éléments de B sont dans A. |
Opérateur IN
Comme indiqué précédemment, l'opérateur IN teste l'appartenance à un ensemble. Cet opérateur renvoie un résultat booléen indiquant si une valeur est membre de l'ensemble. La valeur testée doit être identique ou d'un type compatible avec le type de base de l'ensemble testé. La syntaxe est :
Value IN Set |
Par exemple :
La figure suivante montre l'action des opérateurs d'ensembles sur les ensembles A et B. La zone grisée représente le résultat des opérations sur les ensembles :
Opérateur d'union d'ensemble
L'opérateur d'union d'ensembles (+) fusionne deux ensembles en un troisième ensemble. Si l'un des ensembles est un sous-ensemble de l'autre, la combinaison des deux ensembles donne un ensemble identique à l'ensemble plus grand. Dans l'exemple ci-dessous, deux ensembles avec des membres uniques sont fusionnés, ce qui donne un ensemble plus grand :
- set1=['A'..' Z'];
- set2=['a'..'z'];
- set3=set1+set2;
- set3=['A'..'Z','a'..'z']; { identique à l'assignation précédente }
Dans l'exemple suivant, les deux ensembles de caractères ont des membres se chevauchant. L'ensemble uni se compose de ['A'..' z' ] avec tous les membres se chevauchant représentés une seule fois :
- set1=['A'..'L'];
- set2=['H'..'Z'];
- set3=set1+set2;
- set3=['A'..'Z']; { identique à l'assignation précédente }
Le troisième exemple montre un ensemble réuni avec un sous-ensemble. Il en résulte que set3 et set1 ont les mêmes membres :
- set1:=['A'..'L'];
- set2:=['F'..'J'];
- set3:=set1+set2;
- set3:=['A'..'L']; { identique à l'assignation précédente }
L'opérateur d'union est également important pour ajouter à l'appartenance d'un ensemble. Dans l'exemple suivant, un ensemble de caractères est initialisé puis une boucle FOR est utilisée pour ajouter les caractères A, B, C, D, E, F,... :
- set1:=[]; { initialise }
- For ch:='A' to 'Z' do set1:=set1+[ch];
Notez la présence des parenthèses autour de la variable ch. Ils sont nécessaires pour faire de [ch] un ensemble à un seul élément.
Opérateur de différence d'ensemble
L'opérateur de différence d'ensemble (-) crée un ensemble contenant tous les membres du premier ensemble n'apparaissant pas dans le second ensemble. Par exemple, dans l'énoncé :
- set3:=set1-set2;
set3 contiendra tous les éléments de set1 n'étant pas dans set2. Si set1 et set2 ont les mêmes membres, alors set3 devient un ensemble vide. Si set2 est un sous-ensemble de set1, alors set3 comprend les membres de set1 n'étant sont pas communs à set2.
Dans l'exemple suivant, la différence entre deux ensembles avec des membres uniques est affectée à un troisième ensemble. L'ensemble résultant a les mêmes membres que le set1 puisque les ensembles d'opérandes n'ont rien en commun :
- set1:=['A' . .'Z'];
- set2:=['a'..'z'];
- set3:=set1-set2;
- set3:=['A'..'Z']; { identique à l'assignation précédente }
Dans l'exemple suivant, les deux ensembles de caractères ont des membres se chevauchant. L'ensemble résultant est composé de ['A'..' G'] :
- set1:=['A'..'L'];
- set2:=['H'..'Z'];
- set3:=set1-set2;
- set3:=['A'..'G']; { identique à l'assignation précédente }
L'exemple suivant montre la différence d'un ensemble avec son sous-ensemble. Le résultat est que set3 contient ['A'..'E'], les membres du premier set introuvables dans le second.
- setl:=['A'..'L'];
- set2:=['F'..'J'];
- set3:=setl-set2;
- set3:=['A'..'E', ' K', 'L']; { identique à l'assignation précédente }
L'opérateur de différence peut également être utilisé pour supprimer les membres individuels des variables d'ensemble. Le dernier exemple de l'opérateur d'union peut être réécrit pour utiliser l'opérateur de différence de la manière suivante. L'ensemble de caractères est initialisé à ['A'..'Z'] et une boucle FOR est utilisée pour éliminer les caractères A, B, D, F, H,...
Opérateur d'intersection d'ensemble
L'opérateur d'intersection d'ensemble (*) est utilisé pour extraire tous les éléments se trouvant dans deux ensembles de même type. Par exemple, avec :
- set3:=set1*set2;
set3 contiendra tous les éléments étant à la fois dans set1 et set2. Dans l'exemple suivant, les deux ensembles de caractères ont des membres se chevauchant. L'ensemble d'intersection est ['H'..'L'] :
- set1:=['A'..'L'];
- set2:=['H'..'Z'];
- set3:=set1*set2;
- set3:=['H'..'L'];
L'intersection d'un ensemble avec son sous-ensemble renvoie les membres du sous-ensemble. L'exemple suivant montre une telle opération. Le résultat est que set3 et set2 ont les mêmes membres :
- set1:=['A'..'L'];
- set2:=['F'..'J'];
- set3:=set1*set2;
- set3:=['F'..'J'];
Dans l'exemple suivant, deux ensembles avec des membres uniques sont intersectés. L'ensemble résultant est vide, car les ensembles d'opérandes n'ont rien en commun :
- set1:=['A'..'Z'];
- set2:=['a'..'z'];
- set3:=set1*set2;
- set3:=[];