Bandeau du site

Le Pascal est un langage fortement typé qui sert de support à Delphi. La version utilisé par Delphi est une version enrichie appelée Pascal Objet qui permet la programmation orienté objet dans l'environnement Windows. Ce chapitre propose une présentation du langage Pascal sous Delphi mais n'aborde pas la programmation orintée objet.

Les règles de base

Toutes les instructions se termine par un point virgule. Le point n’est utilisé qu’une seule fois par unité pour en marquer la fin.
On peut écrire plusieurs instructions sur une même ligne.
Un bloc d'instruction est délimité par les instructions Begin et End.

 

Les directives standard du Pascal Objet

absolute far on published
assembler forward persistent resident
dynamic index private vitual
export name protected external
near public    

 

Les mots réservés

and
else
in
or
to
asm
end
inherited
packed
try
array
except
inline
procedure
type
begin
exports
interface
program
unit
case
file
label
record
until
const
finally
library
repeat
uses
constructor
for
mod
set
var
destructor
function
nil
shl
while
div
goto
not
shr
with
do
if
object
string
xor
downto
implementation
of
then

 

La syntaxe

Le Pascal ne tient pas compte de la casse (minuscule/majuscule).
Une ligne de code peut être écrite sur plusieurs lignes.
Le séparateur décimal est le point.

 

Le style de codage

Voici quelques conseils pour rendre le code plus lisible :

  • placer les paramètres d’une fonction ou procédure sur des lignes séparées
  • formatter le code source suivant le standard " bonne impression " : indentation avec deux espace de chaque bloc de code. Ce format est utilisé dans le code source Delphi, les manuels et les exemples d’aide.

 

Les commentaires

Exemple :


  { ceci est un commentaire }
  (* un autre commentaire *)
  // le reste de la ligne est ignoré (seulement depuis Delphi 2)

Pour obtenir les accolades sur un clavier n’en disposant pas, il faut utiliser : Alt 123 et Alt 125.

Remarque : si une accolade ouverte ou la parenthèse-étoile sont suivies du caractère dollar ($), cela devient une directive de compilation car les directives de compilation sont des commentaires.

Exemple :

{$X+ avec un commentaire} // ceci est autorisé

Variables et constantes

La déclaration d’une variable se fait dans une clause particulière du programme, identifiée par le mot clé var.

Les contraintes de formation d’un identificateur sont : seul les 63 premiers caracteres sont pris en compte, les caractères accentués sont interdits, la différence minuscule/ majuscule n'est pas pris en compte, il doit commencer par une lettre ou un souligné.

Il est possible de déclarer plusieurs variables du même type en une seule ligne, chacunes étant séparées par une virgule.

Exemple :

var
  valeur : integer ;
  fin : boolean ;
  car1, car2 : char ;
begin
  valeur :=10 ;
  fin :=True ;

 

Portée d'une variable :

le niveau procédure : les variables sont locales à la procedure ou a la fonction ou elles sont déclarées et sont stockées dans le segment de pile.

le niveau unité : les variables déclarées dans la section var de l'uniré sont globales à toutes les procédures et fonctions de l'unité. Elles sont stockées dans le segment de données du programme.

On peut accéder aux variables déclarées dans la section interface d'une unité à partir d'un autre point du programme, ou d'un autre programme, en déclarant la cette unité dans la section uses de l'unité appelante

Le Pascal Objet permet l’utilisation d’expression constantes : l'affectation d'une valeur à une constante s'effectue en même temps que sa déclaration.

const ident1 : type1 = valeur1;

Exemple :

const
  tva := 18.6 ; 
  initiales : string[2] = 'JM'   age : byte = 24;

 

Les types de données

 

Les types de données prédéfinis

Il existe 3 groupes de types de données : les ordinaux, les réels et les chaines

 

Les types ordinaux

Les types ordinaux sont fondés sur un concept d’ordre qui permet de faire des comparaisons, d'obtenir la valeur suivante ou précédente et de calculer la plus grande et la plus petite valeur possible.

La liste des types ordinaux est la suivante :

  • Integer, Cardinal, Shortint, SmallInt, Longint, Byte, Word
  • Boolean, ByteBool, WordBool, LongBool
  • Char, ANSIChar, WideChar
Type Intervalle Longueur
Shortint -128 .. 127 1 octet (8 bits)
Integer -32768 .. 32767 2 octets
Longint -2147483648 .. 2147483647 4 octets
Byte 0 .. 255 1 octets
Word 0 .. 65535 2 octets
Boolean 0, 1 (ou False, True) 1 octets
Char 0 .. 255 1 octets

Byte et Word réprésentent des valeurs non signées

