Utiliser des charactères étendus ################################ Le standard ISO/ANSI C contient, dans une correction qui fut ajoutée en 1995, un type de caractère codé sur 16 bits ``wchar_t``, un ensemble de fonctions comme celles contenues dans et (déclarées respectivement dans et ), et un ensemble de fonctions de conversion entre ``char *`` et ``wchar_t *`` (déclarées dans ). Tout ce qu'un programme doit faire c'est appeler ``setlocale(LC_ALL,"");`` pour que ces fonctions fassent ce qu'il faut selon la locale de l'utilisateur. Pourquoi les utiliser? ====================== Avant, les ordinateurs traitaient des données encodées avec un jeux de caractères limité ``char`` qui peut prendre 256 valeurs différentes, ce qui correspond aux entrées dans les tables latines de l'**ISO**. D'autre part, le caractère large peut prendre plus de 65536 valeurs, ce qui correspond aux valeurs Unicode. Il s'agit d'une norme internationale plus récente qui permet l'encodage de caractères pour pratiquement toutes les langues et les symboles couramment utilisés. ``wchar_t`` est un type de caractère étendu. Il est utilisé pour représenter des caractères qui nécessitent plus de mémoire qu'un caractère normal. Il est conseillé de l'utiliser si vous souhaitez que votre programme gère correctement les caractères spéciaux tels que les caractères accentués. Exemple ======= .. literalinclude:: sources/widechar/wide.c :language: c :linenos: Le programme ci-dessous affiche le résultat suivant: .. code-block:: text longueur de la chaine char* s1: 14. longeur de la chaîne wchar_t *s2: 13. taille des caractères de char *s1: 1. taille des caractères de wchar_t *s2: 4. mesure de la chaine char *s1: 14. La sortie ci-dessus montre bien qu'il y a quelquechose d'étrange: le mot **Démonstration** fait 13 caractères de longs, alors que la fonction ``strlen()`` renvoie une longueur de 14 caractères. C'est d'autant plus étrange que la fonction équivalente ``wcslen()`` pour les caractères étendus renvoie bien le nombre correct de caractères: 13. Et bien ceci s'explique par le fait que le type ``char`` représente les caractères sur 1 octet et que pour représenter le caractère **é** il utilise deux valeurs de 1 octet. Alors que le type ``wchar_t`` utilise 2 à 4 octets par caractère selon l'implémentation. Ici, dans notre exemple, le mot **Démonstration** a une taille de 14 octets lorsqu'il est représenté en ``char`` et 52 octets lorsqu'il est représenté en ``wchar_t``. .. warning:: Il est évident que si vous écrivez un programme devant mesurer la taille des mots il ne retournera pas un résultat correct dans toutes les langues si vous utilisez le type ``char``. Utiliser le type ``wchar_t`` ============================ Faire appel à ``setlocale()`` ----------------------------- Et bien pour commencer, comme dit précédemment, tout ce qu'un programme doit faire c'est appeler ``setlocale(LC_ALL,"");``. Il est donc nécessaire d'include ```` dans votre programme, et de procéder à son appel avant tout affichage. Représenter une chaîne étendue ------------------------------ Comme on peut le voir dans l'exemple ci-dessus, à la ligne 17: ``wchar_t *s2 = L"Démonstration";`` est la déclaration d'une chaîne de caractères étendue. En fait, il suffit tout simplement de préfixer une déclaraction de chaîne normale avec ``L``. Et c'est pareil pour les caractères, par exemple on aurait pu déclarer: ``wchar_t c = L'ù';`` Et, attention, le type ``char`` ne gère pas ce cas. Par exemple le programme ci-dessous compile sans erreur: .. literalinclude:: sources/widechar/wide2.c :language: c Alors que le programme ci-dessous ne va pas faire ce à quoi on pourrait s'attendre: .. literalinclude:: sources/widechar/wide3.c :language: c Lors de la compilation **gcc** émet deux alertes: .. code-block:: text warning: multi-character character constant [-Wmultichar] char c='é'; ^~~~ warning: overflow in implicit constant conversion [-Woverflow] Et si on exécute ce dernier il n'affichera pas le caractère ``é`` mais: .. code-block:: text le caractère est: �. Conclusion ========== Je vous invite à porter de l'intérêt à cela, et pas uniquement lorsque vous programmez en C, mais dès lors que vous utilisez une application manipulant des chaînes de caractères et proposant l'usage de ces types. Cet article est loin d'être complet et exhaustif, pour allez plus loin, la librairie C offre toutes les fonctions nécessaires pour utiliser le type ``wchar_t``, ainsi que des fonctions de convertions entre ``char`` et ``wchar_t``.