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

SL & STL C++ Discussion :

Convertir une std::string de utf8 vers cp850


Sujet :

SL & STL C++

  1. #1
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut Convertir une std::string de utf8 vers cp850
    Bonjour,

    Avec Linux dans un programme je dois faire en sorte que mes std::string saisies en mode utf8 soient converties en cp850 afin d'être logées dans de vieux fichiers dBase.

    Malheureusement je ne sais pas comment faire la conversion. Il me faudrait au moins une fonction pour y arriver, mais je ne vois pas bien, car le système de codage en utf8 peut aller jusqu'à 4 octets pour coder un caractère.

    Si quelqu'un a une idée ?

  2. #2
    Membre confirmé Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Points : 496
    Points
    496
    ________________________________________________
    http://bliquid.fr : Blog sur Android et l'Acer Liquid

  3. #3
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Bonjour,

    Désolé vous n'avez pas bien compris. iconv ( que je connais ) fait des traductions globales sur des fichiers textes, pas dBf.

    Mon problème est de convertir une chaine de caractères codée en utf8 vers cp850. Je dispose de la méthode qui convertit du cp850 en utf8 mais je me retrouve incapable de faire l'inverse.

    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
     
    void write850_UTF8(std::ostringstream& dst, unsigned char c)
    {
       static int const table[128] = {  0x00c7, 0x00fc, 0x00e9, 0x00e2,
       0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee,
       0x00ec, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2,
       0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7,
       0x0192, 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
       0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, 0x2591,
       0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0, 0x00a9, 0x2563,
       0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510, 0x2514, 0x2534, 0x252c,
       0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3, 0x255a, 0x2554, 0x2569, 0x2566,
       0x2560, 0x2550, 0x256c, 0x00a4, 0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8,
       0x0131, 0x00cd, 0x00ce, 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6,
       0x00cc, 0x2580, 0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5,
       0x00fe, 0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4,
       0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, 0x00b0,
       0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0  };
     
     
      if ( c < 128)
      {
         dst.put(c); // ascii
      }
      else
       {
         int unicode = table [c - 128];
         if (unicode <= 0x07FF)
         { dst.put(0xC0 | (unicode >> 6));
           dst.put(0x80 | (unicode & 0x3F));
         }
         else // unicode <= 0xFFFF
         {  dst.put(0xE0 | (unicode >> 12));
            dst.put(0x80 | ((unicode >> 6) & 0x3F));
            dst.put(0x80 | (unicode & 0x3F));
         }
      }
    }
     
    std::string convert850_UTF8( std::string& z )
    {
      std::ostringstream os ;
      for( size_t i = 0 ; i < z.length() ; i++ )
      {
         write850_UTF8( os, z[i] );
      }
      z = os.str() ;
      return z ;
    }
    Je ne vois pas bien comment faire l'inverse ?

  4. #4
    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 dj.motte Voir le message
    Désolé vous n'avez pas bien compris. iconv (que je connais) fait des traductions globales sur des fichiers textes, pas dBf.
    iconv est aussi une bibliotheque permettant de faire ce que tu veux.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #5
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Bonjour,

    Ben non je ne connaissais pas bien iconv. J'ai consulté le iconv.h mais je ne vois comment me servir des fonctions.
    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
     
    __BEGIN_DECLS
     
    /* Identifier for conversion method from one codeset to another.  */
    typedef void *iconv_t;
     
     
    /* Allocate descriptor for code conversion from codeset FROMCODE to
       codeset TOCODE.
     
       This function is a possible cancellation points and therefore not
       marked with __THROW.  */
    extern iconv_t iconv_open (__const char *__tocode, __const char *__fromcode);
     
    /* Convert at most *INBYTESLEFT bytes from *INBUF according to the
       code conversion algorithm specified by CD and place up to
       *OUTBYTESLEFT bytes in buffer at *OUTBUF.  */
    extern size_t iconv (iconv_t __cd, char **__restrict __inbuf,
    		     size_t *__restrict __inbytesleft,
    		     char **__restrict __outbuf,
    		     size_t *__restrict __outbytesleft);
     
    /* Free resources allocated for descriptor CD for code conversion.
     
       This function is a possible cancellation points and therefore not
       marked with __THROW.  */
    extern int iconv_close (iconv_t __cd);
     
    __END_DECLS
    Il faut faire d'abord un icon_open ensuite je ne comprends rien à la fonction iconv elle même. iconv_t __cd je ne vois pas ce que cela pourrait être.

  6. #6
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Bonjour,

    Je n'y comprends rien. J'ai essayé :
    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
     
     
    void do_conv()
    {
      char  zz[] = "éh éh ùù à paris" ;
      char  * z = zz];
     
      size_t zlen  = strlen(z) ;
      size_t slen  = zlen +10 ;
      char  ss[slen] ;
     
      //system( "piconv -f UTF-8 -t CP850 -s 'éh éh ùù à paris' > z.txt " ); ok
     
      memset( ss, 0, sizeof( ss ));
      char * s =  ss  ;
     
     
      cout << "A) " << endl << z << endl ;
      cout << "zlen= " << zlen << " slen= " << slen << endl ; 
     
     
      iconv_t cd = iconv_open ( "CP850", "UTF-8");
     
      size_t r = iconv ( cd, &z , &zlen , &s, &slen);
     
      cout << "B) " << endl << s <<  endl << "slen= " << slen << endl ;
      cout <<  z <<  endl << "zlen= " << zlen <<  endl ; 
     
     
      cout << endl ;
      cout << "r= " << r << " cd= " << cd << endl;
     
      cout << "len z (in)= " << strlen( z ) << endl << "len s (out)= " << strlen(s) << endl;
     
      iconv_close ( cd );
    }
    Les résultats sont aléatoires. De l'aide SVP ...

  7. #7
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Bonjour,

    Finalement j'ai trouvé une solution qui semble résoudre le problème :
    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
    61
    62
    63
    64
    65
    66
    67
     
    #include <iostream>
    #include <string>
    #include <cstdlib>
    #include <cassert>
    #include <iconv.h>
     
    using namespace std ;
     
    string  str_conv_from_to( const string& z , const char * from, const char * dest )
    {
      char inbuf[ 4096 ] ;
      char outbuf[ 4096 * 2 ] ;
      assert( z.length() < sizeof( inbuf ) ) ;
     
      strcpy( inbuf, z.c_str() ) ;
      size_t inlen = strlen( inbuf ) ;
      size_t outlen = inlen * 2 ;
     
      memset( outbuf, 0, sizeof( outbuf) ) ;
     
      char * s = inbuf ;
      char * d = outbuf ;
      char * str = d ;  // important pour récupérer la sortie 
     
      iconv_t cd = iconv_open ( dest, from );
     
      if (cd == (iconv_t) -1)
      {
           perror ("iconv_open");
           return z ;
      }
     
      size_t res = iconv ( cd, &s , &inlen , &d, &outlen);
     
      if (res == (size_t) -1)
      {
          perror ("iconv");
          return z ;
      }
     
      string value( str ) ;
      iconv_close ( cd );
     
      return value ;
     
    }
     
    int main()
    {
      string z( "&&& èéèé ùùù aaa â è éh éh ùù à paris" ) ;
     
      cout << "avant=" << endl << z << endl ;
      string r =  str_conv_from_to( z, "UTF-8", "CP850" ) ;
      cout << "après= " << endl << r << endl ;
      cout << "avant=" << endl << z << endl ;
     
      cout << "z.len= " << z.length() << endl ;
      cout << "r.len= " << r.length() << endl ;
     
      cout << "========vérification===========" << endl;
     
      string r1 =  str_conv_from_to( r, "CP850", "UTF-8" ) ;
      cout << "en utf8= " << endl << r1 << endl ;
      cout << "r1.len= " << r1.length() << endl ;
      return 0;
    }
    Mais bon c'est juste pour une chaîne pas trop longue.

  8. #8
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Bonjour,

    Finalement avec regrets j'arrive à :
    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
     
    string  str_conv_from_to( const string& z , const char * from, const char * dest )
    {
      size_t inlen = z.length()+1 ;
     
      if( inlen <= 1 ) return z ;
     
      size_t outlen = inlen * 2 ;
      size_t res = (size_t) - 1 ;
     
      char * outbuf = new char [ outlen ] ;
      if( !outbuf ) return z  ;
     
      memset( outbuf, 0, sizeof( outbuf) ) ;
     
      char * s = ( char * ) z.c_str() ;
      char * d = outbuf ;
      char * str = d ;
     
      iconv_t cd = iconv_open ( dest, from );
     
      if (cd != (iconv_t) -1)
      {
         res = iconv ( cd, &s , &inlen , &d, &outlen);
         if (res != (size_t) -1)
         {
            string val( str ) ;
            delete [] outbuf ;
            iconv_close ( cd );
            return val ;
         }
         else
         {
            perror ("iconv");
     
         }   
      }
      else 
      {
         perror ("iconv_open");
     
      }
     
      delete [] outbuf ;
      return z ;
     
    }
    Mais je ne vois pas comment faire du C++ avec cet utilitaire qui est en C.

    L'horreur c'est que l'utilitaire "iconv" n'est même pas livré avec Mingw de Windows.

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/04/2007, 12h39
  2. [FAQ]Comment convertir une std::string en AnsiString ?
    Par Invité dans le forum C++Builder
    Réponses: 2
    Dernier message: 26/11/2006, 18h08
  3. Comment convertir une variable string en double?
    Par quentinoux dans le forum C++
    Réponses: 12
    Dernier message: 31/07/2006, 10h46
  4. Convertir un std::string en double.
    Par vdumont dans le forum SL & STL
    Réponses: 16
    Dernier message: 10/05/2006, 16h46
  5. Réponses: 6
    Dernier message: 14/02/2004, 14h01

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