85 votes

Programmation C: Comment programmer pour Unicode?

Quelles conditions préalables sont nécessaires pour faire de la programmation Unicode stricte?

Cela signifie-t-il que mon code ne doit pas utiliser char types et que des fonctions doivent être utilisées pour gérer wint_t et wchar_t ?

Et quel est le rôle joué par les séquences de caractères multi-octets dans ce scénario?

43voto

Jonathan Leffler Points 299946

La norme C (C99) prévoit à l'échelle des personnages et des caractères multi-octets, mais depuis il n'y a aucune garantie sur le contenu de ces caractères peut contenir, leur valeur est quelque peu limitée. Pour une application donnée, ils fournissent un support utile, mais si votre code doit être en mesure de se déplacer entre les implémentations, il n'y a pas de garanties suffisantes pour qu'ils vous seront utiles.

Par conséquent, l'approche proposée par Hans van Eck (qui consiste à écrire un wrapper autour de l'unité de soins intensifs - International Components for Unicode - bibliothèque) est son, de l'OMI.

Le codage UTF-8 a de nombreux mérites, dont l'une est que si on ne plaisante pas avec les données (en tronquant, par exemple), alors il peut être copiée par des fonctions qui ne sont pas pleinement conscients de la complexité de l'encodage UTF-8. Ce n'est absolument pas le cas avec d' wchar_t.

Unicode est de 21 bits format. C'est, Unicode réserves de points de code à partir de U+0000 à U+10FFFF.

L'une des choses utiles à propos de l'UTF-8, UTF-16 et UTF-32 formats (où UTF signifie Unicode Transformation Format - voir Unicode), c'est que vous pouvez convertir entre les trois représentations sans perte d'information. Chacun peut représenter tout ce que les autres peuvent représenter. Les deux UTF-8 et UTF-16 sont multi-octets formats.

UTF-8 est bien connu pour être un multi-octets format, avec une attention à la structure qui le rend possible pour trouver le début de caractères dans une chaîne de manière fiable, à partir de tout point de la chaîne. Caractères codés sur un octet ont la haute-ensemble de bits à zéro. De caractères Multi-octets ont le premier caractère de commencer avec l'un des modèles de bits 110, 1110 ou 11110 (pour 2-octet 3 octet 4 octet), avec des octets en commençant toujours 10. La poursuite personnages sont toujours dans la gamme 0x80 .. 0xBF. Il y a des règles que les caractères UTF-8 doit être représenté dans le minimum de format possible. Une conséquence de ces règles est que les octets 0xC0 et 0xC1 (également 0xF8..0xFF) ne peut pas apparaître en UTF-8 valide les données.

 U+0000 ..   U+007F  1 byte   0xxx xxxx
 U+0080 ..   U+07FF  2 bytes  110x xxxx   10xx xxxx
 U+0800 ..   U+FFFF  3 bytes  1110 xxxx   10xx xxxx   10xx xxxx
U+10000 .. U+10FFFF  4 bytes  1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx

À l'origine, il était à espérer que Unicode serait un code de 16 bits ensemble et tout allait s'insérer dans un code de 16 bits de l'espace. Malheureusement, le monde réel est plus complexe, et il devait être étendue à l'actuel de 21 bits de codage.

UTF-16 est donc d'une seule unité (mot de 16 bits) code pour le "Plan Multilingue de Base", ce qui signifie les personnages avec des points de code Unicode U+0000 .. U+FFFF, mais utilise deux unités (32 bits) pour les caractères en dehors de cette plage. Ainsi, le code qui fonctionne avec le codage UTF-16 doit être capable de gérer de largeur variable de codage, tout comme de l'UTF-8. Les codes pour le double-unité caractères sont appelés les mères porteuses.

Les mères porteuses sont des points de code à partir de deux plages de valeurs Unicode, réservés pour une utilisation en tant que leader et suiveur les valeurs de paires d'unités de code en UTF-16. Leader, appelé aussi de haut, les mères porteuses à partir de U+D800 U+DBFF, et de fuite, ou faible, les mères porteuses à partir de U+DC00 à U+DFFF. Ils sont appelés substituts, car ils ne représentent pas les caractères directement, mais seulement comme une paire.

UTF-32 est évidemment possible d'encoder n'importe quel point de code Unicode en une seule unité de stockage. Il est efficace pour les calculs, mais pas pour le stockage.

Vous pouvez trouver beaucoup plus d'informations à l' ICU et Unicode sites web.

21voto

Hans van Eck Points 230

Notez que ce n'est pas à propos de "stricte programmation unicode" en soi, mais de l'expérience pratique.

