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 :

Récupérer des accents dans un fichier par getline


Sujet :

C++

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut Récupérer des accents dans un fichier par getline
    Bonjour, je fais mes débuts en C++ et j'ai des difficultés à récupérer un texte accentué depuis un fichier.

    Voici le code que je tente de faire fonctionner:
    void IO::lecture(vector <string> & dest)
    {
    string buffer;
    ifstream file(fichier, ios::in); //fichier est défini ailleurs dans le code
    do
    {
    getline(file, buffer);
    dest.push_back(buffer);
    }while(file);
    file.close();
    }
    Ça fonctionne bien pour un texte normale, mais dès qu'il y a un accent, il est remplacé par un code dans buffer.
    J'ai tenté de passer buffer en wstring mais le compilateur me rejette avec ce message sur mon getline:
    erreur: invalid conversion from ‘void*’ to ‘char**’
    erreur: cannot convert ‘std::wstring’ to ‘size_t*’ for argument ‘2’ to ‘__ssize_t getline(char**, size_t*, FILE*)’
    D'ailleurs je sais pas si c'est bien ça qui réglerait le soucis.

    J'ai également tenté de forcer l'internationalisation par
    locale loc("fr_FR");
    Mais j'ai l'impression que mon code a déjà la bonne localisation, même sans ça, si j'en juge par d'autre partie du programme.


    Qu'est-ce qui m'échappe?

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Au temps pour moi. J'ai bien un problème avec les accents quelque part dans mon programme, et le fait que mon IDE n'affichait pas correctement la valeur de ma variable buffer, j'ai cru que la source de mon problème était mon getline, mais visiblement il fonctionne correctement.

    Je vais continuer à chercher d'où vient le soucis.
    (en fait bien plus loin dans le code, j'ai un isprint qui ne reconnait pas "é" comme un caractère imprimable)

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Ok, voilà d'où vient réellement mon problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    cout << data << endl;	//pour debug
    for(int i=pos; i<data.size(); i++)	
    {	
    	cout << data[i];	//pour debug
    	if( !isprint(data[i]) )
    		return 0;	
    }
    Le résultat donne:
    testé
    test(caractère bizarre)
    Donc c'est l'accès direct au caractère de data qui me cause problème.
    Data est de type string.

    Quelqu'un voit comment je devrais procéder?
    Merci.

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Pensez vous que passer data en wstring pourrait solutionner mon problème?
    C'est ce que j' essayé mais le compilateur m'a alors rapporté une énorme liste d'erreur.
    Et comme l'affichage de data en tant que string fonctionne correctement lorsqu'il est affiché en un bloc, je ne suis pas sûr que ça va changer quelques chose.
    Alors j'aimerais avoir votre avis avant de revoir l'intégralité de mon programme pour l'adapter en wstring.

    (au cas ou, mon compilateur est gcc)

  5. #5
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par wistiti1234 Voir le message
    Ok, voilà d'où vient réellement mon problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	if( !isprint(data[i]) )
    Tu ne peux pas appeler isquelquechose sur un char, il faut passer un entier ayant la valeur d'un unsigned char ou EOF. Une autre valeur provoque un comportement indéfini.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Citation Envoyé par corrector Voir le message
    Tu ne peux pas appeler isquelquechose sur un char, il faut passer un entier ayant la valeur d'un unsigned char ou EOF. Une autre valeur provoque un comportement indéfini.
    Excuse moi d'émettre un doute, mais j'ai trouvé cette fonction sur ce site qui semble avoir été écrit par un professeur en école d'ing.
    D'après son cours cette fonction accepte les char en argument.
    D'ailleurs "if( !isprint('a') )" et "if( !isprint('é') )" ont un comportement parfaitement cohérent chez moi.

    Et je ne suis pas sûr que le problème vient de là puisque "cout << data[i]" pose aussi problème (contrairement cout << data)

    J'aimerais une deuxième confirmation avant de modifier mon isprint.

  7. #7
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par wistiti1234 Voir le message
    Excuse moi d'émettre un doute, mais j'ai trouvé cette fonction sur ce site qui semble avoir été écrit par un professeur en école d'ing.
    D'après son cours cette fonction accepte les char en argument.
    Malheureusement beaucoup de personnes baragouinent du C ou du C++, en total amateurisme (dans le mauvais sens du mot - on n'est pas aux J.O.).

    Ce cours est très (très) mauvais, quelques citations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nom     type param      type retour
    acos    double          double
    Non, les fonctions mathématiques sont surchargées pour float, double et long double.
    Le type char représente l'ensemble de tous les caractères imprimables et non imprimables ordonnés selon le code ASCII (chaque caractère est représenté par un entier entre 0 et 127)

    De façon analogue, si C est une variable de type char,
    désigne le code ASCII du caractère C (entier compris entre 0 et 127).
    Ce n'est pas limité à l'ASCII (d'ailleurs ton exemple 'é' n'est pas de l'ASCII).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      cin >> carac;        /* saisie d'un caractere au clavier */
      if (carac == 'A')    /* si c'est un A, alors */
    Aucune validation : et si il y a une erreur de lecture?

    C'est une erreur de débutant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        /* conversion d'une majuscule en minuscule */
        carac = carac + 'a' - 'A';
    Précisément ce qu'il faut éviter de faire. (toupper c'est du poulet?)

    C'est très exactement le genre de code qu'écrivent les amateurs qui ne croient savoir programmer.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    long double        calcul financier avec 18 chiffres significatifs
    C'est une blague?

    Bon, j'arrête là, c'est suffisant (et je sature).

    Ce cours => poubelle, sans regrets.
    Citation Envoyé par wistiti1234 Voir le message
    D'ailleurs "if( !isprint('a') )" et "if( !isprint('é') )" ont un comportement parfaitement cohérent chez moi.
    Chez toi, char est signé ou non-signé? S'il est non-signé, cela rejoint ce que je dis.

    De toutes façons, ça ne prouve rien. Un code C++ complètement faux peut marcher pas accident, c'est courant. (Un bon cours de C++ devrait préciser ça.)
    Citation Envoyé par wistiti1234 Voir le message
    Et je ne suis pas sûr que le problème vient de là puisque "cout << data[i]" pose aussi problème (contrairement cout << data)

    J'aimerais une deuxième confirmation avant de modifier mon isprint.
    Peut-être pourrais-tu rechercher cette confirmation par toi-même?

    Peut-être devrais-tu regarder la documentation de la fonction isprint, ou un bon bouquin, ou la norme, ou un brouillon de norme?

    Dans les forums, c'est très possible de trouver deux personnes qui affirment la même contre-vérité, ça ne veut rien dire. Cherches plutôt des sources qui font autorité. Vois toi-même qui raconte quasiment systématiquement n'importe quoi.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Effectivement j'ai consulté le man de isprint et c'est bien ça. Je vais donc modifier mon code.

    Mais ça ne résout pas mon problème.


    Pour le cours, a vrai dire je ne l'avais pas lu, je suis tombé dessus par google en cherchant une fonction pour tester des caractères, et je suis directement tombé sur le paragraphe 2.3.4. Mais merci de me prévenir, avant ça c'était pas exclut que je le consulte pour d'autres choses.

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    En tout cas wstring ne change absolument rien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    wstring ch1 = L"lettre accentué";
    string ch2 = "lettre accentué";
    cout << ch2 << endl;
    wcout << ch1 << endl;
    cout << ch2[14] << endl;
    wcout << ch1[14] << endl;
    Resultat:
    lettre accentué
    lettre accentu�


  10. #10
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par wistiti1234 Voir le message
    En tout cas wstring ne change absolument rien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    wstring ch1 = L"lettre accentué";
    string ch2 = "lettre accentué";
    cout << ch2 << endl;
    wcout << ch1 << endl;
    cout << ch2[14] << endl;
    wcout << ch1[14] << endl;
    Resultat:
    Je trouve très surprenant que string et char diffèrent.

    Tu peux envoyer la sortie dans un fichier et faire un dump hexadécimal?

    (Au fait c'est quoi ton système/compilateur?)

  11. #11
    Invité
    Invité(e)
    Par défaut
    Le fichier texte que tu lis utilise quel jeu de caractères ? (ISO-8859-xx, CP850, CP1252, etc.) Quelle est la source (Unix, Windows, Dos ) ? C'est de l'unicode, de l'UCS, UTF ?

    Par exemple, le caractère "é" est codé par :
    0x82 en CP850 (DOS)
    0xE9 en CP1252 (Windows)
    0xE900 en UCS-2 Little Endian, 0x00E9 en UCS-2 Big Endian
    0xC3A9 en UTF-8 (n° unicode 0x00E9)

    Si tu ne sais pas ça, tu ne t'en sortiras pas avec les accents...

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Citation Envoyé par Kaji Voir le message
    Le fichier texte que tu lis utilise quel jeu de caractères ? (ISO-8859-xx, CP850, CP1252, etc.) Quelle est la source (Unix, Windows, Dos ) ? C'est de l'unicode, de l'UCS, UTF ?

    Par exemple, le caractère "é" est codé par :
    0x82 en CP850 (DOS)
    0xE9 en CP1252 (Windows)
    0xE900 en UCS-2 Little Endian, 0x00E9 en UCS-2 Big Endian
    0xC3A9 en UTF-8 (n° unicode 0x00E9)

    Si tu ne sais pas ça, tu ne t'en sortiras pas avec les accents...
    Système Linux en FR.UTF-8 avec compilateur GCC 4.2.2
    J'ai tenté de "jouer" avec locale loc() mais sans succès.

  13. #13
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par wistiti1234 Voir le message
    Système Linux en FR.UTF-8
    Bingo! Imprime la longueur de tes chaines.

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par wistiti1234 Voir le message
    Système Linux en FR.UTF-8 [...]
    Et le voilà ton problème...
    Pour simplifier, le code UTF-8 code les lettres a-z sur un octet et les lettres accentuées sur deux...

    Si tu veux récupérer tous les caractères de ta chaîne en unicode, il va falloir la décoder.

    Il me semble que l'UTF-8 fonctionne comme ça :
    Si tu lis un octet dont les 3 premiers bits de poids fort sont 1, ta lettre est composée de 3 octets.
    Si tu lis un octet dont les 2 premiers bits de poids fort sont 1, ta lettre est composée de 2 octets.
    Sinon ta lettre est composée de 1 octet.

    Il faut regarder la spécification UTF-8 pour prendre le "bon" nombre d'octets et leur enlever les bits dont tu n'as pas besoin (les premiers, suivant le nombre d'octets de la lettre).

  15. #15
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Citation Envoyé par corrector Voir le message
    Je trouve très surprenant que string et char diffèrent.

    Tu peux envoyer la sortie dans un fichier et faire un dump hexadécimal?

    (Au fait c'est quoi ton système/compilateur?)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ofstream file("test.txt", ios::out);
    string ch2 = "lettre accentué";
    file << ch2 << endl;
    file << ch2[14] << endl;
    file.close();
    Donne:
    0000000 656c 7474 6572 6120 6363 6e65 7574 a9c3
    0000010 c30a 000a
    0000013

  16. #16
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par Kaji Voir le message
    Si tu veux récupérer tous les caractères de ta chaîne en unicode, il va falloir la décoder.
    Ce n'est pas au programmeur de faire ça.

    Normalement, tu utilises wcin et wcout et c'est bon.

  17. #17
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Ok donc 'a' est codé sur 1 octet et 'é' sur 4.
    Donc concrètement je dois procéder comment maintenant?

  18. #18
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par wistiti1234 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ofstream file("test.txt", ios::out);
    string ch2 = "lettre accentué";
    file << ch2 << endl;
    file << ch2[14] << endl;
    file.close();
    Donne:
    Mouais :
    é => a9c3c3
    c'est pas de l'UTF-8, c'est sûr.

    ch2[14] => 0
    comme caractère isolé

    Tu appelles locale::global(locale&) avant?

  19. #19
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 112
    Points : 165
    Points
    165
    Par défaut
    Citation Envoyé par corrector Voir le message

    Tu appelles locale::global(locale&) avant?
    Non. Ça sert à quoi et ça s'utilise comment?

    edit: Enfin comme dit plus j'avais tenté le "locale loc("fr_FR") mais je sais pas trop l'utiliser, ni si c'est de ça dont tu parle.

  20. #20
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par wistiti1234 Voir le message
    Non. Ça sert à quoi et ça s'utilise comment?
    Citation Envoyé par N2315, 22.1.1.5 locale static members [locale.statics]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static locale global(const locale& loc );
    Sets the global locale to its argument.
    Effects: Causes future calls to the constructor locale() to return a copy of the argument. If the argument has a
    name, does
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::setlocale(LC_ALL, loc.name().c_str());
    otherwise, the effect on the C locale, if any, is implementation-defined. No library function other than locale::global() shall affect the value returned by locale().
    Returns: The previous value of locale().
    Citation Envoyé par wistiti1234 Voir le message
    edit: Enfin comme dit plus j'avais tenté le "locale loc("fr_FR") mais je sais pas trop l'utiliser, ni si c'est de ça dont tu parle.
    Si tu créé un objet et que tu n'en fais strictement rien, ça n'a aucun influence, donc non, ce n'est pas ce dont je parle.

    Par contre il faudrait que tu indiques le programme complet que tu compiles, avec la ligne de commande exacte utilisée pour compiler.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Réponses: 10
    Dernier message: 23/04/2007, 14h18
  2. Réponses: 1
    Dernier message: 05/09/2006, 17h56
  3. récupérer des données dans un fichier
    Par pymouse dans le forum Langage
    Réponses: 7
    Dernier message: 19/06/2006, 17h43
  4. Réponses: 2
    Dernier message: 16/01/2006, 19h34
  5. Réponses: 1
    Dernier message: 22/12/2005, 15h45

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