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 :

Abandonner les char au profit des wchart_t


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 Abandonner les char au profit des wchart_t
    Tous les exemples de la FAQ (ou presque) ainsi que tous les tutoriaux utilisent des char et des std::string.
    Pareil pour les iostream. Par défaut c'est fait pour gérer du texte, à condition qu'il soit en en "char" (on va dire "codé sur 8 bits").

    J'essaie de porter mes programmes en unicode afin de laisser tomber définitivement (?) les char et string au profit des wchar_t et wstring. Je pensais la tâche relativement simple puisque les os (enfin, Windows) fonctionnent en unicode en interne. Pareil pour les langages comme Java, C#, l'interface COM, etc.
    Je suis donc en train de changer les char en _TCHAR, les "..." en _T("..."), les string en _tstring (j'en ai fait un #define), les strxxx en _tcsxxx, etc, afin de pouvoir compiler à ma guise en _MBCS ou en _UNICODE.

    Il s'avère que le C++ ne propose pas grand chose pour nous y aider... Pire, il nous met des batons dans les roues.
    Ainsi par exemple pour ouvrir un fichier en utilisant wifstream() le nom de fichier passé en paramètre doit être une chaîne en... char et non pas wchar_t (aberrant je trouve ).
    Autre exemple, les exceptions sont en char, pas en wchar_t (le fameux what() retourne un const char *).
    "Officiellement", la norme C++ dit que wchar_t est au moins aussi grand que char, rien de plus. wchart_t n'est donc pas nécessairement un caractère sur 16 bits (même si en pratique je crois qu'il y a un consensus pour que se soit quand même le cas sur toute les plateformes, sauf peut-être sur les mac ?).

    Bref, comment faire afin d'éviter la moindre conversion interne WideCharToMultiByte et vice versa ?
    Merci pour vos expériences.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Et ca se complique encore quand tu utilises des librairies externes... Les char sont un peu partout, parfois en tant que représentation de caractères, parfois juste comme "unité minimale". Un changement brutal (à coup de define) peut entrainer des catastrophes, un portage manuel peut prendre un temps fou...

    Pareil pour Windows, d'ailleurs, vu de loin, ou des COM, c'est du WideString, mais dès que tu regarde l'API...

    J'ai l'impression que les w_char font partie, avec les valarray de la STL et quelques autres belles idées, de ces zones du standard pas tout à fait abouties, ou en tous cas pas assez utilisées pour être recommandables...

    Si l'utilisation que tu fais des chaines est limitée à l'affichage et la recherche de sous chaines, une bonne solution intermédiaire est l'UTF8. A l'intérieur de ton programme, ça reste des char, leur interprétation en "caractères exotiques" n'étant faite qu'en toute fin de parcours... J'ai l'impression que c'est d'ailleurs ce que font pas mal de programmeurs qui doivent travailler avec des langues multioctets.

    Francois
    Dernière modification par Invité ; 04/03/2010 à 22h56.

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Citation Envoyé par fcharton Voir le message
    J'ai l'impression que les w_char font partie, avec les valarray de la STL et quelques autres belles idées, de ces zones du standard pas tout à fait abouties, ou en tous cas pas assez utilisées pour être recommandables...
    Disons, qu'à l'époque, la problématique n'était pas mûre non plus. Je ne pense pas dire beaucoup de bêtise en disant que dans les années 90 les chaînes de caractères étaient majoritairement gérées par des char y compris côté système.
    Mais, effectivement, les chaînes de caractères, ça fait partie des choses assez pénibles à gérer en C++ et je ne connais pas de solution idéale.

  4. #4
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par camboui Voir le message
    "Officiellement", la norme C++ dit que wchar_t est au moins aussi grand que char, rien de plus. wchart_t n'est donc pas nécessairement un caractère sur 16 bits (même si en pratique je crois qu'il y a un consensus pour que se soit quand même le cas sur toute les plateformes, sauf peut-être sur les mac ?).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #include <iostream>
     
    int main()
    {
            std::cout << sizeof(wchar_t) << std::endl;
    }
    --> 4 chez moi (linux)

    D'ailleurs, il me semble que pour gérer tout l'unicode, il faut effectivement 32 bits par caractères (si tous les caractères font la même taille). Je ne sais pas comme fait windows (puisqu'avec visual, sizeof(wchar_t)==2) pour gérer les caractères qui ne tiennent pas en 2 octets.

    Bref, comment faire afin d'éviter la moindre conversion interne WideCharToMultiByte et vice versa ?
    Merci pour vos expériences.
    Pas vraiment de solution miracle. Mais j'irais un peu plus loin que toi, en rajoutant que non seulement, C++ est pénible pour ce qui est de l'unicode, mais il est pénible pour ce qui est de l'encodage en général : les fonctions de la libc sont dépendantes de la locale courante, et une vraie plaie à utiliser en multithread (et tu n'as aucune garantie qu'une locale est installée sur le système), d'où la nécessité de passer par une lib (comme iconv, par exemple).

    Si tu t'intègres à un framework comme Qt et GTK, tout devient beaucoup plus simple : la gestion des encodages y est intégrée. Mais sinon...

  5. #5
    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
    Citation Envoyé par camboui Voir le message
    "Officiellement", la norme C++ dit que wchar_t est au moins aussi grand que char, rien de plus. wchart_t n'est donc pas nécessairement un caractère sur 16 bits (même si en pratique je crois qu'il y a un consensus pour que se soit quand même le cas sur toute les plateformes, sauf peut-être sur les mac ?).
    C'est plutôt l'inverse, à part sur Windows où wchar_t fait 16 bits, il y a plus ou moins consensus ailleurs pour que wchar_t fasse 32 bits !

    Citation Envoyé par white_tentacle
    D'ailleurs, il me semble que pour gérer tout l'unicode, il faut effectivement 32 bits par caractères (si tous les caractères font la même taille). Je ne sais pas comme fait windows (puisqu'avec visual, sizeof(wchar_t)==2) pour gérer les caractères qui ne tiennent pas en 2 octets.
    Windows, pour des raisons historiques, a d'abord fonctionné en USC-2, puis maintenant en UTF-16.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Points : 1 176
    Points
    1 176
    Par défaut
    Je ne crois pas que ça soit la bonne méthode de tout faire à coup de #define et advienne que pourra.

    Bon je vais pas pouvoir te donner trop de conseils, vu que je n'utilise que des version récentes de Linux pour mes GUI et que Linux gère très bien tout seul la gestion de chaînes UTF-8 à partir de std::strings.

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Je ne sais pas où est le consensus exactement, puis que Java aussi bosse en UTF-16.

    D'un autre côté, quand on ajoute les accents, même UTF-32 ne peut représenter un caractère dans un seul wchar_t (même si un code point dans un seul wchar_t, c'est déjà un progrès).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    D'ailleurs, il me semble que pour gérer tout l'unicode, il faut effectivement 32 bits par caractères (si tous les caractères font la même taille). Je ne sais pas comme fait windows (puisqu'avec visual, sizeof(wchar_t)==2) pour gérer les caractères qui ne tiennent pas en 2 octets.
    Comme pour le 8 bits... Avec des pages de code (ou parfois des polices). Il faut dire que 16 bits, c'est "presque assez" pour tout l'Unicode. En gros, tant que ton programme ne gère pas les langues Mycéniennes, ou les caractères chinois sur os (jiaguwen), tu ne crains pas grand chose...

    Comme ces caractères anciens et rares sont plus souvent lus qu'écrits, on utilise parfois des scans. Sur certains sites, on a des polices spécifiques.

    Pour un bon exemple du type de problème rencontré, et des solutions qu'on y apporte, tu peux regarder chant.org. C'est une base de donnée qui recense toutes les inscriptions chinoises anciennes découvertes, avec donc pas mal de signes qui n'existent qu'en un exemplaire... Il y a un peu d'explication en anglais sur leur site.

    Francois

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Des pages de codes? Surement pas!
    Windows n'utilise pas de pages de codes pour l'Unicode, seulement du bon vieil UTF-16 (enfin bien sûr, quand on convertit en 8 bits, les pages de codes reviennent).

    Pour les polices, c'est un tout autre problème: C'est juste qu'aucune police ne contient tout (Arial Unicode MS est une des plus complètes, mais elle est livrée avec Office, pas Windows).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    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
    Merci pour vos avis. Il n'y a donc pas de solution simple
    Il n'y a même pas de cohérence avec wchar_t dont la taille est tantôt sur 16bits tantôt sur 32... Quelle gaspillage de place quand on n'en a pas l'utilité ! (je doute qu'on soit nombreux sur le forum à avoir besoin des 32 bits )

    Mais il me faut bien faire un choix donc je vais adopter la méthode MS qui consiste à mettre des TCHAR partout puis de compiler au choix avec _MBCS ou _UNICODE. Cela devrait permettre de passer facilement de l'un à l'autre, mais à priori je vais continuer avec le char, l'encodage ISO8859-1 ou la CP1252 ayant comblé 100% de mes besoins jusqu'à présent.

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Au passage, n'oublie pas quelques considérations:
    • Un caractère ISO-8859-1 peut être casté en wchar_t, mais pas un caractère Windows-1252. Donc, penser à utiliser des fonctions de conversion
    • Une console utilise de l'IBM-850 en France et de l'IBM-437 aux États-Unis.
    • Plutôt que des #ifdef/#else/#endif pour les parties n'acceptant que des char ou des wchar_t (comme COM), n'oublie pas que tu codes en C++: La surcharge est ton amie.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    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
    Et bien merci pour tous ces avis et conseils. Je me suis plongé dedans.
    Je souffre

    Question quand même à ceux qui ont un sizeof(wchar_t)==4.
    Sachant que sizeof("abc")==4, que donne sizeof(L"abc") ?
    Sous visual (et donc windows) ça donne 8. Est-ce que ça donne 16 pour ceux dont wchar_t est codé sur 4 bytes ?

  13. #13
    Expert confirmé

    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 382
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 382
    Points : 4 936
    Points
    4 936
    Par défaut
    la seule solution que j'ai trouvé (bon j'ai pas fait des masses recherche, j'avais pas le temps, je devais me faire juste un petit programme pour utiliser la libiconv sous windows) c'est de proscrire l'utilisation des chaines gérées par la stl. j'ai tout passé par les fonctions fournis par windows.

  14. #14
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par camboui Voir le message
    Et bien merci pour tous ces avis et conseils. Je me suis plongé dedans.
    Je souffre

    Question quand même à ceux qui ont un sizeof(wchar_t)==4.
    Sachant que sizeof("abc")==4, que donne sizeof(L"abc") ?
    Sous visual (et donc windows) ça donne 8. Est-ce que ça donne 16 pour ceux dont wchar_t est codé sur 4 bytes ?
    Oui, ça donne 16.

    Effectivement, les CString sont un moyen simple, sous windows, de se passer de ce genre de problèmes. De même que les QString de Qt.

Discussions similaires

  1. Réponses: 1
    Dernier message: 28/07/2010, 13h44
  2. Réponses: 13
    Dernier message: 18/12/2009, 15h00
  3. Type de colonne : Les char deviennent des VarChar !?
    Par Giovanny Temgoua dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 29/06/2005, 13h21
  4. Réponses: 3
    Dernier message: 24/10/2003, 21h46
  5. Créer les get et set des classes
    Par cameleon2002 dans le forum JBuilder
    Réponses: 3
    Dernier message: 17/09/2003, 21h03

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