Integer et Cardinal utilise la représentation native ( 2 octets sur plateforme 16 bits, 4 octets sur 32 bits) signée et non signée respectivement.La taille des entiers varient selon le microprocesseur et le système d’exploitation (ex : un entier est codé avec 2 octets sous Windows 3.x, 4 octets sous Window 95).

Cela peut poser des problèmes lors de la sauvegarde dans un fichier d’un entier sur une plateforme et la relecture sur une autre. Il faut utiliser un type de donnée qui soit indépendant de la plateforme utilisée ( ex : LongInteger ou SmallInteger). Mais pour une utilisation normale il est préférable d’utiliser une représentation native.

Les 4 booléens sont utiless pour la programmation avec les API Windows.

Les 3 types de caractères sont utilisés pour indiquer des caractères 8 bits (ANSI) ou 16 bits(UniCode).

Char correspond à ANSIChar dans les versions 16 et 32 bits.

Contrairement à Windows NT, Windows 95 n’a qu’un support limité de l’Unicode (le nouvel ensemble de caractère capable de représenter les lettres de chacun des alphabets connus en utilisant 16 bits au lieu de 8).

Le type char est un entier compris entre 0 et 255, interpreté comme une lettre selon le code ASCII. Une affectation du type caractère :=’q’ ; est autorisée. La variable contiendra la valeur ASCII de la lettre sous forme d’entier.

Il existe differentes routines systèmes pour la gestion des types ordinaux :

Routine Rôle
Dec Décrémente la variable passée en paramètre par un ou par la valeur du second paramètre éventuel
Inc Incrémente la variable passée comme paramètre d’un ou de la valeur spécifiée 
Odd Retourne vrai si l’argument est un nombre impair
Pred Retourne le prédécesseur de l’argument dans l’ordre déterminée par le type de donnée
Succ Retourn le successeur
Ord Retourne un nombre indiquant l’ordre de l’argument dans l’ensemble des valeurs du type de données
Low Retourne la plus petite valeur du type ordinal passé en paramètre
High Retoune la plus grande valeur du type ordinal passé en paramètre

 

Les types réels

Le type réels representent des nombres en virgule flottante : Single, Real, Double, Extended, Comp, Currency  

Type Intervalle Longueur  Nb chiffres pris
en compte
Real 2.9 * 10-39 .. 1.7 * 1038 6 octets  11 - 12 
Single 1.5 * 10-45 .. 3.4 * 1038 4 octets  7 - 8 
Double 5.0 * 10-324 .. 1.7*10328 8 octets  15 - 16 
Extended 3.4 * 10-4932 .. 1.1 * 104932 10 octets  19 - 20 
Comp -263+1 .. 263-1 8 octets  19 -20 

Comp est en fait un type entier traité comme un type réel permettant de décrire de très grands entiers

Currency (disponible uniquement depuis Delphi 2) indique un type en virgule flottante avec quatre chiffres décimaux et une représentation 64 bits pour représenter des valeurs monétaires énormes sans perdre le moindre chiffre significatif.

Remarque : Delphi utilise des nombres réels dans les types de données TDateTime pour stocker jour, mois, heures, minutes, secondes et millisecondes dans une seule variable.

 

Les types de données spécifiques à Windows

Ces types de données ne font partie du langage Pascal mais des bibliothèques de Windows.

Thandle représente un Handle et est un rédéfinition du type Cardinal. Un Handle est un code interne qui est une référence vers un élément spécifique géré par le système. Il est utile pour appeler une API non supportée par Delphi.

TColorRef représente une référence couleur et est une redéfinition du type LongInt.

 

Le type charactère

Le type char qualifie un caractère alphanumérique. Les données de type char sont notées entre 2 apostrophes.
Affectation d'un caractere ASCII à une variable ou une contante de type char : c := #7;
Plusieurs fonctions de l'unité System permettent de manipuler les caractères :

Chr (X : Byte) : Char; Obtenir un caractère à partir de son code ASCII
UpCase (c : Char) : Char; Convertir un caractère compris entre 'a' et 'z' en majuscule

 

Le type de donnée Variant

La version 32 bits de Delphi introduit une nouvelle approche pour gérer les variables pour supporter OLE Automation : le type Variant. Ces variables peuvent stocker n’importe quel type de données. Les variants sont vérifiés et calculés en mode exécution.

Exemple :

var
  v : Variant ;
begin
  v :=10 ;
  v :=’Hello’ ; ...

Une fois la valeur du variant affectée, on peut la copier vers n’importe quel type de données compatible ou non sachant que dans ce dernier cas, Delphi tente une conversion, si c’est possible.

Les variants stockent à la fois le type d’information et les données et permettent un certain nombre d’opérations à l'execution. Ceci peut être pratique mais cela s’avère souvent lent et peut sûr : il faut réserver leurs utilisation pour utiliser OLE Automation.

 

Transtypage et conversion de types

Pour assigner une variable à une autre variable d’un autre type il faut utiliser le transtypage (Casting).

Exemple :

var
  n : integer ;
  c : char ;
  b : boolean ;
begin
  n :=Integer(‘X’) ;
  c :=Char(n) ;
  b :=Boolean(0) ;

On peut généralement effectuer un transtypage entre deux types de données de même taille.

Il est possible d’utiliser une routine système de conversion de type :

Routine But
Chr Convertit un ordinal en caractère
Ord Convertit la valeur d’un type ordinal en nombre indiquant son ordre
Round Convertit la valeur d’un type réel en celle d’un type entier, en arrondissant sa valeur
Trunc Convertit la valeur d’un type réel en celle d’un type entier, en tronquant sa valeur
Frac Renvoie la décimales d’un réel
Int Renvoie la partie entière d’un réel
IntToStr Convertit un nombre en chaine
IntToHex Convertit un nombre en chaine, avec une représentation hexadecimale
StrToInt Convertit une chaine en nombre, en affichant une erreur si la chaine est incorrecte
StrToIntDef Convertit une chaine en nombre, en utilisant une valeur par défaut si la chaine est incorrecte
Val(s : string ; i , j : Integer) Convertit une chaine s en nombre i. j contient en cas d’erreur la position du premier caractère non convertie
Str Convertit un nombre en chaine, en utilisant des paramètres de formatage
StrPas Convertit une chaine terminée par un caractère Null en chaine de type Pascal
StrPCopy Convertit (copie) un chaine de style Pascal en chaine terminée par un caractère Null
StrPLCopy Convertit (copie) une portion de chaine de style Pascal en une chaine terminée par un Null

 

Les types de données définis par l’utilisateur

On peut définir ses propres type de données au moyen de " type constructors " tel que les intervalles, plages, tableaux, énumerations, pointeurs et ensembles.

La déclaration d'un type doit se faire dans une clause d'initialisation par le mot clé type pouvant se trouver dans la clause interface d'une unité (pour une déclaration publique) ou dans la section implementation (pour une déclaration locale à l'unité), ou bien encore dans une fonction ou une procedure si le type doit rester privé à ce sous programme.

Ces types peuvent recevoir un nom pour usage ultérieur ou être appliqués directement à une variable :

Exemple :

type
  majuscules = ‘A’ .. ‘Z’ ;
  mdate = record
    jour : byte ;
    mois : Byte ;
    annee : Integer ;
  end ;

  couleurs = (bleu, vert, violet, noir) ;
  lettres = set of char ;
var
  tableau : array [ 1 .. 31 ] of Byte ;
  palette : set of couleurs

En général il faut éviter d’utiliser des types non nommés car on ne peut pas les passer comme paramètres ou definir d’autre variable du même type.

 

Les intervalles

Un intervalle se définit comme un ensemble ordonné de valeurs limitées par une borne inférieure et par une borne supérieure. Ces valeurs appartiennent elles-même à un type de données (prédéfini ou utilisateur) appéllé type de base ou type hote. L'opérateur qui permet la déclaration du type intervalle est .. (double point), selon la syntaxe suivante :

id_type : constante_inferieure .. constante_supérieure

avec nécessairement constante_inférieure < constante_supérieure

Exemple :

type
  chiffre = 0 .. 9;
var
  c : chiffre; c := 3;

Remarque : on peut également utiliser les membres d'une énumération pour définir un intervalle

exemple :

type
  jours = (lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche);
  jour_ouvrables = lundi .. vendredi;

Un type intervalle définit une plage de valeurs à l’intérieur d’une plage d’un autre type.

Exemple :

type
  majuscules = ‘A’ .. ‘Z’ ;

Une fois définit on peut lui affecter une valeur de cette plage sinon un message d’erreur survient " l’expression constante viole les limites de la plage allouées ".

L’option " Verification des plages " de la page Option de compilation est très utile lors de la phase de développement pour vérifier d'eventuel débordement..

 

Les Enumérations.

Les types énumérés constituent un autre type ordinal défini par l’utilisateur. Au lieu d’indiquer une plage d’un type existant, on liste les valeurs possible pour le type. Une énumération est une liste de valeurs

Exemple :

type
  couleurs = (bleu, vert, violet, noir);

Chaque élément d'un type énuméré est associé à une valeur numérique qui correspond à sa position dans la liste des éléments, le premier élément possédant la valeur 0. La déclaration de type utilise l'opérateur () (parenthèses) selon la syntaxe suivante :

id_type = (id_1 , id_2 , id_3 , ... , id_n);

Exemple :

type
  jours = (lundi,mardi,mercredi,jeudi,vendredi,samedi,dimanche);
var
  x : jours;
begin
  x := lundi;

Chaque valeur de la liste est associé à une valeur ordinale qui débute à zéro. La fonction Ord appliquée à une valeur de type énumérée retourne une valeur qui débute par 0. La représentation interne des type énumérés peut différé : par défaut Delphi utilise une représentation 8 bits sauf si il y a plus de 256 valeurs. La directive $Z permet de demander une représentation plus grande.

 

Les ensembles (Set)

Un type set indique l’ensemble des possibilité d’un type ordinal, souvent une énumération ou un intervalle, puisque le type de base ne peut contenir plus de 256 valeurs. Chaque ensemble contient aucune, une ou plus d’une de toutes les valeurs possibles dans la plage de type ordinal.

Exemple :

type
  lettres = set of majuscules ;
var
  lettre : lettres ;

On peut assigner des valeurs aves les instructions suivantes

Exemple :

lettre := [ ‘A’, ‘B’, ‘C’] ; // assignation de plusieurs valeurs
lettre := [ ‘A’ ], // assignation d’une seule valeur
lettre := [] ; // assignation de l’ensemble vide

Dans Delphi, les ensembles sont souvent utilisés pour indiquer des drapeaux non exclusifs..

 

Les tableaux

La définition d'un type tableau unidimentionnel consiste à spécifier le type de base et le type d'indice du tableau : Pour définir un tableau, on utilise deux constantes de type ordinal pour spécifier les bornes du tableau :
type_tableau = array [ type_indice ] of  type_composant;

Exemple :

type
  tabentiers = array [ 1 .. 100 ] of integer;

Le type des membres du tableau, que l'on appelle souvent des cellules, peut être simple ou structuré, à l'exception du type fichier

Pour obtenir un tableau indéxe à partir de zéro, spécifié la valeur 0 comme borne inférieure.

Exemple :

ligne = array [ 0 .. 100 ] of char;

Exemple de déclaration d'un tableau à deux dimensions :

type
  ecran = array [ 1 .. 24 , 1 .. 80 ] of char;
var
  ec : ecran;

Un tableau défini un nombre fixe d’éléments d’un certain type.

Utiliser les fonctions Low et High pour connaître les bornes d’un tableau. L’utilisation de ces fonctions est fortement recommandée surtout dans les boucles pour permettre au code de rester indépendant de la plage du tableau. Ces fonctions sont traduites par des constantes au moment de la compilation ce qui ne dégrade pas les temps d’execution.

 

Les enregistrements

Les engeristrements permettent de regrouper des types différents au sein d'une même structure. La liste des champs composant l'enregistrement se place entre les mots clés Record et End.

Exemple :

type
  individu = record
  nom : String;
  prenom : String;
  age : Byte;
  end
var
  ind : individu;
Begin
  ind.nom := 'Durand';

Exemple :

type
  mdate = record
  jour : 1 .. 31;
  mois : (janvier, fevrier, mars, avril, mai, juin, juillet, aout, septembre, octobre, novembre, decembre);
  annee : 1910 .. 2010;
  end;

L'instruction With permet de référencer de façon rapide les membres d'un enregistrement en evitant de répéter le nom de la variable d'enregistrement.

With nom_variable_enregistrement Do instructions End;

Exemple  :

with ind do
begin
  nom := 'Durand';
  age := 21;
end;

Un type enregistrement définit un collection fixe d’élément de types différents.

Exemple :

type
  pdate = record
  year : Integer ;
  month : byte ;
  day : byte ;
end ;
var
  anniversaire : date ;
begin
  anniverssaire.year :=1996 ;

Les enregistrements peuvent également posséder une partie variant qui permet d’interpréter une même zone mémoire differement.

 

Les pointeurs

Un pointeur définit une variable qui tient en mémoire l’adresse d’une autre variable d’un certain type.

La définition d’un pointeur utilise la caractère spécial carret (^) :

Exemple :

type
  pointerversint := ^integer ;

Une fois la variable pointeur definie, on peut lui assigner l’adresse d’une autre variable du même type en utilisant l’opérateur @ ou créer une nouvelle variable sur le tas avec l’opérateur New.

Si un pointeur n’a pas de valeur on peut lui affecter la valeur Nil. Ce test est souvent utiliser car déreferencer un pointeur invalide provoque une erreur de protection générale.

Exemple :

var
  p1,p2 : ^integer ;
  n : integer ;
begin
  n :=10 ;
  p1 := @n ;
  new(p2) ;
  p1^ :=20 ;
  p2^ :=P1^ * 20 ;
  dispose(P2) ;
end ;

La commande New essaie de trouver un espace mémoire correspondant à la taille de la variable. Le pointeur contient ensuite l’adresse de la zone mémoire réservée. S’il n’y a pas assez de place pour allouer la variable dynamique, une exception EOutOfMemory est provoquée.

Pour pouvoir accéder au contenu de la variable sur laquelle il pointe, il faut déférencer la variable pointeur :

pointeur^ :=valeur ;

La commande Dispose libère la mémoire allouée. La portée d’une variable pointeur dynamique est comprise entre les instructions New et Dispose.

Il existe un type de données pointeurs qui indique des pointeurs sans type. Avec un pointeur sans type (la taille de la mémoire variable n’est pas définie) il faut utiliser GetMem au lieu de New.

Les pointeurs non typés sont définis par le mot clé : Pointer

Exemple :

var
  pointeur_non_type : Pointer ;

Ces pointeurs sont exclus du controle du compilateur : une utilisation erronée provoque un plantage de l’application.

 

Le type fichier (file)

Un autre constructeur de type en Pascal est le type fichier.

Exemple :

type 
  intfile = file of integer ;

 

Les chaines de caractères

 

Les chaines Pascal

Le type String represente une chaine de caractere possédant une longueur variable et une taille fixe qui ne peut pas dépasser 255 caracteres, ce qui est également la valeur par défaut.

Les chaines de caracteres doivent être délimitées par des apostrophes. Si la chaine contient elle même une apostrophe, il suffit de doubler l'apostrophe :

s:='l''apostrophe'; 

Chaque caractère de la chaine est repéré par un index . Le premier caractère possèdent la position 1 (ex: s[1] vaut 'l').

La première cellule d'une chaine possèdent la longueur de celle-ci (ex: s[0] vaut 12).

Déclaration d'une chaine de caractères : sNom : String[30];
(String; equivaut à String[255];).

Pascal possède une façon de gérer les chaines tandis que Windows en possède une autre. Pour accroitre la confusion la version 32 bits de Delphi introduit le support de chaines longues.

En Pascal, la chaine typique est une séquence de caractères possèdant un compteur de taille à son origine. Chaque chaine possède une taille fixée par défaut à 255

Exemple :

var
  nom : string ; // chaine de 255 caractères
  titre : string[50]; // chaine de 50 caractères

Shortstring est équivalent au chaine Pascal limitée à 255 caractères.

Les chaines Pascal sont limitées à 255 caractères. Une chaine est presque un tableau :

Exemple :

  premier_car :=nom[1] ;

Par défaut, la déclaration s : string alloue l’espace mémoire nécessaire à une variable de type AnsiString. Cette option peut être désactivée dans le menu Projet/Options, page compilateur, groupe Option de syntaxe, désactiver la case Chaines vastes.

 

Les opérateurs de chaine de caractères

Il est possible de concatener deux chaines avec l’opérateur +.

L'opérateur + permet de concatener deux chaines de caractères (type String) ou deux caractères (type Char) en une nouvelle chaine dont la taille de doit pas dépasser 255 caractères pour les ShortString, sinon elle sera tronquée. Il n’y a pas de problème acec les AnsiString.

Les opérateurs de comparaison = , <> , < , > , <= , >= peuvent également être employés avec des chaines de caractères. Les chaines sont comparées d'après la valeur des codes ASCII qui la composent. On peut aussi comparer un type String avec un type Char, car dans ce cas ce dernier est automatiquement considéré comme une chaine de caractère dont la longeur vaut 1.

 

Les fonctions sur les chaines de caractères
Length(S : String) : Integer; obtenir la longeur actuelle d'une chaine de caractères
High(X) : Integer; obtenir l'élément ayant l'index le plus élevé
Copy(S : String; Index , Count : Integer) : String; extraire d'une chaine une sous chaine d'une longeur donnée à partir d'une position donnée. Si l'on tente d'extraire plus de caractères qu'il n'est possible, la sous chaine est automatiquement tronquée. Si la position de l'index est supérieur à la longueur de la chaine, on obtient une chaine vide.
Delete(S : String ; Index , Count : Integer); suppression une sous chaine à partir d'une position et d'une longueur donnée. La chaine de caractères doit être nécessairement stockées dans une variable.
Pos(Substr : String ; S : String) : Byte; localiser une sous chaine. La valeur retournée est l'index de la première occurrence de substr dans s. La valeur 0 est retourné si la sous chaine n'est pas rencontrée.
CompareStr(S1 , S2 : String) : Integer; comparaison de chaines. Retourne 0 si les deux chaines sont identiques. La fonction retourne une valeur positive si S1 est supérieur à S2, sinon elle retourne une valeur négative.
CompareText( S1 , S2 : String) : Integer; comparaison de chaine sans tenir compte de la difference minuscule/majuscule
UpperCase(const s : String) : String; mettre une chaine en majuscule
LowerCase( const s : String) : String; mettre une chaine en minuscule
Str( i : Integer ; s : String); convertit une valeur numérique en chaine
Trim( s : String ) : String; Supprimer les espaces en préfixe et en suffixe
TrimLeft( s : String ) : String; Supprimer les espaces en préfixe
TrimRight(s : String ) : String; Supprimer les espaces en suffixe

 

Les chaines Pascal longues

Delphi 2 introduit le support des chaines longues pour remédier aux limites des 255 caractères.

Les ShortStrings correspondent aux chaines Pascal normale, limitée à 255 caractères et correspondent aux chaines de la version 16 bits. Chaque élément d’une chaine courte est de type ANSIChar (le type de caractère standard).

ANSIString correspond aux chaines longues. Ces chaines sont allouées dynamiquement et sont pratiquement illimitées. Elles sont fondées sur le type ANSIChar.

Dans Delphi 2, si on utilise le type de donnée chaine, on obtient soit une chaine courte soit une chaine ANSI selon la valeur de la directive $H du nouveau compilateur. La valeur par défaut est $H+ qui se réfère aux chaines longues (ANSIString utilisé aussi par la VCL).

Ces nouvelles chaines sont allouées dynamiquement : une chaine est un pointeur vers la chaine réelle. Lorsque l’on fait une copie de la chaine, c’est le pointeur qui est copié ce qui rend l’opération très rapide. Dès que l’on change le contenu de l’une de ces chaines, la chaine est dupliquée et seules les valeurs dupliqués sont affectées par le changement. Ceci est possible grace un à mécanisme de comptage des références du système, qui peut également libérer la mémoire lorsqu’une chaine en mémoire n’est plus utilisée (compteur de référence à zéro).

La chaine est allouée à nouveau lorsque l’on change la taille, ce qui implique une copie complète de la chaine si la chaine ne peut pas croitre au même endroit. On peut affecter la taille maximale de la chaine avec la procedure SetLength en allouant la quantité de mémoire souhaitée :

Exemple :

SetLength(string1, 2000) ;

Bien que rarement nécessaire, cela peut réellement accroitre le code liée aux chaines. Lors de l’allocation d’un grande chaine, le système réserve l’espace d’adresse pour la chaine mais ne l’alloue pas réellement jusqu’au moment voulu.

Le seul cas on l’on doit allouer une mémoire aux chaines longues en utilisant SetLength est lorsque cette chaine doit être passée en paramètre à une fonction API.

Les chaines longues sont terminée par un caractère Null et sont plainement compatible avec les chaines Windows.

 

Conversions de chaines

StrPas convertit une chaine terminée par un null en chaine Pascal courte.
StrPCopy réalise l’opération en sens inverse.

Pour convertir une chaine Pascal longue en Pchar, un simple transtypage est suffisant.

Exemple : copier la légende d’un forme en chaine en utilisant le fonction API GetWindowText

var
  s1 : string ;
begin
  SetLength(s1,100) ;
  GetWindowsText(button1.Handle, PChar(s1), Length(s1));
end;

Si l’allocation de mémoire de SetLength échoue, le programme risque d’interrompre tout le système.

Pour passer un paramètre à une API il suffit d’utiliser un transtypage vers le PChar :

Exemple : SetWindowsText(Handle, PChar (Label1.Caption)) ;

Il existe des problèmes de conversions de chaines longues en PChar. Après la conversion on devient responsable de la chaine et de son contenu.

Exemple :

var
  s1 : string;
begin
  SetLength(s1,100) ;
  GetWindowsText(Handle,PChar(s1),Length(s1)) ;
  s1 :=s1+’ suite du texte’ ;
  button1.caption :=s1 ;
end;

Ce programme est compilé sans problème mais le titre du bouton ne contient pas la constante chaine ajoutée. Lorsque Windows écrit vers la chaine, il n’établit pas la dimension de la chaine Pascal de façon adaptée. Delphi peut utiliser cette chaine en sortie et comprendre où elle se termine grace au caractère null mais l’ajout de caractère ce fait après le null.

Il faut reconvertir la chaine en chaine Pascal.

Exemple : s1 := string(s1) ;

Mais le système l’ignorera car elle est inutile. Pour obtenir une chaine longue, on doit refaire un transtypage de la chaine vers un PChar et laisser Delphi la reconvertir correctement en chaine.

Exemple :

s1 := string(PChar(s1)) ;

 

Les instructions Pascal

 

Expressions et opérateurs

Opérateur Rôle
@ adresse de (retourne un pointeur)
not non booléen
* multiplication arithmétique ou intersection d’ensemble
div division de réel (div est plus rapide que /)
mod division en partie entière
as typecast
and et booléen
shl glissement à gauche
shr glissement à droite
+ addition, union d’ensemble, concaténation de chaines, valeur positive, addition d’offset
or ou booléen (l’une ou l’autre des conditions doit être vérifiée)
xor ou exclusif booléen (soit l’une soit l’autre des conditions doit être vérifée)
= test si égal
<> test si inégal
< test si moins que
> test si plus grand que
<= test si moins grand que ou egal, ou sous ensemble d’un ensemble
>= test si plus grand que ou égal, ou surensemble d’un ensemble
in test si élément dans ensemble
is test si type compatible

 

Les opérateurs d’ensemble

L'union d'ensembles : +
La différence : -
L’intersection : *
Le test membre de : in

Exemple : style d’un fonte

  style := style + [fsBold] ;
  style := style - [fsUnderline] ;

 

Instructions simples et composées

Un instruction simple ne contient pas d’autres instructions. Elles sont séparées par un ;
Une instruction composée est déliminée par Begin .. End ;. Le point virgule après la dernière instruction n’est pas obligatoire.
Le ; est en faite une instruction null.

 

Les structures de controle

 

Les instructions conditionnelles

if condition then instruction ;

if condition then instruction
else instruction ;

Pas de ; avant le else.

case variable_ordinale of
valeur1 : instruction ;
valeur2 : instruction ;
else : instruction ;
end ;

L’utilisation de case n’est possible que si l’on compare une variable à un type ordinal : Integer, Char ou Boolean.
Il est possible de comparer une variable à une plage de valeur :
case c of
' a' .. 'f' :

Mais Delphi refuse de compiler les plages qui se superposent.
Il est possible de faire correspondre plusieurs valeurs au libellé du case :
case c of :
'a','f' :

Les valeurs doivent obligatoirement correspondre à des valeurs littérales et non des variables.

 

Les instructions itératives

For compteur := debut To fin Do instruction

For compteur := debut DownTo fin Do instruction

While expression Do instruction

Repeat instruction Until expression

Le code de l’instruction Repeat est toujours exécuté au moins une fois.

 

Procédure système :
Break Permet d’interrompre une boucle
Continue Permet de sauter de façon directe au test de la boucle ou à l’incrémentation du compteur
Exit Permet de sortir de la fonction en cours
Halt Permet de terminer le programme

 

L’instruction with

L’instruction With est un raccourci. Lorsque l’on réfère à un enregistrement ou à un objet, au lieu de répéter son nom à chaque fois on peut utiliser l’instruction with.

 

L’intruction goto

L’instruction goto du Pascal Objet renvoie à une étiquette qui doit être préalablement définie dans la clause var de la procédure

Exemple :

procedure TForm1.Button1Click(Sender : TObject);
var
  s : string ;
  label retour ; // définition d’une étiquette
begin
  ...
  retour :
  ....
  if s=’’ then goto retour ;
  ....
end ;

L'instruction goto est à éviter.

 

Les procédures et les fonctions Pascal

 

Les procedures

La déclaration d'une procedure se compose d'un en-tête suivi d'une liste d'instruction délimitée par les mots clés Begin et End. L'en-tête est également appellé prototype.

exemple :

procedure test;
begin
...
end;

Pour executer cette procedure il suffit de saisir : test;

Lorque l'en-tête d'une procedure ou d'une fonction a été déclarée dans la section interface de l'unité, il n'est pas obligatoire de reprendre dans la partie implementation les arguments déclarées publiquement

Exemple :

unit utest;
interface
  procedure ptaxe(var r : real);
implementation
  procedure ptaxe;
  begin
      r := r * 0.186;
  end;

Toutes les déclarations effectuées à l'intérieur de la procedure (variables, types, constantes, étiquettes, ...) sont locales à cette procedure . Ces déclarations locales s'effectuent de la façon suivante :
Procedure nomproc [(listearguments)]
Type
...
Const
...
Var
...
Begin
...
End;

 

Les arguments d'une procedure

[ var | const ] nomparametre [ : type ]

Dans la déclaration d'une procedure ou d'une fonction, lorsque la liste comprend plusieurs arguments, chaque argument passé doit être séparé par le caractère ; (point virgule). Par contre, lors de l'appel du sous programme, les arguments passés doivent être séparés par le caractère , (virgule).

 

Le passage d'argument par valeur et par référence

Dans la cas d'un passage de paramètre par valeur, c'est en fait une copie de la donnée qui est transmise. Toute modification effectuée sur la donnée en question, à l'intérieur de la procedure appelée, n'aura aucun effet sur la valeur de cette donnée, puisque les modifications n'auront été justement effectuées que sur cette copie et non sur la valeur originale. Inversement, lorque vous transmettez un argument par référence, ce n'est pas la valeur (ou une copie de celle-ci) qui est passée à la procedure, mais l'adresse de cette donnée. C'est pourquoi tout traitement effectué sur le paramètre peut accéder à la donnée originale en mémoire et peut dont effectuer des modifications sur la valeur initiale. Un paramètre transmis par référence est précédé du mot clé var, alors qu'un paramètre transmis par valeur ne possède aucun mot clé.

 

Les paramètres constants

Les paramètres dits constants désignent un type de paramètres dont les valeurs ne peuvent être utilisées qu'en lecture. Si vous déclarez un paramètre  avec le mot clé Const, il devient en conséquence impossible d'affecter une quelconque valeur à l'argument actuel. Si vous tentez de modifier la valeur de l'argument, le compilateur génère une erreur. Le compilateur optimise le code lorque les paramètres sont des types structurés ou des chaines de caractères.

 

Les fonctions

Les fonctions retourne une valeur correspodante au resultat du traitement. Une fonction peut donc apparaître à l'intérieur d'une expression, ce qui ne peut pas être le cas d'une procédure.

function nomfonction [(listearguments)] : type;

Exemple :

function fdouble(quantite : integer) : integer;
begin
  fdouble := quantite *2;
end;

Si la fonction ne possède aucun argument, les parenthèses ne devront apparaitre ni dans l'entete, ni dans l'appel de la fonction.

Chaque fonction comprend par défaut une variable result qui stocke le résultat de la fonction. Depuis Delphi 2, il est préférable d’utiliser cette variable plutôt que le nom de fonction pour donner le résultat du traitement.

Les fichiers texte

Lorsque l’on souhaite utiliser un fichier texte, il faut suivre cinq étapes.

Déclaration d’une variable de fichier texte

 nomdevariable : TextFile ;

Exemple :

var
  source : TextFile ;

 

Affecter un fichier à une variable

AssignFile(nomdevariable,’nomdefichier’) ;

Exemple :

AssignFile(source,’c :\fichier.txt’) ;

Le nom du fichier est passé en paramètre sous forme de chaine de caractères. Si le fichier ne se trouve pas dans le répertoire courant ou le chemin de recherche, il faut indiquer le chemin absolu du fichier. On peut faire référence à un fichier qui n’existe pas pour le créer.

 

Ouvrir un fichier texte

Delphi possède 3 instructions pour ouvrir un fichier :

  • Rewrite(nom_de_variable) : permet de créer un fichier qui n’existe pas. Si le fichier existe déjà, il sera simplement écrasé. Le contenu du fichier ne sera perdu qu’à partir du moment où l'on écrit des données dans le fichier.
  • Reset(nom_de_variable) : permet d’ouvrir un fichier en lecture seul. Si le fichier à ouvrir n’existe pas il y aura une erreur d’exécution.
  • Append(nom_de_variable) : permet d’ouvrir un fichier en écriture. Les données insérées le seront en fin de fichier. Si le fichier n’existe pas, l’application génère une erreur d’execution.

 

Lire un fichier texte

La fonction Readln permet de lire un fichier texte ligne après ligne. Le " ln " fait référence à la séquence CR-LF.

Readln(variablesource,variabledestockage) ;

Exemple :

var
  s : string ;
  source : TextFile ;
begin
  Readln( source , s ) ;
end ;

La fonction Eof permet de détecter la fin d’un fichier. Elle prend comme paramètre la variable qui pointe sur le fichier. Eof renvoie True lorsque la fin du fichier est atteinte.

Exemple :

  while not Eof(source) do

 

Ecrire dans une fichier texte

La fonction Writeln permet d’écrire un fichier texte.

Writeln(variablesource,variabledestockage) ;

Il existe une procedure Write qui permet d’écrire une ligne en plusieur fois mais il est indispensable d’utiliser Writeln à la fin pour passer à la ligne.

 

Fermeture d’un fichier

La fermeture des fichiers est importaent car elle libère les ressources exigées par le fichier et permet une réelle écriture des données sans risque de perte d’information.

CloseFile(variablesource) ;

 

Test d’existence d’un fichier

FileExists(‘nomdeficheir’) : Boolean

Exemple :

var
  F : TextFile ;
  ...
  AssignFile(F,’c :\fichier.txt’) ;
  if FileExists(‘c :\fichier.txt’)  then Append( F )
  else Rewrite( F ) ;
  ...
  Close( F ) ;

 

Les directives de compilation pour gérer les erreurs d’E/S

Pour éviter que le déroulement d’une application ne s’interrompe en cas d’abscence d’un fichier, il faut désactiver la vérification d’entrée sortie en utilisant la directive {$I+/-}

Exemple :

var
  F : TextFile ;
  I : Integer
  ...
  AssignFile(F,’c :\fichier.txt’) ;
  {$I-}
  Append(F) ;
  {I+}
  I :=IOResult ;
  if( I = 2 ) then Rewrite( F ); // le fichier n’existe pas
  ...
  CloseFile( F ) ;

Le résultat d’une évaluation est stockée dans la variable IOResult déclarée implicitement. La valeur de la variable doit être stockée dans une autre variable car le simple fait d’appeler IOResult la vide de son contenu.