Les chaînes font partie de ces problèmes en C et C ++. Dans les premiers temps des langages, les chaînes de caractères étaient toutes des tableaux de caractères, généralement du code ASCII 7 bits (bien que peut-être EBCDIC sur des mainframes IBM sous lesquels le portage du C). Viennent ensuite une série de solutions de contournement spécifiques au système d'exploitation, telles que les pages de code, pour permettre l'utilisation de langues avec des caractères qui ne sont pas dans l'alphabet anglais. Après une période de chaos, est venu Unicode. Puis Unicode. Et puis encore Unicode. Et quelques autres Unicodes ici et là aussi, qui est la racine du problème aujourd'hui.
Unicode est, par essence, deux choses. Il s’agit d’une série définie de points de code dans lesquels il existe une correspondance individuelle entre un point de code particulier et une valeur particulière, certains étant graphiques, d’autres contrôlant et manipulant le formatage ou fournissant les autres informations requises. Tous ceux qui utilisent Unicode sont d'accord sur tous ces points, y compris les points de code à usage privé, qui sont tous réservés, mais réservés aux applications conformes à Unicode. Jusqu'ici tout va bien.
Ensuite, il y a les schémas de codage d'où proviennent les divisions. Il y a 1 114 112 points de code dans Unicode. Comment les représentez-vous? La réponse était les schémas d'encodage. UTF-16 était le premier. Il a ensuite été suivi par UTF-8 et UTF-32. Il y a aussi des problèmes d'endianité avec certains d'entre eux.
D'autres formats vont et viennent, dont certains ne font même pas partie d'Unicode.
Windows a finalement adopté UTF-16, tout comme .NET et Java. De nombreux systèmes GNU / Linux et autres systèmes similaires à UNIX ont adopté UTF-8. Certains systèmes de type UNIX utilisent UTF-32. Certains pourraient utiliser UTF-16. La plupart du temps, le Web utilise UTF-8, du fait que la conception intentionnelle de cet encodage est principalement compatible avec l’ASCII. Tant que vous travaillez sur un système, tout va bien. Lorsque vous essayez de devenir multi-plateforme, les choses peuvent devenir plus confuses.
carboniser*
Les cordesLes chaînes char * (pointeurs sur les tableaux de caractères) désignaient à l'origine des chaînes ASCII. Maintenant, ils désignent parfois ASCII, mais plus fréquemment UTF-8. Ceci est particulièrement vrai dans le monde UNIX.
Lors de la programmation pour Windows, vous devez généralement supposer qu'une chaîne char * est une chaîne ASCII ou une chaîne de page de code. Les pages de code utilisent le bit supplémentaire restant de l'ASCII 7 bits pour ajouter 128 caractères supplémentaires, créant ainsi une grande quantité de texte localisé qui convient toujours dans un octet par caractère..
wchar_t *
Les cordeswchar_t *
chaînes de caractères (pointeurs vers des tableaux de wchar_t
, également appelés caractères larges) utilisent un jeu de caractères différent, dépendant de la mise en oeuvre. Sous Windows, cela signifie une valeur de 16 bits, utilisée pour UTF-16. Vous devez toujours utiliser wchar_t comme type de caractère natif pour Windows, sauf si vous devez prendre en charge de très très anciennes versions de système d'exploitation (c'est-à-dire l'ancienne série Windows 9X)..
Lorsque vous écrivez une constante de chaîne de caractères larges dans le code, vous préfixez l'ouverture entre guillemets par un L. Par exemple: const wchar_t * s = L "Bonjour le monde";
. Si vous n'avez besoin que d'un seul caractère, vous utilisez à nouveau le L, mais avec des guillemets simples: wchar_t ch = L'A '
;.
std :: string
et std :: wstring
Les cordesle std :: string
et std :: wstring
les classes se trouvent dans le std :: string
Correspond à carboniser*
tandis que std :: wstring
Correspond à wchar_t *
.
Ces classes constituent un moyen pratique de stocker des chaînes de longueur variable et doivent être utilisées pour les variables de membre de classe à la place des pointeurs bruts correspondants (char * et wchar_t *). Vous ne devez utiliser les pointeurs bruts que pour passer des chaînes en tant qu'arguments, et uniquement si la chaîne est utilisée telle quelle ou copiée localement dans l'un de ces types de chaîne..
Dans les deux cas, la fonction doit prendre le pointeur de chaîne comme un pointeur sur const (par exemple., const wchar_t * someStr
). Après tout, les pointeurs n’engagent pas les mêmes dépenses de construction et de destruction que std :: string et std :: wstring. L'utilisation d'un pointeur sur const garantit que la fonction ne modifiera pas les données par inadvertance ou ne tentera pas de libérer la mémoire pointée..
Pour obtenir un pointeur sur const pour le contenu de l'un d'eux, appelez sa fonction membre c_str. Notez que le pointeur renvoyé pointe sur const puisque les données ne doivent pas être modifiées, ni delete ne doit être appelé sur le pointeur. La mémoire est toujours détenue et gérée par l'instance sous-jacente std :: string ou std :: wstring. Cela signifie également que si l'instance sous-jacente est détruite, le pointeur que c_str vous donne devient invalide. C'est pourquoi, si vous avez besoin de données de chaîne dépassant la portée de la fonction à laquelle elles sont transmises, vous devez toujours stocker les données de chaîne dans un de ces types plutôt que de stocker le pointeur directement.
Pour ajouter du texte, utilisez la fonction append member.
Pour voir si une séquence particulière de caractères se produit dans une chaîne, utilisez la fonction find member ou l'une de ses variantes plus spécifiques, telles que find_first_of. Si la séquence ne figure pas dans la chaîne, la valeur renvoyée sera égale à std :: npos
. Sinon, ce sera l'indice du point de départ pertinent pour la séquence.
Pour obtenir une sous-chaîne, utilisez la fonction membre substr en lui transmettant l'index de base zéro de départ et le nombre d'éléments (c.-à-d. Le nombre de caractères char ou wchar_t) à copier. Il renverra un std :: string ou un std :: wstring sans vous permettre de déborder d'un tampon en transmettant un nombre inexact ou un index de départ incorrect..
Il existe d'autres méthodes utiles, qui sont toutes documentées dans la classe basic_string, qui est une classe de modèle pour laquelle std :: string et std :: wstring sont des spécialisations prédéfinies de.
std :: wstringstream
Les cordesle std :: wstringstream
classe (il y a un std :: stringstream
également) est similaire à la classe .NET StringBuilder. Il est utilisable de la même manière que tout autre flux de bibliothèque standard C ++. Je trouve ce type très utile pour construire une chaîne dans une fonction membre qui sera ensuite stockée dans un std :: wstring
membre de la classe.
Pour un exemple d'utilisation, voir le Garnitures :: GetString
fonction membre dans le fichier ConstructorsSample \ Toppings.h. Voici son code, à titre de rappel:
const wchar_t * GetString (void) if (m_toppings == None) m_toppingsString = L "None"; return m_toppingsString.c_str (); bool addSpace = false; std :: wstringstream wstrstream; if (m_toppings & HotFudge) if (addSpace) wstrstream << L" "; wstrstream << L"Hot Fudge"; addSpace = true; if (m_toppings & RaspberrySyrup) if (addSpace) wstrstream << L" "; wstrstream << L"Raspberry Syrup"; addSpace = true; if (m_toppings & CrushedWalnuts) if (addSpace) wstrstream << L" "; wstrstream << L"Crushed Walnuts"; addSpace = true; if (m_toppings & WhippedCream) if (addSpace) wstrstream << L" "; wstrstream << L"Whipped Cream"; addSpace = true; if (m_toppings & Cherry) if (addSpace) wstrstream << L" "; wstrstream << L"Cherry"; addSpace = true; m_toppingsString = std::wstring(wstrstream.str()); return m_toppingsString.c_str();
Comme je l'ai mentionné dans l'introduction, l'histoire des chaînes n'est pas belle, mais j'espère que cet article vous a permis de bien comprendre les chaînes en C ++. La prochaine tranche de cette série couvre les idiomes courants en C++.
Cette leçon représente un chapitre de C ++ Succinctly, un eBook gratuit de l’équipe de Syncfusion..