Types de données chaines - Delphi Pascal

A propos des types chaîne

Une chaîne représente une suite de caractères. Delphi supporte les types chaîne prédéfinis suivants.

Types chaîne
TypeLongueur maximaleMémoire nécessaireUtilisé pour
ShortString
255 caractères
de 2 à 256 octets
Compatibilité descendante
AnsiString
~2^31 caractères
de 4 octets à 2 Go
Caractères sur 8 bits (ANSI), DBCS ANSI, MBCS ANSI, caractères Unicode, etc.
UnicodeString
~2^30 caractères
de 4 octets à 2 Go
Caractères Unicode, caractères sur 8 bits (ANSI), serveurs multi-utilisateurs et applications multilingues
WideString
~2^30 caractères
de 4 octets à 2 Go
Caractères Unicode ; serveurs multi-utilisateurs et applications multilingues.UnicodeString est généralement préféré à WideString, sauf pour les applications COM.

Remarque : Le type chaîne par défaut est UnicodeString. WideString est fourni à des fins de compatibilité avec le type BSTRCOM. Vous devez généralement utiliser UnicodeString pour les applications non COM. Dans la plupart des cas, UnicodeString est le type préféré. Le type string est un alias pour UnicodeString.
Les types chaîne peuvent être combinés dans les affectations et les expressions ; le compilateur effectue automatiquement les conversions nécessaires. Par contre, les chaînes passées par référence à une fonction ou à une procédure (comme les paramètres var et out) doivent être du type approprié. Les chaînes peuvent être explicitement converties dans un type de chaîne différent. Toutefois, le transtypage d'une chaîne multi-octets en une chaîne mono-octet peut conduire à des pertes de données.
Voici quelques valeurs de types de chaîne spéciaux :
  • Les AnsiStrings à page de code sont définis comme suit :
Type mystring = AnsiString(CODEPAGE)
C'est un AnsiString ayant une affinité à maintenir ses données internes dans une page de code spécifique.
  • Le type RawByteString est type AnsiString($FFFF). RawByteString permet le passage des données chaîne de toute page de code sans conversion de page de code. RawByteString doit seulement être utilisé comme un paramètre de type value ou const ou un type de retour d'une fonction. Il ne doit jamais être passé par référence (passé par var) et ne doit jamais être instancié comme une variable.
  • UTF8String représente une chaîne encodée en UTF-8 (nombre variable d'octets Unicode). C'est un type AnsiString avec une page de code UTF-8.
Le mot réservé string fonctionne comme un identificateur de type chaîne générique. Par exemple :
var S: string;
crée une variable S contenant une chaîne. Sur la plate-forme Win32, le compilateur interprète string (quand il apparaît sans être suivi d'un nombre entre crochets) comme désignant UnicodeString.
Sur la plate-forme Win32, vous pouvez utiliser la directive {$H-} pour transformer string en ShortString. C'est une technique potentiellement utile lors de l'utilisation d'anciens codes Turbo Pascal ou Delphi 16 bits avec vos programmes actuels.
Notez que le mot clé string est aussi utilisé lors de la déclaration de types ShortString de longueurs spécifiques (voir Chaînes courtes ci-dessous).
Les comparaisons de chaînes sont définies par l'ordre des éléments dans les positions correspondantes. Avec des chaînes de longueurs différentes, chaque caractère de la chaîne la plus longue n'ayant pas de caractère correspondant dans la chaîne la plus courte prend la valeur "supérieur à". Par exemple, 'AB' est supérieure à 'A' ; c'est-à-dire que 'AB' > 'A' renvoie True. Les chaînes de longueur nulle représentent les valeurs les plus petites.
Il est possible d'indexer une variable chaîne comme un tableau. Si S est une variable chaîne non UnicodeString et i, une expression entière, S[i] représente le nième octet dans S, qui peut ne pas être le nième caractère ou un caractère entier pour une chaîne de caractères multi-octet (MBCS). De façon similaire, l'indexation d'une variable UnicodeString résulte en un élément qui peut ne pas être un caractère entier. Si la chaîne contient des caractères du BMP (Basic Multilingual Plane), tous les caractères sont sur 2 octets et l'indexation de la chaîne obtient ainsi des caractères. Toutefois, si certains caractères ne sont pas dans le BMP, un élément indexé peut être une paire de substitution, pas un caractère entier.
La fonction standard Length renvoie le nombre d'éléments d'une chaîne. Comme indiqué ci-dessus, le nombre d'éléments ne correspond pas nécessairement au nombre de caractères. La procédure SetLength ajuste la longueur d'une chaîne. Notez que la fonction SizeOf renvoie le nombre d'octets utilisés pour représenter une variable ou un type. Sachez que SizeOf renvoie le nombre de caractères d'une chaîneseulement pour une chaîne courteSizeOf renvoie le nombre d'octets d'un pointeur pour tous les autres types de chaîne, puisque ce sont des pointeurs.
Pour une chaîne courte ou AnsiString, S[i] est de type AnsiChar. Pour un WideString, S[i] est de type WideChar. Pour les locales utilisant un octet (locales occidentales), MyString[2] := 'A'; affecte la valeur A au second caractère de MyString. Le code suivant utilise la fonction standard UpCase pour convertir MyString en majuscule :
var I: Integer;
begin
  I := Length(MyString);
  while I > 0 do
  begin
    MyString[I] := UpCase(MyString[I]);
    I := I - 1;
  end;
end;
Attention en utilisant de cette manière des index sur les chaînes car si vous écrivez au-delà de la fin de la chaîne, vous provoquez des violations d'accès. De même, évitez de transmettre en paramètre var des index de chaîne car cela produirait un code inefficace.
Vous pouvez affecter à une variable la valeur d'une constante chaîne ou de toute expression renvoyant une chaîne. La longueur de la chaîne change de manière dynamique lors de l'affectation. Exemples :
MyString := 'Hello world!';
MyString := 'Hello' + 'world';
MyString := MyString + '!';
MyString := ' '; { space }
MyString := '';  { empty string }

Chaînes courtes

Un ShortString compte de 0 à 255 caractères mono-octet. Si la longueur d'un ShortString peut changer de manière dynamique, 256 octets de mémoire lui sont alloués statiquement. Le premier octet stocke la longueur de la chaîne, les 255 octets suivants sont disponibles pour les caractères. Si S est une variable ShortString, Ord(S[0]) renvoie, comme Length(S), la longueur de S ; l'affectation d'une valeur à S[0], comme l'appel de SetLength, modifie la longueur de S. ShortString est maintenu seulement pour la compatibilité descendante.
Le langage Delphi gère des types de chaîne courte, des sous-types de ShortString dont la longueur maximale se situe entre 0 et 255 caractères. Ils sont simplement désignés par un nombre entre crochets suivant le mot réservé string. Par exemple :
var MyString: string[100];
crée une variable appelée MyString dont la longueur maximale est de 100 caractères. Ceci revient aux déclarations suivantes :
type CString = string[100];
var MyString: CString;
Les variables déclarées ainsi allouent seulement la mémoire nécessaire au type, c'est-à-dire la longueur maximale plus un octet. Dans notre exemple, MyString utilise 101 octets, à comparer aux 256 octets d'une variable ayant le type prédéfini ShortString.
Quand vous affectez une valeur à une variable chaîne courte, la chaîne est tronquée si elle dépasse la longueur maximale du type.
Les fonctions standard High et Low acceptent les identificateurs de type chaîne courte et les variables de ces types. High renvoie la longueur maximale du type de chaîne courte alors que Low renvoie zéro.

AnsiString

AnsiString représente une chaîne allouée dynamiquement dont la longueur maximale n'est limitée que par la mémoire disponible.
Une variable AnsiString est une structure contenant des informations de chaîne. Quand la variable est vide (c'est-à-dire quand elle contient une chaîne de longueur nulle), le pointeur vaut nil et la chaîne n'utilise pas de mémoire supplémentaire. Quand la variable est non vide, elle pointe sur un bloc de mémoire alloué dynamiquement qui contient la valeur de la chaîne. Cette mémoire est allouée sur le tas mais sa gestion est entièrement automatique et ne nécessite pas de codage. La structure AnsiString contient un indicateur de longueur 32 bits, un compteur de références 32 bits, une longueur de données 16 bits indiquant le nombre d'octets par caractère et une page de code 16 bits.
Une variable AnsiString représente une chaîne à un seul octet. Avec un jeu de caractères sur un seul octet (SBCS), chaque octet d'une chaîne représente un seul caractère. Dans un jeu de caractères multi-octets (MBCS), les éléments sont toujours des octets uniques, mais certains caractères sont représentés par un octet et d'autres par plusieurs octets. Les jeux de caractères multi-octets, en particulier les jeux de caractères sur deux octets (DBCS), sont fréquemment utilisés pour les langues asiatiques. Une variable AnsiString peut contenir des caractères MBCS.
L'indexation de AnsiString est à base 1. L'indexation des chaînes multi-octets n'est pas fiable, puisque S[i] représente le nième octet (pas nécessairement le nième caractère) de S. Le nième octet peut être un caractère unique ou une partie d'un caractère. En revanche, les fonctions standard de manipulation de chaînes AnsiString ont un équivalent multi-octet qui implémente aussi le tri des caractères en tenant compte de la localisation. Le nom des fonctions multi-octets commence généralement par Ansi-. Ainsi, la version multi-octet de StrPos est AnsiStrPos. Le support des caractères multi-octets dépend du système d'exploitation et est basé sur les paramètres régionaux en cours.
Comme les variables AnsiString ont des pointeurs, plusieurs peuvent pointer sur la même valeur sans utiliser de mémoire supplémentaire. Le compilateur utilise ceci pour économiser les ressources et exécuter les affectations plus rapidement. A chaque fois qu'une variable AnsiString est détruite ou qu'une nouvelle valeur lui est affectée, le compteur de références de AnsiString (la valeur précédente de la variable) est décrémenté et le compteur de références de la nouvelle valeur (le cas échéant) est incrémenté. Si le compteur de références d'une chaîne devient nul, sa mémoire est désallouée. Ce processus est appelé comptage de références. Quand des index sont utilisés pour modifier la valeur d'un seul caractère d'une chaîne, une copie de la chaîne est effectuée si, et seulement si, son compteur de références est supérieur à un. On parle alors de sémantique copie-sur-écriture.

UnicodeString

Le type UnicodeString représente une chaîne Unicode allouée dynamiquement dont la longueur maximale n'est limitée que par la mémoire disponible.
Dans un jeu de caractères Unicode, chaque caractère est représenté par un ou plusieurs octets. Unicode a plusieurs formats de transformation Unicode qui utilisent des encodages de caractère différents mais équivalents qui peuvent être facilement transformés de l'un à l'autre.
  • En UTF-8, par exemple, les caractères peuvent comporter de 1 à 4 octets. En UTF-8, les 128 premiers caractères Unicode correspondent aux caractères US-ASCII.
  • UTF-16 est un autre encodage Unicode couramment utilisé dans lequel les caractères sont de 2 octets ou 4 octets. La majorité des caractères internationaux appartient au plan multilingue de base et ils peuvent être représentés sur 2 octets. Les autres caractères nécessitent deux caractères à 2 octets, et sont connus sous le terme paires de substitution.
  • UTF-32 représente chaque caractère avec 4 octets.
La plate-forme Win32 gère des jeux de caractères mono-octet (sur un octet), des jeux multi-octets (sur plusieurs octets) et Unicode. Le système d'exploitation Windows supporte UTF-16.
Le type UnicodeString a exactement la même structure que le type AnsiString. Les données UnicodeString sont encodées en UTF-16.
Puisque UnicodeString et AnsiString ont la même structure, ils fonctionnent de façon très similaire. Quand une variable UnicodeString est vide, elle n'utilise aucune mémoire supplémentaire. Quand elle n'est pas vide, elle pointe sur un bloc de mémoire alloué dynamiquement qui contient la valeur de la chaîne, et la gestion de la mémoire est alors transparente à l'utilisateur. Les variables UnicodeString utilisent le comptage de références, et deux ou plusieurs d'entre elles peuvent référencer la même valeur sans consommer de mémoire supplémentaire.
Les instances de UnicodeString peuvent indexer les caractères. L'indexation est à base 1, comme pour AnsiString.
UnicodeString est compatible en affectation à tous les autres types chaîne. Toutefois, les affectations entre AnsiString et UnicodeString effectuent toujours les conversions appropriées vers le bas et vers le haut. Notez que l'affectation d'un type UnicodeString à un type AnsiString n'est pas recommandé et peut générer une perte de données.
Delphi peut aussi supporter les caractères et les chaînes Unicode par le biais des types WideChar, PWideChar et WideString.


WideString

Le type WideString représente une chaîne allouée dynamiquement composée de caractères Unicode sur 16 bits. Par certains points, il ressemble à AnsiString. Sur Win32, WideString est compatible avec le type COM BSTR.
WideString est approprié dans les applications COM. Toutefois, WideString n'utilise pas le comptage de références, ainsi UnicodeString est plus flexible et efficace dans d'autres types d'applications.
L'indexation de chaînes multi-octets WideString n'est pas fiable, puisque S[i] représente le nième élément (pas nécessairement le nièmecaractère) dans S.


Manipulation des chaînes terminées par null

Beaucoup de langages de programmation, dont le C et le C++, n'ont pas de type de donnée chaîne naturel. Ces langages, et les environnements qui ont été construits avec, utilisent des chaînes terminées par null. Une chaîne terminée par null est un tableau de caractères à base zéro qui se termine par NULL (#0). Comme le tableau n'a pas d'indicateur de longueur, le premier caractère NULL indique la fin de la chaîne. Vous pouvez utiliser des constructions Delphi et des routines spéciales de l'unité SysUtils pour manipuler des chaînes terminées par null quand vous avez besoin de partager des données avec des systèmes les utilisant.
Par exemple, les déclarations de type suivantes permettent de stocker des chaînes terminées par null :
type
  TIdentifier = array[0..15] of Char;
  TFileName = array[0..259] of Char;
  TMemoText = array[0..1023] of WideChar;
Avec la syntaxe étendue activée ({$X+}), vous pouvez affecter une constante chaîne à un tableau de caractères à base zéro alloué statiquement. Les tableaux dynamiques ne peuvent pas être utilisés pour cela. Si vous initialisez une constante tableau avec une chaîne plus courte que la longueur déclarée du tableau, les caractères restants sont initialisés à #0.

Utilisation des pointeurs, tableaux et des constantes chaîne

Pour manipuler des chaînes terminées par null, il est souvent nécessaire d'utiliser des pointeurs. Les constantes chaîne sont compatibles pour l'affectation avec les types PChar et PWideChar qui représentent des pointeurs sur des tableaux terminés par null de valeurs Char et WideChar. Par exemple :
var P: PChar;
  ...
P := 'Hello world!'
fait pointer P sur une zone de mémoire contenant une copie terminée par null de 'Bonjour chez vous!'. C'est équivalent à :
const TempString: array[0..12] of Char = 'Hello world!';
var P: PChar;
   ...
P := @TempString[0];
Vous pouvez aussi transmettre des constantes chaîne aux fonctions qui attendent des valeurs ou des paramètres const de type PChar ouPWideChar, par exemple StrUpper('Bonjour chez vous!'). Comme avec les affectations à un PChar, le compilateur génère une copie terminée par null de la chaîne et transmet à la fonction un pointeur sur cette copie. Vous pouvez, enfin, initialiser des constantes PChar ou PWideChar avec des littéraux chaîne, seuls ou dans un type structuré. Exemples :
const
  Message: PChar = 'Program terminated';
  Prompt: PChar = 'Enter values: ';
  Digits: array[0..9] of PChar =
    ('Zero', 'One', 'Two', 'Three', 'Four', 'Five',
     'Six', 'Seven', 'Eight', 'Nine');
Les tableaux de caractères à base zéro sont compatibles avec PChar et PWideChar. Quand vous utilisez un tableau de caractères à la place d'une valeur pointeur, le compilateur convertit le tableau en une constante pointeur dont la valeur correspond à l'adresse du premier élément du tableau. Par exemple :
var
  MyArray: array[0..32] of Char;
  MyPointer: PChar;
begin
  MyArray := 'Hello';
  MyPointer := MyArray;
  SomeProcedure(MyArray);
  SomeProcedure(MyPointer);
end;
Ce code appelle deux fois SomeProcedure avec la même valeur.
Un pointeur de caractère peut être indexé comme s'il était un tableau. Dans l'exemple précédent, MyPointer[0] renvoie H. L'index spécifie un décalage ajouté au pointeur avant qu'il ne soit déréférencé. Pour les variables PWideChar, l'index est automatiquement multiplié par deux. Donc, si P est un pointeur de caractère, P[0] est équivalent à P^ et spécifie le premier caractère du tableau, P[1] spécifie le second caractère du tableau, et ainsi de suite ; P[-1] spécifie le "caractère" immédiatement à gauche de P[0]. Le compilateur n'effectue pas de vérification des bornes sur ces index.
La fonction StrUpper illustre l'utilisation de l'indexation de pointeurs pour parcourir une chaîne terminée par null :
function StrUpper(Dest, Source: PChar; MaxLen: Integer): PChar;
var
  I: Integer;
begin
  I := 0;
  while (I < MaxLen) and (Source[I] <> #0) do
  begin
    Dest[I] := UpCase(Source[I]);
    Inc(I);
  end;
  Dest[I] := #0;
  Result := Dest;
end;

Mélange de chaînes Delphi et de chaînes terminées par null

Vous pouvez mélanger des chaînes (valeurs AnsiString et UnicodeString) et des chaînes terminées par null (valeurs PChar) dans les expressions et les affectations, et vous pouvez passer des valeurs PChar aux fonctions ou procédures qui prennent des paramètres de type chaîne. L'affectation S := P, où S est une variable chaîne et P une expression PChar, copie une chaîne terminée par null dans une chaîne.
Dans une opération binaire, si un opérande est une chaîne et l'autre un PChar, l'opérande PChar est converti en un UnicodeString.
Vous pouvez transtyper une valeur PChar en un UnicodeString. Ceci est pratique pour effectuer une opération de chaîne sur deux valeurs PChar. Par exemple :
S := string(P1) + string(P2);
Vous pouvez aussi transtyper une chaîne UnicodeString ou AnsiString en une chaîne terminée par null. Les règles suivantes s'appliquent :
  • Si S est un UnicodeString, PChar(S) transtype S en une chaîne terminée par null ; ceci renvoie un pointeur sur le premier caractère de S. De tels transtypages sont utilisés pour l'API Windows. Si, par exemple Str1 et Str2 sont des UnicodeStrings, vous pouvez appeler la fonction MessageBox de l'API Win32 de la manière suivante : MessageBox(0, PChar(Str1), PChar(Str2), MB_OK);. Utilisez PAnsiChar(S) si S est un AnsiString.
  • Vous pouvez aussi utiliser Pointer(S) pour transtyper une chaîne en un pointeur non typé. Mais si S est vide, le transtypage renvoienil.
  • PChar(S) renvoie toujours un pointeur sur un bloc mémoire; si S est vide, un pointeur sur #0 est renvoyé.
  • Quand vous transtypez une variable UnicodeString ou AnsiString en pointeur, le pointeur reste valide jusqu'à ce qu'une nouvelle valeur soit affectée à la variable ou que la variable sorte de la portée. Si vous transtypez n'importe quelle autre expression chaîne en pointeur, le pointeur n'est valable qu'à l'intérieur de l'instruction où le transtypage est effectué.
  • Quand vous transtypez une expression UnicodeString ou AnsiString en pointeur, le pointeur doit généralement être considéré en lecture seule. Vous pouvez utiliser sans risque le pointeur pour modifier la chaîne uniquement si les conditions suivantes sont respectées :
    • L'expression transtypée est une variable UnicodeString ou AnsiString.
    • La chaîne n'est pas vide.
    • La chaîne est unique, c'est-à-dire que son compteur de références vaut un. Pour vérifier que la chaîne est unique, appelez les procédures SetLength, SetString et UniqueString.
    • La chaîne n'a pas été modifiée depuis le transtypage.
    • Les caractères modifiés se trouvent tous dans la chaîne. Faites attention à ne pas utiliser d'index hors intervalle sur le pointeur.
Les mêmes règles s'appliquent aux mélanges de valeurs WideString à des valeurs PWideChar.

Aucun commentaire: