Caractères accentué dans les chaines

Caractères accentué dans les chaines - C - Programmation

Marsh Posté le 07-09-2007 à 00:33:58    

Salut,
 
Quand on a:

Code :
  1. int main(int argc, char** argv)


on récupère les chaines de caractères de la ligne de commande avec argv. Comment faire quand c'est chaines contiennent un é, è, ï, ö, ê etc... pour qu'il soit conservé ?
Quand je fais un printf() d'une de ces chaines un tel caractère est remplacé par un caractère bizarre.
Il me semble que cela est une histoire de ANSI et UNICODE mais j'ai pas très bien compris et j'ai pas trouvé la solution. J'ai trouvé des trucs genre _T("cahine de caractère" ) ou TEXT("chaine de caractère" ) ou des fonction avec un w devant, ca a un rapport ou pas du tout ?

Message cité 1 fois
Message édité par cimourdain le 07-09-2007 à 01:10:32
Reply

Marsh Posté le 07-09-2007 à 00:33:58   

Reply

Marsh Posté le 07-09-2007 à 01:34:53    

Oué, fait gaffe, la fenêtre DOS utilise un jeu de caractère qui n'a rien à voir avec celui de Windows. DOS utilise je ne sais plus quel code page préhistorique, windows pour son charset 8bit utilise le code page 1252 a.k.a. Windows1252 qui assez proche de l'iso-8859-1 (a.k.a Latin1). Pour le charset dit unicode, c'est de l'UTF-16LE.
 
Pour faire simple :
- CP1252 et le truc DOS sont compatibles ASCII (128 premiers caractères), le reste est différent. Ce sont des charsets 8bits, les éditeurs sous Windows vont mettre du CP1252 dans tes chaines, ceux sous DOS (entre autres les éventuels paramètres que tu vas passer à ton programme -- sauf si tu passes par ton IDE), le charset DOS dédié donc. En C, tu utilises les chaines classiques, entre double quote et c'est tout.
- UTF-16 : tu peux soit te farcir les codes caractères à la main dans les chaines à coup de \xXX\xXX ou préfixer tes chaines par L, du genre : L"Hello". En mémoire tes caractères seront stockés sur 16bits, ordre des octets de ta machine (certainement du little endian). Pour utiliser de telle chaine dans la famille de fonction printf, tu dois utiliser le spécificateur %S ou %ls (ce qui sous DOS revient à tronquer les caractères sur 8bits).
 
L'API Win32 en rajoute une couche (haha) : elle définit la macro _T(chaine) qui rajoutera automatiquement le L si tu compile ton programme en unicode ou non (je ne me rappelle plus le nom de la macro, mais gougeule doit s'en souvenir). En fait si tu regardes l'API Win32, 90% des fonctions sont en doubles : une version pour les charsets 8bits et une autre pour l'UTF-16.
 
Chais pas si c'est plus clair ...  :pt1cable:
 
Perso je préfère passer par de l'UTF-8 (because j'utilisais du CP1252 avant) et convertir à la volée (la conversion UTF-8 => CP1252 ou UTF-16 est assez triviale) si besoin.


Message édité par tpierron le 07-09-2007 à 01:36:51
Reply

Marsh Posté le 07-09-2007 à 02:11:47    

euhhh ouais j'ai pas tout compris là... peut etre demain apres avoir dormi et en relisant tout ca.
 
Mais concretement c'est quoi la fonction _tprintf() ? et ca fait quoi de l'utiliser avec _T ? _printf(_T()) ca a un rapport avec ce que je veux faire ou pas du tout ?
 
En tout cas merci pour ta réponse bien détaillée !
 
EDIT: je crois aussi que je comprends pas ce que ca veut dire compiler en UNICODE ou pas avec le #define et tout...
 
Au fait je code pas pour DOS, je code pour Windows XP et il me semble que sa console (cmd.exe) n'a plus rien a voir avec DOS.


Message édité par cimourdain le 07-09-2007 à 02:46:41
Reply

Marsh Posté le 07-09-2007 à 15:24:34    

Oula, évite en général les fonctions systèmes qui commencent par _, sauf indication contraire (genre _beginthread).
 
En fait DOS dans Windows ressemble (hélas) beaucoup au DOS des anciennes versions. Tu ne peux plus lancer d'appli en mode privilégié, mais il a toujours les mêmes tares que ses ancêtres, entre autre son jeu de caractère à la con. Suivant l'environnement où tu lances ton programme, ça va influencer la valeur des caractères non-ASCII.
 
Je ne sais pas si DOS est capable d'afficher des caractères unicode uniquement avec printf, et à supposer que ça soit possible, tu va te prendre la tête pour pas grand chose.
 
Les fonctions C (printf, ...) ne feront aucune conversion de charset, si tu leur transmet du CP1252 et que ça va atterir dans une fenêtre DOS (à priori si tu utilises printf, il n'y a pas d'autres endroits où ça peut aller), bah tes caractères non-ASCII vont affichés n'importe quoi. Ça ne veut pas dire que tu as n'importe quoi dans ta chaine. À la limite, redirige la sortie de ton programme dans un fichier et utilise une appli windows (pas DOS) pour le lire.
 
Bref, tout ça pour dire : DOS et Windows (3.1 à Vista) utilisent deux charsets différents. Au-delà de l'ASCII, pas de compatibilité. _T() est une macro à utiliser que si tu utilises l'API Win32 ou les MFC. Sinon oublie là.

Reply

Marsh Posté le 07-09-2007 à 16:29:14    

Sous Windows ça peut se régler en faisant un system ("chcp 1252" ); et en utilisant la police Lucida.

Reply

Marsh Posté le 07-09-2007 à 16:57:51    

ok mais quand j'utilise _T() ca me met pas les accents pour autant.

Reply

Marsh Posté le 08-09-2007 à 15:54:46    

la glib, utf8 ?


---------------
Blog photo/récits activités en montagne http://planetcaravan.net
Reply

Marsh Posté le 08-09-2007 à 21:59:32    

cimourdain a écrit :

Salut,
 
Quand on a:

Code :
  1. int main(int argc, char** argv)


on récupère les chaines de caractères de la ligne de commande avec argv. Comment faire quand c'est chaines contiennent un é, è, ï, ö, ê etc... pour qu'il soit conservé ?
Quand je fais un printf() d'une de ces chaines un tel caractère est remplacé par un caractère bizarre.
Il me semble que cela est une histoire de ANSI et UNICODE mais j'ai pas très bien compris et j'ai pas trouvé la solution. J'ai trouvé des trucs genre _T("cahine de caractère" ) ou TEXT("chaine de caractère" ) ou des fonction avec un w devant, ca a un rapport ou pas du tout ?

Je ne sais pas si celà répond à ton problème, mais essaye ce petit code :

Code :
  1. #include <windows.h>
  2. #include <stdio.h>
  3. int main(void)
  4. {
  5. char *txt = "àéïöüôîûêâç";
  6. char recep[256];
  7. AnsiToOem(txt, recep);
  8. printf("Avant %s\nApres %s\n", txt, recep);
  9. return 0;
  10. }


Ce code fonctionne de la même manière

Code :
  1. #include <windows.h>
  2. #include <stdio.h>
  3. int main(int argc, char *argv[])
  4. {
  5. char recep[256];
  6. AnsiToOem(*++argv, recep);
  7. printf("Avant %s\nApres %s\n", *argv, recep);
  8. return 0;
  9. }



Message édité par Trap D le 08-09-2007 à 22:03:19
Reply

Marsh Posté le 09-09-2007 à 19:26:00    

ca marche très bien ! merci du tuyau !

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed