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 :

Conversions Unicode Ascii


Sujet :

C++

  1. #1
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut Conversions Unicode Ascii
    Bonjour,

    Apparemment le code que l'on retrouve là : Comment effectuer les conversions de texte ASCII <-> Unicode ? ne compile pas sous VC8 SP1.

    L'erreur apparait dés la première ligne de chaque fonction, voici la première :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cannot convert parameter 1 from 'const std::wstring' to 'std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it'
    A priori ça ressemble a un mauvais copier coller?

    Par ailleurs, est-ce que ce code fonctionnera pour tous les charactères Unicodes (donc tous ceux possibles) ou est-ce qu'il faut changer la locale de manière a ce que ça corresponde? Où se trouvent les définitions des locales?

    Merci de votre attention

  2. #2
    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
    Le code dans la FAQ
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    std::string narrow(const std::wstring& ws)
    {
        std::string res(ws);
        std::locale loc("english");
        std::use_facet< std::ctype<wchar_t> >(loc).narrow(&ws[0], &ws[ws.length()], '?', &res[0]);
     
        return res;
    }
    a au moins trois erreurs :

    1) std::string res(ws); n'est pas valide
    2) &ws[ws.length()] n'est pas valide
    3) &res[0] ne retourne pas forcement un pointeur vers les caractères de la chaine

    Il faudrait le remplacer par quelque chose comme ça
    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
    #include <string>
    #include <locale>
    #include <vector>
     
    std::string narrow(const std::wstring& ws)
    {
        std::vector<char> buffer(ws.size());
        std::locale loc("english");
        std::use_facet< std::ctype<wchar_t> >(loc).narrow(ws.data(), ws.data() + ws.size(), '?', &buffer[0]);
     
        return std::string(&buffer[0], buffer.size());
    }
     
    std::wstring widen(const std::string& s)
    {
        std::vector<wchar_t> buffer(s.size());
        std::locale loc("english");
        std::use_facet< std::ctype<wchar_t> >(loc).widen(s.data(), s.data() + s.size(), &buffer[0]);
     
        return std::wstring(&buffer[0], buffer.size());
    }

  3. #3
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    On va corriger ça, merci

  4. #4
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Merci pour la correction, je vais tester ça de suite.

    En attendant je réitère mes questions :

    Par ailleurs, est-ce que ce code fonctionnera pour tous les charactères Unicodes (donc tous ceux possibles) ou est-ce qu'il faut changer la locale de manière a ce que ça corresponde? Où se trouvent les définitions des locales?

  5. #5
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Comme je m'en doutais, le code de la FAQ ne marche pas dans tous les cas.

    Je l'ai proposé sur le forume de Ogre : http://www.ogre3d.org/phpBB2/viewtop...=230609#230609

    Voici une variante avec test proposée dans le thread :
    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
     
    #include "stdafx.h"
    #include <string>
    #include <locale>
    #include <stdlib.h>
     
    using namespace std;
     
    wstring toWideString(const string &str)
    {
       size_t size = mbstowcs(NULL, str.c_str(), 0) + 1;
       wchar_t *wmsg = new wchar_t[size];
       mbstowcs(wmsg, str.c_str(), size);
       wstring ret(wmsg);
       delete wmsg;
       return ret;
    }
     
     
    string toString(const wstring &wstr)
    {
       size_t size = wcstombs(NULL, wstr.c_str(), 0) + 1;
       char *msg = new char[size];
       wcstombs(msg, wstr.c_str(), size);
       string ret(msg);
       delete msg;
       return ret;
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
       string hello("Hello World!");
       wstring hellow = toWideString(hello);
     
       wstring byew(L"Goodbye!");
       string bye = toString(byew);
       return 0;
    }

    Pourrais-je avoir votre avis là dessus ? Je capte pas tout au niveau du jonglage avec les locales pour l'instant...

  6. #6
    Membre habitué
    Avatar de superspag
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    153
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 153
    Points : 186
    Points
    186
    Par défaut
    Tiens ? Je n'avais même pas remarqué que mon code était dans la FAQ...
    Il ne correspond cependant pas tout à fait à ce que j'avais proposé... Il faut remplacer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::string s(ws) ;
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::string s;
    s.resize(ws.length()) ;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::string ws(s) ;
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    std::string ws ;
    ws.resize(s.length()) ;
    Le but est simplement de construire une chaine du bon type et avec la bonne taille. Peut importe ce qu'il y a dedant

    Par contre, je ne vois pas en quoi l'utilisation de l'opérateur [] est une erreur... Quelqu'un peut m'eclairer ? Il y a peutetre une subtilité qui m'échape

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Bizarre que ça ne fonctionne pas sous VC, c'est justement le seul compilo avec lequel ça avait fonctionné pour moi
    Sinon, voici un code qui a fonctionné pour un projet que j'ai testé sous VC (7.1?), Mingw et GCC:
    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
     
    #include <string>
    #include <locale>
     
    std::string narrow(const std::wstring& ws)
    {
        std::string res(ws.length(),' ');
        std::locale loc("english");
        std::use_facet< std::ctype<wchar_t> >(loc).narrow(&ws[0], &ws[ws.length()], '?', &res[0]);
     
        return res;
    }
     
    std::wstring widen(const std::string& s)
    {
        std::wstring res(s.length(),' ');
        std::locale loc("english");
        std::use_facet< std::ctype<wchar_t> >(loc).widen(&s[0], &s[s.length()], &res[0]);
     
        return res;
    }
    PS: sérieux, faudrait quand même tester un minimum avant de mettre des trucs dans la faq, ça ne compile même pas avec un compilo standard.

  8. #8
    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 superspag
    Par contre, je ne vois pas en quoi l'utilisation de l'opérateur [] est une erreur... Quelqu'un peut m'eclairer ? Il y a peutetre une subtilité qui m'échape
    C'est l'utilisation de &res[0] qui est problématique car la norme ne garanti pas que les éléments d'une std::string sont contigus en mémoire (seul std::vector a cette garantie).

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Citation Envoyé par Sylvain Togni
    C'est l'utilisation de &res[0] qui est problématique car la norme ne garanti pas que les éléments d'une std::string sont contigus en mémoire (seul std::vector a cette garantie).
    Je ne vois pas comment ce serait possible d'implémenter un string sans cette garantie. La méthode c_str() renvoie un const char*, c'est obligatoirement une copie du char* utilisé en interne et pointe donc vers les mêmes charactères. Si ce n'était pas le cas il faudrait gérer le cycle de vie de ce nouveau buffer (et ça le standard ne serait pas d'accord).

  10. #10
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Je ne vois pas comment ce serait possible d'implémenter un string sans cette garantie. La méthode c_str() renvoie un const char*, c'est obligatoirement une copie du char* utilisé en interne et pointe donc vers les mêmes charactères. Si ce n'était pas le cas il faudrait gérer le cycle de vie de ce nouveau buffer (et ça le standard ne serait pas d'accord).
    Et pourtant si. Rien n'indique dans la norme que les caractères doivent être contigüs en mémoire, et c'est notamment pour cela que le pointeur renvoyé par c_str() n'est plus considéré comme valide après l'appel (la chaîne peut être un temporaire construit juste pour l'appel).
    En pratique ce n'est jamais le cas, mais dans le standard c'est comme ça.

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Mais comment les données pointées par un const char* pourraient-elles être détruites après l'appel? C'est impossible, par contre je comprends très bien qu'il ne faille plus utiliser ce pointeur après l'appel, pour la simple raison que le string pourrait être détruit entre temps.

  12. #12
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Sylvain Togni
    C'est l'utilisation de &res[0] qui est problématique car la norme ne garanti pas que les éléments d'une std::string sont contigus en mémoire (seul std::vector a cette garantie).
    Ca le sera en C0X. Je doute qu'il y ait beaucoup d'implementations ou ce n'est pas le cas.

  13. #13
    Membre habitué
    Inscrit en
    Mai 2007
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2007
    Messages : 157
    Points : 151
    Points
    151
    Par défaut
    La chaine de caractères n'est pas forcement détruite après l'appel, mais tout simplement aucun element (pointeur) ne permet d'acceder à la chaine.

    La mémoire sera reécrite ultèrieurement aux besoins de l'OS. En effet le système de gestion de la mémoire est mis à jour par l'OS pour indiquer que cette espace mémoire est à nouveau disponible.

  14. #14
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par zais_ethael
    Je ne vois pas comment ce serait possible d'implémenter un string sans cette garantie. La méthode c_str() renvoie un const char*, c'est obligatoirement une copie du char* utilisé en interne et pointe donc vers les mêmes charactères. Si ce n'était pas le cas il faudrait gérer le cycle de vie de ce nouveau buffer (et ça le standard ne serait pas d'accord).
    Le resultat de c_str() n'est pas necessairement ce qui est utilise en interne, il ne faut pas tenter de le modifier et tout appel a un membre non const (ou au destructeur) l'invalide.

  15. #15
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par zais_ethael
    Mais comment les données pointées par un const char* pourraient-elles être détruites après l'appel? C'est impossible, par contre je comprends très bien qu'il ne faille plus utiliser ce pointeur après l'appel, pour la simple raison que le string pourrait être détruit entre temps.
    On peut utiliser le resultat de c_str() jusqu'a un appel a un membre non const ou au destructeur.

  16. #16
    Membre expérimenté
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Points : 1 419
    Points
    1 419
    Par défaut
    et ICU ?

  17. #17
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Citation Envoyé par rikau2
    La chaine de caractères n'est pas forcement détruite après l'appel, mais tout simplement aucun element (pointeur) ne permet d'acceder à la chaine.

    La mémoire sera reécrite ultèrieurement aux besoins de l'OS. En effet le système de gestion de la mémoire est mis à jour par l'OS pour indiquer que cette espace mémoire est à nouveau disponible.
    Ca c'est ce qu'on appelle un garbage collector. Comme on est en C++, ça n'existe pas et le terme approprié est plutot fuite mémoire.

  18. #18
    Membre habitué
    Inscrit en
    Mai 2007
    Messages
    157
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2007
    Messages : 157
    Points : 151
    Points
    151
    Par défaut
    Citation Envoyé par zais_ethael
    Ca c'est ce qu'on appelle un garbage collector. Comme on est en C++, ça n'existe pas et le terme approprié est plutot fuite mémoire.
    je parlais de l'appel simple a:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    string str;
    mafonction(str.c_str());
    Merci de m'expliquer dans ce cas comment libérer la mémoire,...... j'aimerai bien savoir

  19. #19
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    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 382
    Points : 41 589
    Points
    41 589
    Par défaut
    Il n'y a rien à libérer ici, car l'objet string est sur la pile et son destructeur sera automatiquement appelé.
    Pour la fonction c_str(), la plupart des implémentations retournent directement le pointeur de la string, mais si une implémentation retourne un objet temporaire, lui aussi sera détruit automatiquement.

  20. #20
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Citation Envoyé par rikau2
    je parlais de l'appel simple a:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    string str;
    mafonction(str.c_str());
    Merci de m'expliquer dans ce cas comment libérer la mémoire,...... j'aimerai bien savoir
    Mais c'est exactement ce que je dis, c'est impossible! La seule solution est qu'on aie pas besoin de libérer la mémoire et que, de fait, le const char* qui soit retourné ne puisse en aucun cas être un objet temporaire.
    Citation Envoyé par Médinoc
    Pour la fonction c_str(), la plupart des implémentations retournent directement le pointeur de la string, mais si une implémentation retourne un objet temporaire, lui aussi sera détruit automatiquement.
    Mais puisque je dis que c'est impossible, vous avez déja vu un const char* avec un destructeur vous?

Discussions similaires

  1. Réponses: 13
    Dernier message: 16/09/2014, 13h59
  2. conversion UNICODE -> ASCII
    Par juniorAl dans le forum C#
    Réponses: 5
    Dernier message: 20/05/2010, 00h09
  3. Conversion de ASCII vers Unicode
    Par Arnaud F. dans le forum Langage SQL
    Réponses: 5
    Dernier message: 15/10/2008, 16h48
  4. Conversion Texte ASCII -> Unicode
    Par lesouriciergris dans le forum C++
    Réponses: 6
    Dernier message: 26/04/2006, 21h43
  5. conversion Unicode -> ASCII
    Par juzam dans le forum C
    Réponses: 8
    Dernier message: 24/07/2003, 11h07

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