IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

cout, string et TCHAR


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut cout, string et TCHAR
    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.

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 630
    Points : 30 699
    Points
    30 699
    Par défaut
    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

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Points : 858
    Points
    858
    Par défaut
    Tu peux les définir toi même :
    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
    ou une autre façon de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef std::basic_string<TCHAR> tstring;
    ...

  4. #4
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    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;
    }

  5. #5
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par camboui
    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).
    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).

    Citation Envoyé par camboui
    Voilà à quoi j'en suis réduit, c'est pas trop élégant je trouve
    En effet j'aurais préféré #define _tcout std::[w]cout par exemple, comme ça _tcout ne ferait pas partie de std.

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par camboui Voir le message
    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).
    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.

  7. #7
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    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...

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par camboui Voir le message
    Tu ne fais plus que des applis en wchar_t ?
    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...

  9. #9
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Extrait de la FAQ (merci Aurélien)
    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.
    Là, c'est mal parti. On peut pas faire un simple getline() sur un fichier en unicode ?

  10. #10
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    AFAIK il faut ouvrir les fichiers en binaire pour gérer les IO en unicode...

  11. #11
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Comment se fait-il qu'un détail aussi élémentaire ne soit pas géré ?
    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;
    Ce code crée un fichier ne contenant que "test ".
    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 !

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par camboui Voir le message
    Là, c'est mal parti. On peut pas faire un simple getline() sur un fichier en unicode ?
    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.

  13. #13
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    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 unicode
    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;
    Exception car "unicode" n'est pas une valeur valide.
    Comment connaitre la liste des valeurs "locale" valides ?
    Comment utiliser les locales ?
    Des exemples concrets ?
    Merci

  14. #14
    Membre éclairé

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Points : 858
    Points
    858
    Par défaut
    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".

  15. #15
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    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:
    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;
    Voici l'affichage
    12345.6
    12á345,6


Discussions similaires

  1. Conversion variable string en TCHAR dans dll
    Par Pierre95 dans le forum Débuter
    Réponses: 6
    Dernier message: 10/07/2013, 13h36
  2. Conversions : String->int et int->TCHAR
    Par CyberSlan dans le forum C++
    Réponses: 10
    Dernier message: 13/06/2008, 16h12
  3. Réponses: 2
    Dernier message: 25/04/2008, 07h37
  4. de Tchar[2048] à String
    Par PP(Team) dans le forum C++Builder
    Réponses: 10
    Dernier message: 23/04/2007, 15h45
  5. [C++> C#]Comment régler problème de type TCHAR*/string ?
    Par fkerbourch dans le forum C++/CLI
    Réponses: 6
    Dernier message: 10/03/2006, 10h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo