Section courante

A propos

Section administrative du site

Utilisation de chaînes de caractères terminées par NULL

Le Turbo Pascal prend en charge une classe de chaînes de caractères appelées chaînes de caractères à terminaison nulle. Avec la syntaxe étendue de Turbo Pascal et l'unité Strings, vos programmes peuvent utiliser des chaînes de caractères terminées par nulle en se référant simplement à l'unité Strings avec l'instruction USES dans votre programme.

Qu'est-ce qu'une chaîne de caractères terminée par nulle ?

Le compilateur entrepose un type de chaîne de caractères Turbo Pascal traditionnel sous la forme d'un octet de longueur suivi d'une séquence de caractères. La longueur maximale d'une chaîne de caractères Pascal est de 255 caractères et une chaîne de caractères Pascal occupe de 1 à 256 octets de mémoire. Une chaîne de caractères terminée par un zéro n'a pas d'octet de longueur; au lieu de cela, il se compose d'une séquence de caractères non nuls suivis d'un caractère NULL (#0). Il n'y a pas de restriction inhérente à la longueur d'une chaîne de caractères terminée par nulle, mais l'architecture 16 bits de DOS impose une limite supérieure de 65 535 caractères.

Fonctions de l'unité de chaînes de caractères

Le Turbo Pascal n'a pas de routines intégrées spécifiquement pour la gestion des chaînes de caractères terminées par nulle. Au lieu de cela, vous trouverez toutes ces fonctions dans l'unité Strings. Parmi eux se trouvent StrPCopy, que vous pouvez utiliser pour copier une chaîne de caractères Pascal dans une chaîne de caractères terminée par un nulle, et StrPas, que vous pouvez utiliser pour convertir une chaîne de caractères terminée par un nulle en une chaîne de caractères Pascal. Voici une brève description de chaque fonction :

Nom Description
StrCat Ajoute une chaîne de caractères source à la fin d'une chaîne de caractères de destination et renvoie un pointeur vers la chaîne de caractères de destination.
StrComp Compare deux chaînes de caractères, S1 et S2, et renvoie une valeur inférieure à zéro si S1 < S2, zéro si S1 = S2 ou supérieure à zéro si S1 > S2.
StrCopy Copie une chaîne de caractères source dans une chaîne de caractères de destination et renvoie un pointeur vers la chaîne de caractères de destination.
StrECopy Copie une chaîne de caractères source dans une chaîne de caractères de destination et renvoie un pointeur vers la fin de la chaîne de caractères de destination.
StrIComp Compare deux chaînes de caractères sans respecter la casse.
StrLCat Ajoute une chaîne de caractères source à la fin d'une chaîne de caractères de destination, en s'assurant que la longueur de la chaîne de caractères résultante ne dépasse pas un maximum donné, et renvoie un pointeur vers la chaîne de caractères de destination.
StrLComp Compare deux chaînes de caractères pour une longueur maximale donnée.
StrLCopy Copie jusqu'à un nombre donné de caractères d'une chaîne de caractères source vers une chaîne de caractères de destination et renvoie un pointeur vers la chaîne de caractères de destination.
StrEnd Renvoie un pointeur vers la fin d'une chaîne de caractères (c'est-à-dire un pointeur vers le caractère nul terminant une chaîne de caractères).
StrDispose Supprime une chaîne de caractères précédemment allouée.
StrLen Renvoie la longueur d'une chaîne de caractères.
StrLIComp Compare deux chaînes de caractères pour une longueur maximale donnée sans respect de la casse.
StrLower Convertit une chaîne de caractères en minuscules et renvoie un pointeur vers la chaîne de caractères.
StrMove Déplace un bloc de caractères d'une chaîne de caractères source vers une chaîne de caractères de destination et renvoie un pointeur vers la chaîne de caractères de destination. Les deux blocs peuvent se chevaucher.
StrNew Alloue une chaîne de caractères sur la mémoire de tas.
StrPas Convertit une chaîne de caractères terminée par un nul en une chaîne de caractères Pascal.
StrPCopy Copie une chaîne de caractères Pascal dans une chaîne de caractères terminée par NULL et renvoie un pointeur vers la chaîne de caractères terminée par NULL.
StrPos Renvoie un pointeur vers la première occurrence d'une sous-chaîne de caractères donnée dans une chaîne de caractères, ou NIL si la sous-chaîne de caractères n'apparaît pas dans la chaîne de caractères.
StrRScan Renvoie un pointeur vers la dernière occurrence d'un caractère donné dans une chaîne de caractères, ou NIL si le caractère n'apparaît pas dans la chaîne de caractères.
StrScan Renvoie un pointeur sur la première occurrence d'un caractère donné dans une chaîne de caractères, ou NIL si le caractère n'apparaît pas dans la chaîne de caractères.
StrUpper Convertit une chaîne de caractères en majuscules et renvoie un pointeur sur la chaîne de caractères.

