Mettez des accents dans vos programmes avec le type wchar_t

Formation

En Ligne

Prix sur demande

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Description

  • Typologie

    Formation

  • Méthodologie

    En ligne

Grâce à cette formation vous pourrez acquérir les connaissances nécessaires qui vous permettrons d’ajouter des compétences à votre profil et obtenir de solides aptitude qui vous offriront de nombreuses opportunités professionnelles.

Questions / Réponses

Ajoutez votre question

Nos conseillers et autres utilisateurs pourront vous répondre

À qui souhaitez-vous addresser votre question?

Saisissez vos coordonnées pour recevoir une réponse

Nous ne publierons que votre nom et votre question

Les Avis

Le programme

Introduction du cours

Bonjour à tous !
Aujourd'hui, nous allons voir comment utiliser les caractères spéciaux en langage C.
Vous êtes fatigués de ne pas pouvoir utiliser de textes contenant de beaux accents dans vos programmes en C ? Cette injure à la langue française vous révolte :-° ? Ce tuto va vous permettre de rendre vos programmes bien plus fonctionnels et agréables à utiliser !
Nous allons apprendre à utiliser une nouveauté du C99 vous permettant de gérer nativement, sans bibliothèque tierce, les caractères spéciaux dans toutes vos chaînes de textes.

Bonne lecture !

Caractères spéciaux et langage C : un peu d'histoire

Tout d'abord, pour mieux comprendre ce que l'on va faire par la suite, je vous invite à une petite rétrospective sur le langage C.

Pourquoi les caractères spéciaux en C c'est si compliqué ? Pourquoi je ne peux écrire tout simplement ça ?

char texte[4] = {'ζ', 'é', 'Щ', '\0'}

Bizarrement, la réponse à cette question est à la fois simple et compliquée. Simple, parce que le langage C a été inventé par des américains qui, comme vous devez le savoir, n'utilisent pas d'accents ou de lettres bizarroïdes. À une époque où les ordinateurs étaient encore volumineux et disposaient de très peu de mémoire, le type char conçu pour stocker des caractères devait prendre le moins de place possible en mémoire. Il ne peut donc stocker que des entiers de -128 à 127.

Compliquée, parce que 256 nombres ce n'est pas du tout suffisant pour stocker tous les caractères de toutes les langues ! Pensez aux cédilles françaises, aux accents espagnols, aux Umlauts des allemands ou, pire, aux lettres des grecs et des russes ! Et je ne parle même pas des chinois avec leurs milliers d'idéogrammes ...
Le type char ne peut en fait stocker que quelques types de caractères, selon la très ancienne norme ASCII, que vous pouvez consulter sur ce site.