Ce que nous avons fait dans mon entreprise était de créer un wrapper de la bibliothèque autour d'IBM USI de la bibliothèque. La bibliothèque d'encapsulation a un UTF-8 interface et les convertit en UTF-16 lorsqu'il est nécessaire d'appeler les soins intensifs. Dans notre cas, nous n'avons pas à trop se soucier de la performance de hits. Quand la performance est un problème, nous avons également fourni UTF-16 interfaces (à l'aide de notre propre type de données).

Les Applications pourraient demeurer en grande partie-est (à l'aide de char), bien que dans certains cas, ils doivent être conscients de certains problèmes. Par exemple, au lieu de strncpy (), nous utilisons un wrapper qui évite de couper des séquences UTF-8. Dans notre cas, c'est suffisant, mais on peut aussi envisager des contrôles pour la combinaison de caractères. Nous avons aussi des wrappers pour compter le nombre de codepoints, le nombre de graphèmes, etc.

Lors de l'interfaçage avec d'autres systèmes, nous avons parfois besoin de faire de caractères personnalisée de la composition, de sorte que vous pouvez avoir besoin d'une certaine souplesse (selon votre demande).

Nous n'utilisons pas de wchar_t. À l'aide de soins intensifs évite les problèmes inattendus dans la portabilité (mais pas à d'autres, des problèmes inattendus, bien sûr :-).

11voto

dbyron Points 136

Cette FAQ est une mine d'info. Entre cette page et cet article de Joel Spolsky, vous aurez un bon point de départ.

Une des conclusions que j'en suis venu à le long du chemin:

  • wchar_t 16 bits sur Windows, mais pas nécessairement 16 bits sur d'autres plates-formes. Je pense que c'est un mal nécessaire sur Windows, mais peut probablement être évité ailleurs. La raison pour laquelle il est important sur Windows, c'est que vous en avez besoin pour utiliser des fichiers qui ont des caractères non-ASCII dans le nom (avec la version W de fonctions).

  • Notez que les Api Windows qui prennent wchar_t chaînes attendre le codage UTF-16. Notez également que c'est différent de l'UCS-2. Prendre note des paires de substitution. Cette page de test a éclairant tests.

  • Si vous êtes à la programmation sous Windows, vous ne pouvez pas utiliser fopen(), fread(), fwrite(), etc. depuis ils ne prennent char * et ne comprennent pas l'encodage UTF-8. Fait de la portabilité douloureux.

-DB

7voto

sebastien Points 92

Faire le strict programmation unicode:
Seule l'utilisation de la chaîne de l'API qui sont conscient unicode (PAS strlen (), strcpy, ... mais leur widestring homologues wstrlen, wsstrcpy, ...)
- Lorsque vous traitez avec un bloc de texte, utiliser un codage qui permet de stocker des caractères unicode (utf-7, utf-8, utf-16, ucs-2, ...) sans perte.
- Vérifiez que votre système d'exploitation par défaut le jeu de caractères unicode (ex: utf-8)
- Utiliser des polices qui sont compatibles avec unicode (ex: arial_unicode)

Les séquences de caractères multi-octets est un codage qui date d'avant l'encodage UTF-16 (celui utilisé normalement avec wchar_t) et il me semble qu'il est plutôt pour Windows uniquement.

Je n'ai jamais entendu parler de wint_t.

HTH

2voto

Mike Weller Points 28387

Fondamentalement, vous voulez traiter avec des chaînes de caractères dans la mémoire de wchar_t des tableaux au lieu de char. Quand vous faites n'importe quel type d'e/S (comme la lecture/écriture de fichiers, vous pouvez encoder/décoder en utilisant UTF-8 (ce qui est probablement le plus commun de codage) qui est assez simple à mettre en œuvre. Juste google les Rfc. Donc en mémoire, rien ne doit être multi-octets. Un wchar_t représente un seul caractère. Quand vous venez à la sérialisation cependant, c'est quand vous avez besoin de coder quelque chose comme de l'UTF-8 où certains personnages sont représentés par plusieurs octets.

Vous aurez également à l'écriture de nouvelles versions de strcmp etc. pour l'échelle des chaînes de caractères, mais ce n'est pas un gros problème. Le plus gros problème sera de l'interopérabilité avec les bibliothèques/code existant qui n'acceptent que des tableaux de char.

Et quand il s'agit de sizeof(wchar_t) (vous aurez besoin de 4 octets si vous voulez le faire à droite), vous pouvez toujours le redéfinir à une plus grande taille avec typedef/macro hacks si vous en avez besoin.

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