Utilisation de chaînes de caractères terminées par NULL

Les chaînes de caractères à terminaison nulle sont entreposées sous forme de tableaux de caractères avec un type d'index entier de base zéro; c'est-à-dire un tableau de la format :

Array[0..X] of Char;

X est un entier positif non nul. Ces tableaux sont appelés tableaux de caractères de base zéro. Voici quelques exemples de déclarations de tableaux de caractères de base zéro pouvant être utilisés pour entreposer des chaînes de caractères terminées par nulle :

Type
Tldentificateur = array[0..15] of Char;
TNomDeFichier = array[0..79] of Char;
TTextDeMemo = array[0..1023] of Char;

La plus grande différence entre l'utilisation de chaînes de caractères Pascal et de chaînes de caractères terminées par nulle est l'utilisation intensive de pointeurs dans la manipulation des chaînes de caractères terminées par nulle. Le Turbo Pascal effectue des opérations sur ces pointeurs avec un ensemble de règles de syntaxe étendues.

Pointeurs de caractères et chaîne de caractères littérales

Lorsque la syntaxe étendue est activée, une chaîne de caractères littérale est une affectation compatible avec le type PChar. Cela signifie qu'un littéral de chaîne de caractères peut être affecté à une variable de type PChar. Par exemple :

Var
P:PChar;
BEGIN
P:='Bonjour Gladir.com!';
END.

L'effet d'une telle affectation est que le pointeur pointe vers une zone de mémoire contenant une copie terminée par une nulle de la chaîne de caractères littérale. Cet exemple accomplit la même chose que l'exemple précédent :

Const
ChaineTemp:Array[0..14] of Char = 'Bonjour Gladir.com!'#0;
Var
P:PChar;
BEGIN
P:=@ChaineTemp;
END.

Vous pouvez utiliser des chaînes de caractères littérales comme paramètres réels dans les appels de procédure et de fonction lorsque le paramètre formel correspondant est de type PChar. Par exemple, étant donné une procédure avec la déclaration suivante :

Procedure PrintStr(Str:PChar);

les appels de procédure suivants sont valides :

PrintStr('Ceci est un test');
PrintStr(#10#13);

Tout comme il le fait avec une affectation, le compilateur génère une copie terminée par nulle de la chaîne de caractères littérale. Le compilateur passe un pointeur vers cette zone de mémoire dans le paramètre Str de la procédure PrintStr. Enfin, vous pouvez initialiser une constante typée de type PChar avec une constante chaîne de caractères. Vous pouvez également le faire avec des types structurés, tels que des tableaux de PChar et des enregistrements et des objets avec des champs PChar.

Const
Message:PChar = 'Terminaison de programme';
Prompt:PChar = 'Entrez des valeurs : ';
Digits:Array[0..9] of PChar = ('Zéro','Un','Deux','Trois','Quatre','Cinq', 'Six', 'Sept', 'Huit', 'Neuf');

Une expression de constante de chaîne de caractères est toujours évaluée comme une chaîne de caractères de style Pascal même si elle initialise une constante typée de type PChar; par conséquent, une expression de constante de chaîne de caractères est toujours limitée à 255 caractères.

Pointeurs de caractères et tableaux de caractères

Lorsque vous activez la syntaxe étendue avec $X, un tableau de caractères de base zéro est compatible avec le type PChar. Cette situation signifie que chaque fois qu'un PChar est attendu, vous pouvez utiliser un tableau de caractères de base zéro à la place. Lorsque vous utilisez un tableau de caractères à la place d'une valeur PChar, le compilateur convertit le tableau de caractères en une constante de pointeur dont la valeur correspond à l'adresse du premier élément du tableau. Par exemple :

Var
A:Array[0..63] of Char;
P:PChar;
BEGIN
P:=A;
PrintStr(A);
PrintStr(P);
END.

En raison de cette instruction d'affectation, le P pointe maintenant vers le premier élément de A, donc PrintStr est appelé deux fois avec la même valeur. Vous pouvez initialiser une constante typée d'un type de tableau de caractères de base zéro avec une chaîne de caractères littérale plus courte que la longueur déclarée du tableau. Les caractères restants sont définis sur NULL (#0) et le tableau contient effectivement une chaîne de caractères terminée par nulle.

Type
TNomDeFichier = Array[0..79] of Char;
Const
TamponNomDeFichier:TNomDeFichier = 'GLADIR.PAS';
PointeurNomDeFichier:PChar = TamponNomDeFichier;

Indexation du pointeur de caractère

Tout comme un tableau de caractères à base zéro est compatible avec un pointeur de caractère, un pointeur de caractère peut être indexé comme s'il s'agissait d'un tableau de caractères à base de zéros.

Var
A:Array[0..63] of Char;
P:PChar;
Ch:Char;
{ : }
BEGIN
P := A;
Ch := A[5];
Ch := P[5];
END.

Les deux dernières instructions attribuent à Ch la valeur contenue dans le sixième élément de caractère de A. Lorsque vous indexez un pointeur de caractère, l'index spécifie un déplacement non signé à ajouter au pointeur avant qu'il ne soit déréférencé. Par conséquent, P[0] est équivalent à P^ et spécifie le caractère pointé par P. Le P[1] spécifie le caractère juste après celui pointé par P, P[2] spécifie le caractère suivant, et ainsi de suite. Pour l'indexation, un PChar se comporte comme s'il était déclaré comme suit :

Type
TCharArray=Array[0..65535] of Char;
PChar=^TCharArray;

Le compilateur n'effectue aucune vérification d'intervalle lors de l'indexation d'un pointeur de caractère car il ne dispose d'aucune information de type disponible pour déterminer la longueur maximale de la chaîne de caractères terminée par un caractère nul pointé par le pointeur de caractère. Votre programme doit effectuer une telle vérification d'intervalle. La fonction StrUpper suivante illustre l'utilisation de l'indexation de pointeur de caractère pour convertir une chaîne de caractères terminée par un nul en majuscules :

Function StrUpper(Str:PChar):PChar;
Var
I:Word;
Begin
I:=0;
While Str[I] <> #0 do Begin
Str[I]:= UpCase(Str[I]);
Inc(I);
End;
StrUpper := Str;
End;

Notez que StrUpper est une fonction, pas une procédure, et qu'il renvoie toujours la valeur lui ayant été transmise en tant que paramètre. Étant donné que la syntaxe étendue permet d'ignorer le résultat d'un appel de fonction, StrUpper peut être traité comme s'il s'agissait d'une procédure :

StrUpper(A);
PrintStr(A);

Cependant, comme StrUpper renvoie toujours la valeur lui ayant été transmise, les instructions précédentes peuvent être combinées en une seule :

PrintStr(StrUpper(A));

L'imbrication d'appels à des fonctions de gestion de chaînes de caractères terminées par nulle peut être très pratique lorsque vous souhaitez indiquer une certaine interrelation entre un ensemble de manipulations de chaînes de caractères séquentielles. La syntaxe étendue de Turbo Pascal permet aux procédures standard Read, Readln, Str et Val d'être appliquées aux tableaux de caractères de base zéro, et permet aux procédures standard Write, Writeln, Val, Assign et Rename d'être appliquées aux deux caractères de base zéro tableaux et pointeurs de caractères.

Un exemple utilisant des fonctions de gestion de chaînes de caractères

Voici un exemple de code montrant une utilisation de certaines des fonctions de gestion des chaînes de caractères pour la fonction FileSplit dans l'unité WinDos :

Const
fSPathName = 79;
fsDirectory = 67;
fsFileName = 8;
fsExtension = 4;
fcExtension = $0001;
fcFileName = $0002;
fcDirectory = $0004;
fcWildcards = $0008;

Function FileSplit(Path,Dir,Name,Ext:PChar):Word;
Var
DirLen,NameLen,Flags:Word;
NamePtr,ExtPtr:PChar;
Begin
NamePtr := StrRScan(Path, '\');
If NamePtr = nil Then NamePtr := StrRScan(Path, ': ');
If NamePtr = nil Then NamePtr := Path else Inc(NamePtr);
ExtPtr := StrScan(NamePtr,'.');
If ExtPtr = nil Then ExtPtr := StrEnd(NamePtr);
DirLen := NamePtr - Path;
If DirLen > fsDirectory Then DirLen := fsDirectory;
NameLen := ExtPtr - NamePtr;
If NameLen > fSFilename Then NameLen := fsFilename;
Flags := 0;
If (StrScan(NamePtr, '?') <> nil) or (StrScan(NamePtr, '*') <> NIL) Then
Flags := fcWildcards;
If DirLen <> 0 then Flags := Flags or fcDirectory;
If NameLen <> 0 then Flags := Flags or fcFilename;
If ExtPtr[O] <> #0 then Flags := Flags or fcExtension;
If Dir <> nil then StrLCopy(Dir, Path, DirLen);
If Name <> nil then StrLCopy(Name, NamePtr, NameLen);
If Ext <> nil then StrLCopy(Ext, ExtPtr, fsExtension);
FileSplit := Flags;
End;


Dernière mise à jour : Dimanche, le 15 novembre 2020