Mais alors, que faire ? Finalement, pour remédier à cette situation intolérable, de nouvelles normes de transformation des lettres en chiffres (on parle d'encodage) ont été successivement instaurées : d'abord l'ASCII étendu, qui a l'avantage de gérer un plus grand nombre de caractères, y compris nos fameux accents (elle couvre presque toutes les langues européennes). Les chinois, arabes et japonais ont dû quant à eux attendre l'arrivée de l'Unicode, qui gère la totalité des caractères présents sur terre, pour pouvoir utiliser les ordinateurs dans leurs langues.
Et aujourd'hui encore, cette affaire d'encodage est loin d'être réglée et de nombreux problèmes de comptabilité subsistent... On est donc bel et bien en terrain hostile.

Windows possède depuis toujours un léger retard sur la gestion des caractères spéciaux. Sur les OS dits de "type UNIX", comme Linux, Mac OS, etc., la gestion de l'Unicode est intégrée au système à la base, et est donc bien plus transparente. Par exemple, sous Linux, vous pouvez sans problème inclure des accents dans votre code-source, car Linux enregistre les fichiers en UTF-8, l'une des variantes de l'Unicode. Sous Windows, c'est impensable. À ce sujet, Windows 7 suscitait beaucoup d'espoir, mais il n'est en fait toujours pas passé à l'Unicode.

Pour utiliser en C ces nouveaux outils, il nous faut un type de caractères plus grand que char, qui a une "taille" de 1 octet et ne peut donc stocker que $2^8$ soit 256 caractères différents. En multipliant le nombre d'octets par 2 voire 4, on augmente significativement le nombre de caractères gérés : une variable qui occupe 2 octets peut stocker $2^{16}$, soit 65 536 caractères différents !

Ce type existe, il s'appelle wchar_t, mais il n'a été introduit en C que tardivement. C'est pourquoi pour l'utiliser correctement il nous faudra passer notre compilateur en mode C99 (nous verrons comment on fait). Nous allons aussi utiliser de nouvelles fonctions spécifiques aux caractères spéciaux, mais rassurez-vous dans l'ensemble, tout restera très similaire aux chaînes de caractères "classiques".

Vous l'aurez compris : nous allons tout simplement mettre le type char à la poubelle ! Faites lui vos adieux, il n'est plus adapté à notre époque... De nos jours la mémoire ce n'est plus ce qui manque, et se limiter à quelques lettres est bien trop restrictif. Le nouveau type que nous allons utiliser, le type prend plus de place en mémoire, mais se fera un plaisir de stocker tous les caractères que vous voulez, en ASCII étendu voire en Unicode.

À l'assaut de <wchar.h>Le type wchar_t : quelques infos théoriques

Tiens, que signifie wchar_t ?

Cette question m'a été posée dans les commentaires : wchar_t signifie Wide Character Type. "Wide Character" signifie littéralement "Caractère Étendu", ce que l'on peut interpréter par "Caractère Spécial" (codé sur plus d'un octet) ; en français on pourrait donc traduire l'expression par Type caractère spécial.

Quelle place prend le type wchar_t en mémoire ?

Cette question est inévitable, et pourtant soyez sûrs que je la redoutais. En deux mots : ça dépend. Selon de nombreux paramètres, en particulier votre compilateur, le type wchar_t peut prendre 2 octets (2 x 8 bits), ou 4, ou plus... Si cela vous intéresse, cette petite ligne de code vous renseignera :

printf("%d", sizeof(wchar_t));

La plupart du temps, sauf compilateur ou système bizarroïde, vous pouvez vous attendre à ce que wchar_t prenne 2 octets.

Mais en fait, selon quelle norme est stockée une lettre dans un wchar_t ?

Là encore, la réponse est à la fois simple et cauchemardesque : ce n'est pas spécifié. Le type wchar_t vous laisse simplement stocker des nombres bien supérieurs à 127, en vue d'utiliser des caractères spéciaux, mais il ne fixe aucun encodage particulier. Là encore, tout dépend de votre compilateur et de votre OS, voire des bibliothèques que vous utilisez.
Dans le souci de préserver le côté théorique, simple et multiplateforme de ce tuto, je n'envisage pas de vous faire un cours magistral sur la gestion de l'Unicode. Nous allons d'abord faire nos tests avec l'ASCII étendu, une simple extension de l'ASCII qui permet de gérer nos chers accents et fonctionne aujourd'hui de la même façon sur quasiment toutes les plateformes. Mais soyez prévenus : vos valeurs peuvent être différentes des miennes...
Pour utiliser l'Unicode, il faudrait utiliser une bibliothèque tierce, ou les outils spécifiques livrés avec les OS. Et la console Windows est si limitée sur ce point qu'il ne faudrait pas espérer faire des programmes en russe... Certaines bibliothèques proposent même leurs propres types pour gérer l'Unicode, on n'est donc pas sortis de l'auberge si on commence à s'aventurer dans cette voie.
Vous l'aurez compris, pour vous apprendre à utiliser le type wchar_t, nous ne ferons que de simples essais en ASCII étendu ayant pour but d'afficher des accents. Cela vous permettra à la fois d'acquérir les bases de la gestion des chaînes de caractères spéciaux et d'accentuer les caractères de vos programmes en console.

Configurer le compilateur

Comme je l'ai dit, avant de pratiquer nous devons faire une petite manipulation pour passer notre compilateur en mode C99.

Le C99 est une amélioration récente du langage C, qui apporte quelques nouveautés intéressantes. Si vous ne faites pas cette manipulation, il est très probable que la compilation plante dans la suite du tutoriel : ne négligez pas cette partie !

Je vais vous expiquer pas à pas comment faire sous Code::Blocks 10.05, puisque cet IDE est libre et multi-plateformes, mais la procédure est similaire sur les autres IDE.
Cette procédure est spécifique au GNU GCC Compiler, un compilateur libre très utilisé. Les compilateurs propriétaires, comme celui de Microsoft, aurons d'ailleurs de fortes chances d'être déjà en C99.

  • Dans le menu de Code::Blocks, allez dans "Settings" puis "Compiler and Debugger.."

  • Vérifiez que dans la partie "Selected Compiler", l'option GNU GCC Compiler est bien séléctionnée.

  • Ensuite, cliquez sur l'onglet "Compiler Settings" puis allez dans le sous-onglet "Other options".

  • Dans le champ de texte qui se présente à vos yeux, tapez EXACTEMENT cette chaîne de texte : -std=c99

  • Cliquez sur "OK" puis, seulement maintenant, créez un nouveau projet. On y est arrivé :-° !

Modifier les directives de préprocesseur du projet

En plus des fichiers de la bibliothèque standard que vous intégrez habituellement à vos projets, vous allez ajouter cette ligne à vos directives de préprocesseur :

#include <wchar.h>

C'est en effet dans cette partie de la bibliothèque standard du C99 que se trouvent les fonctions de manipulation des caractères spéciaux qui nous intéressent.

Le monde merveilleux des accentsNotre première chaîne de wchar_t

Nous y sommes ! Voyons maintenant comment créer puis afficher une chaîne de caractères accentués. Nous allons nous exercer sur des caractères simples, les caractères ASCII étendu, qui incluent les è, î, à, etc. En effet, le type wchar_t permet de stocker bien d'autres caractères mais compilateur et consoles pourraient se montrer capricieux, comme je l'ai déjà expliqué.

Comme je vous l'ai dit, il faut d'abord utiliser un nouveau type de caractère. Fini le type char, dorénavant nous utiliserons le type wchar_t.

Si les chaînes standard sont des tableaux de char, les chaînes ASCII étendu sont des tableaux de wchar_t. Rien ne change à ce niveau-là !
Ce code créé un tableau de 50 wchar_t, donc 49 caractères.

#include <stdlib.h> #include <stdio.h> #include <wchar.h> int main() { wchar_t texte[50]; return 0; }

Même avec le type wchar_t il ne faut pas oublier le fameux '\0', caractère qui termine toute chaîne de texte ! Attention aux pièges...

Voyons maintenant comment initialiser cette chaîne avec le texte "Salut !"
Essayons ce code :

#include <stdlib.h> #include <stdio.h> #include <wchar.h> int main() { wchar_t texte[50] = "Salut !"; return 0; }

Aïe, ça ne fonctionne pas ...
C'est tout à fait normal, vu que ce code tente de remplir une chaîne wchar_t avec une chaîne classique ! Les deux types sont différents, et donc ça coince à la compilation...
Pour spécifier au compilateur qu'il s'agit d'une chaîne wchar_t étendu, vous DEVEZ ajouter un L avant les guillemets. Ainsi, ce code est parfaitement correct.

wchar_t texte[50] = L"Salut !";

Attention : ce n'est pas à ce stade que vous pouvez ajouter des accents. En effet, ce code a de gros risques de planter à la compilation !

wchar_t texte[50] = L"Salut Gérard !";

Notez que si le type wchar_t vous autorise à gérer les caractères accentués, il ne vous autorise pas à en insérer dans votre code ! Par exemple, n'appelez jamais une variable "chaîne", ou "élément", vous risquez de gros plantages !

Mais alors, comment initialiser cette chaîne si elle contient un é ? Nous allons dans un premier temps faire comme au bon vieux temps, caractère par caractère. Ainsi, ce code est parfaitement correct. Notez qu'il faut ajouter le L avant la valeur de chaque lettre. Ce n'est pas indispensable, mais bien plus propre !

wchar_t texte[50] = {L'S', L'a', L'l', L'u', L't', L' ', L'G', 130, L'r', L'a', L'r', L'd', L' ', L'!', L'\0'};

C'est quoi ce 130 qui traîne ?

Bonne question ! C'est en fait le é de ce pauvre Gérard. Tous les compilateurs n'acceptent pas la notation L'é', pourtant plus pratique. Il faut donc remplacer la lettre é par sa valeur en ASCII étendu, et cette valeur, c'est 130.
Vous trouverez les valeurs ASCII étendu correspondant à chaque caractère sur ce site.

Selon le compilateur que vous utilisez, certaines valeurs peuvent être complètement différentes des miennes ! Cela ne doit pas trop vous perturber, demandez de l'aide sur les forums pour connaître l'encodage de votre compilateur ou utilisez, comme moi, Code::Blocks avec le GNU GCC Compiler^^ .

Cette méthode d'initialisation n'est extrêmement pas pratique, c'est pourquoi il existe une petite astuce pour s'en passer : les échappements. Les échappements sont tout simplement des raccourcis pour faire figurer des caractères spéciaux dans l'initialisation d'un chaîne. Un échappement se présente sous la forme :
\xNN
NN est tout simplement la valeur ASCII du caractère à afficher. Elle doit être exprimée dans le système hexadécimal. Pour convertir un nombre standard en valeur hexadécimale, vous pouvez utiliser la calculatrice Windows ou un outil sur internet, en voici un.

Revenons à notre code source de tout à l'heure. Je vous le remémore.

wchar_t texte[50] = {L'S', L'a', L'l', L'u', L't', L' ', L'G', 130, L'r', L'a', L'r', L'd', L' ', L'!', L'\0'};

Plutôt terrible, n'est-ce pas ? Sachant que la valeur de "é" en ASCII est 130, et que cette valeur vaut 82 en hexadécimal, on va pouvoir utiliser pour "é" l'échappement \x82 ! Voici le code en question.

wchar_t texte[50] = L"Salut G\x82rard !";

Un peu plus commode, hein ?

Normalement, vous connaissiez déjà des échappements dits "spéciaux" : par exemple, \n pour le saut de ligne.

Afficher et récupérer une chaîne de wchar_t

Nous allons maintenant tester un bout de code qui devrait vous sembler intuitif, mais qui est vraiment archi-faux :p !

wchar_t texte[50] = {0}; fgets(texte, 50, stdin); printf("%s", texte);

Il fallait s'en douter, ça ne marche pas. Ce serait trop beau !
Il manque en effet trois choses à ce code pour le rendre fonctionnel. Vous devez connaître la première.

  • Il faut ajouter un L avant chaque guillemet représentant une chaîne. C'est primordial pour indiquer qu'il s'agit d'une chaîne de texte wchar_t !

  • Les codes %c et %s, indiquant où insérer un caractère et une chaîne de caractères, ne fonctionnent plus ! Il faut les remplacer par leur équivalent, c'est-à-dire %lc et %ls !

  • Enfin, TOUTES les fonctions de manipulation du texte doivent être remplacées par leurs équivalents dans la bibliothèque wchar.h. Ne faites pas ces têtes-là, ces fonctions sont heureusement similaires aux fonctions que vous...

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Mettez des accents dans vos programmes avec le type wchar_t

Prix sur demande