76 votes

Encodage Unicode pour les chaînes littérales en C++11

Suite à un Question connexe J'aimerais poser une question sur les nouveaux types de caractères et de chaînes de caractères en C++11. Il semble que nous ayons maintenant quatre types de caractères et cinq types de chaînes de caractères. Les types de caractères :

char     a =  '\x30';         // character, no semantics
wchar_t  b = L'\xFFEF';       // wide character, no semantics
char16_t c = u'\u00F6';       // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF';   // 32-bit, assumed UCS-4

Et les chaînes littérales :

char     A[] =  "Hello\x0A";         // byte string, "narrow encoding"
wchar_t  B[] = L"Hell\xF6\x0A";      // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6";        // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto     E[] = u8"\u00F6\U0010FFFF"; // (3)

La question est la suivante : Est-ce que les \x / \u / \U Les références de caractères sont-elles librement combinables avec tous les types de chaînes de caractères ? Tous les types de chaînes de caractères ont-ils une largeur fixe, c'est-à-dire que les tableaux contiennent précisément autant d'éléments que ceux qui apparaissent dans le littéral, ou bien les types de chaînes de caractères ont-ils une largeur fixe ? \x / \u / \U sont expansées en un nombre variable d'octets ? Est-ce que u"" et u8"" Les chaînes de caractères ont une sémantique d'encodage, par exemple, puis-je dire char16_t x[] = u"\U0010FFFF" et le point de code non-BMP est encodé dans une séquence UTF16 de deux unités ? Et de la même manière pour u8 ? Dans (1), puis-je écrire des substituts solitaires avec \u ? Enfin, les fonctions de chaîne de caractères sont-elles conscientes de l'encodage (c'est-à-dire qu'elles tiennent compte des caractères et peuvent détecter les séquences d'octets invalides) ?

Il s'agit d'une question un peu ouverte, mais j'aimerais obtenir une image aussi complète que possible du nouveau codage UTF et des fonctions de type du nouveau C++11.

51voto

Nicol Bolas Points 133791

Est-ce que les \x / \u / \U les références de caractères sont-elles librement combinables avec tous les types de chaînes de caractères ?

Non. \x peut être utilisé dans n'importe quel domaine, mais \u et \U ne peut être utilisé que dans les chaînes de caractères qui sont spécifiquement codées en UTF. Cependant, pour toute chaîne encodée en UTF, \u et \U peut être utilisé comme bon vous semble.

Tous les types de chaînes de caractères ont-ils une largeur fixe, c'est-à-dire que les tableaux contiennent précisément autant d'éléments qu'il y en a dans le littéral, ou est-ce que les types de chaînes de caractères ont une largeur fixe ? \x / \u / \U sont expansées en un nombre variable d'octets ?

Pas dans le sens où vous l'entendez. \x , \u et \U sont convertis en fonction de l'encodage des chaînes de caractères. Le nombre de ces "unités de code" (selon les termes d'Unicode. A char16_t est une unité de code UTF-16) dépend de l'encodage de la chaîne de caractères qui la contient. Le littéral u8"\u1024" créerait une chaîne contenant 2 char plus un terminateur nul. Le littéral u"\u1024" créerait une chaîne contenant 1 char16_t plus un terminateur nul.

Le nombre d'unités de code utilisées est basé sur le codage Unicode.

Les chaînes u"" et u8"" ont-elles une sémantique d'encodage, par exemple, puis-je dire char16_t x[] = u" ? \U0010FFFF "et le point de code non-BMP est encodé dans une séquence UTF16 de deux unités ?

u"" crée une chaîne de caractères encodée en UTF-16. u8"" crée une chaîne de caractères codée UTF-8. Elles seront encodées selon la spécification Unicode.

Dans (1), puis-je écrire des substituts solitaires avec \u ?

Absolument pas. La spécification interdit expressément l'utilisation des paires de substituts UTF-16 (0xD800-0xDFFF) comme points de code pour les éléments suivants \u ou \U .

Enfin, les fonctions de chaîne de caractères sont-elles sensibles à l'encodage (c'est-à-dire qu'elles tiennent compte des caractères et peuvent détecter les séquences d'octets invalides) ?

Absolument pas. Eh bien, permettez-moi de reformuler cela.

std::basic_string ne traite pas les encodages Unicode. Ils peuvent certainement magasin chaînes de caractères codées en UTF. Mais ils ne peuvent y penser que comme des séquences de char , char16_t ou char32_t ils ne peuvent pas les considérer comme une séquence de points de code Unicode qui sont codés avec un mécanisme particulier. basic_string::length() retournera le nombre d'unités de code, et non de points de code. Et évidemment, les fonctions de chaîne de la bibliothèque standard du C sont totalement inutiles.

Il convient toutefois de noter que la "longueur" d'une chaîne Unicode ne signifie pas le nombre de points de code. Certains points de code sont des "caractères" de combinaison (un nom malheureux), qui se combinent avec le point de code précédent. Ainsi, plusieurs points de code peuvent correspondre à un seul caractère visuel.

Les Iostreams peuvent en fait lire/écrire des valeurs codées en Unicode. Pour ce faire, vous devrez utiliser une locale pour spécifier l'encodage et l'imprégner correctement dans les différents endroits. C'est plus facile à dire qu'à faire, et je n'ai pas de code sur moi pour vous montrer comment.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X