TCHAR est un #define sur char ou wchar_t.
Existe-t-il les mêmes #define pour cout et wcout, string et wstring, ostringstream et wostringstream, etc ?
Merci.
TCHAR est un #define sur char ou wchar_t.
Existe-t-il les mêmes #define pour cout et wcout, string et wstring, ostringstream et wostringstream, etc ?
Merci.
Salut,
En fait, string,istringstream, ostringstream wstring, wistringstream et wostringstrieam ne sont que des typedef de classes template, les uns spécialisant celles-ci avec des char, les autres les spécialisant avec des wchar.
cin et cout sont, quant à elles, des instances globales de variables, dont le type est, de manière générale, dérivée des même flux que les *stringstream.
Ce ne sont normalement pas de define, mais bel et bien des typedef
Tu peux les définir toi même :ou une autre façon de faire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 #ifdef _UNICODE typedef std::wstring tstring; ... #else typedef std::string tstring; ... #endif
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2typedef std::basic_string<TCHAR> tstring; ...
koala01, merci mais je crois que tu n'as pas compris ma question.
Sylvain, merci. J'aime bien l'autre façon de faire
Donc rien n'est prévu en C++ pour compiler un projet entièrement en unicode ou en ascii. Ce n'est prévu que lorsqu'on fait du C avec l'api Windows et/ou la crt lib (avec les _tcscpy, _tcscmp, etc).
Voilà à quoi j'en suis réduit, c'est pas trop élégant je trouve
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 #include <iostream> #include <iomanip> #include "tchar.h" #include <string> #ifndef _tstring # ifdef _UNICODE # define _tstring wstring #else # define _tstring string # endif #endif #ifndef _tcout # ifdef _UNICODE # define _tcout wcout #else # define _tcout cout # endif #endif ... int cppmain(int argc, _TCHAR* argv[]) { std::_tstring helloworld(_T("Hello world!");; std::_tcout << _T("Message: ") << helloworld.c_str() << std::endl; #ifdef _DEBUG std::_tcout << _T("DEBUG: press any key to finish") << std::endl; _getch(); #endif return 0; } int _tmain(int argc, _TCHAR* argv[]) { #ifdef _DEBUG OutputDebugString(argv[0]); OutputDebugString(_T(" debug: main begins\n")); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF //_CrtSetBreakAlloc(-1);//sets _crtBreakAlloc //_crtBreakAlloc=-1;// <- set _crtBreakAlloc using the debugger without recompiling #endif int exitCode; __try { exitCode=cppmain(argc,argv); } __except(EXCEPTION_EXECUTE_HANDLER) { std::_tcout << std::endl << "Critical ERROR!!! structured exception handling" << std::endl << std::endl; exitCode=EXIT_FAILURE; } #ifdef _DEBUG OutputDebugString(argv[0]); OutputDebugString(_T(" debug: main ends\n")); #endif return exitCode; }
C'est un peu vrai. Pour être plus exact, les TCHAR et fonctions associées font partie de la CRT et de l'API Windows qui peuvent toutes être utilisées aussi bien en C qu'en C++. Mais ont est bien d'accord que tout ça se sont des extensions Microsoft hein, éventuellement disponibles dans d'autres implémentations (pratiquement dans toutes les implémentations Windows).Envoyé par camboui
En effet j'aurais préféré #define _tcout std::[w]cout par exemple, comme ça _tcout ne ferait pas partie de std.Envoyé par camboui
Sauf que je ne crois pas aux TCHAR et autre... Pourquoi je n'y crois pas ? simplement parce que pour un vrai projet, on va se retrouver à devoir gérer dans un seul programme différents types de chars, pour prendre en compte différents types de fichier. Donc pas de TCHAR partout...
Et dans l'autre sens, quel intérêt sur du nouveau code de devoir gérer deux versions des exécutables, des DLL... non compatibles entre elles ?
Sans compter que toutes ses macros, ça fini par causer des soucis (et si j'ai une variable qui porte le même nom qu'une des nombreuses macros définies pas VC++ pour gérer ça ?).
Mon conseil est donc d'oublier ces histoires qui n'ont peut-être de l'intérêt que pour préparer un portage d'une vieille appli de char vers wchar_t sans tout casser lors de la phase de portage, et d'écrire directement le code en utilisant wchar_t en interne et en gérant les différents types d'encodage pour les fichiers externes.
Tu ne fais plus que des applis en wchar_t ?
J'aurais peut-être dû y passer plus tôt puisque j'utilise souvent des objets COM qui m'impose cette m.rd. de BSTR (ADO, msxml, etc). D'un autre coté, on ne travaille qu'en ISO8859-1 (voir UTF8) avec des données sur fichiers qui font quelques gigas. Il est bon d'éviter de trimballer le double de volume qui ne contiendrait que des zéros en plus sans compter que de nombreux (vieux) outils ne connaissent que les char (en particulier ceux qui manipulent les fichiers texte, justement).
D'un autre coté il y a un choix politique à faire. Pas simple tout ça...
Globalment oui. Même si on gère de gros volumes de données en UTF-8, l'appli elle même est en wchar_t, hors code legacy.
Les vieux outils qui ne connaissent que des char vont de toute manière poser des problèmes d'interface si tu tentes de les faire marcher avec des TCHAR compilés en mode unicode, donc tu n'éviteras pas avec TCHAR de devoir soit réécrire cette application legacy, soit faire des conversions à l'interface.
Et ils vont poser des problèmes bien plus important dès qu'ils devront traiter des données étrangères...
Extrait de la FAQ (merci Aurélien)Là, c'est mal parti. On peut pas faire un simple getline() sur un fichier en unicode ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 Notez qu'une version Unicode existe aussi pour les flux, afin de les rendre utilisables avec wstring et wchar_t. Ainsi, on utilisera wcout pour l'affichage, wcin pour la saisie, wifstream pour la lecture de fichiers, ... Cependant, en ce qui concerne les fichiers, les caractères wchar_t sont convertis de manière transparente en char au moment de l'écriture. Le C++ standard ne permet pas en effet de manipuler des fichiers Unicode.
AFAIK il faut ouvrir les fichiers en binaire pour gérer les IO en unicode...
Comment se fait-il qu'un détail aussi élémentaire ne soit pas géré ?Ce code crée un fichier ne contenant que "test ".
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 std::wofstream of(L"tfile.txt"); of << L"test Αα Ππ" << std::endl; of << L"test Ββ Ωω" << std::endl;
C'est l'horreur, c'est épouvantable, c'est une catastrophe !
On peut sauver nos cpp en unicode ou utf8, c'est toujours ça.
Mais lire des fichiers unicode en binaire c'est ridicule, grotesque !
EDIT: le forum est encore plus ridicule, il n'affiche même pas mes beaux caractères en grec !
Dans un flux, il faut différencier deux formats de caractères : Le format écrit dans le flux, et le format que voit le programme qui manipule le flux. Les flux en w... indiquent simplement que le programme va manipuler les flux avec des wchar_t (par exemple, on peut faire wcout << L"Test"), il n'indique rien sur le format des caractères du flux eux-mêmes.
Pour gérer ce second aspect, il faut jouer sur les codecvt de la locale utilisée par les flux. Par exemple, boost fournit un codecvt pour l'UTF8, et créer un codecvt pour l'UCS-2 n'est pas très compliqué. Je m'étais même fait une classe qui va lire les premiers caractères d'un flux à l'ouverture (le BOM) afin d'imbuer la bonne locale de manière transparente (désolé, je ne peux pas filer le code, il appartient à ma boîte).
Je crois qu'en C++0x, il y aura des choses "out of the box" pour ça, et il est possible que tu les aies déjà si tu utilises un compilo récent.
Il semble que tout réside dans locale et use_facet, mais j'ai rien trouvé dans la faq à ce propos.
EDIT:
Supposons que ufile.txt soit un fichier en unicodeException car "unicode" n'est pas une valeur valide.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 std::wifstream ifs("ufile.txt"); std::locale loc("unicode"); ifs.imbue(loc); std::wstring s; while (std::getline(ifs, s, L'\n')) std::wcout << s.c_str() << std::endl;
Comment connaitre la liste des valeurs "locale" valides ?
Comment utiliser les locales ?
Des exemples concrets ?
Merci
Unicode n'est pas un encodage, c'est une table de caractères.
Les encodages c'est UTF-8, UCS-2, UCS-4, ...
Pour savoir lesquels sont disponibles sur ta machine il faut consulter la doc de ton compilateur et ou bibliothèque standard. Le standard n'impose qu'une seule locale, je crois, c'est la locale "C".
Encodage et jeu de caractères sont deux choses différentes, en effet. Reste que mélanger les deux quand on parle d'unicode n'est pas trop un soucis, on se comprend
Le problème reste entier. On aurait pu s'attendre à un support aisé des streams du C++ pour ouvrir des fichiers textes en détectant le BOM (Byte Order Marker) et d'en faire l'extraction correcte, éventuellement en fonction de la locale si une réduction wide string vers multibyte string est imposée.
Mais il n'en est rien.
Je n'étais déjà pas fan des stream C++ (lent, compliqué, mal adapté aux accès binaires), voilà qu'ils ont définitivement perdu tout crédit à mes yeux.
J'ai fait un petit test:Voici l'affichage
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 std::cout << 12345.6f << std::endl; std::cout.imbue(std::locale("French")); std::cout << 12345.6f << std::endl;
12345.6
12á345,6
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager