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 :

Comportement différent GCC windows/linux : strlen ou getline?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut Comportement différent GCC windows/linux : strlen ou getline?
    Bonjour,

    Nous observons un comportement différent au niveau d'un programme écrit en C/C++ entre une compilation GCC sous windows (mingw / codeblock) et GCC linux (codeblock).

    En fait, pour lire dans un fichier une ligne,

    - nous ouvrons un flux sur le fichier à l'aide de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::ifstream               fin; //déclaration
    fin.open(filename);              //ouverture du flux
    - nous déclarons un buffer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char buf[MAX_LINE_LENGTH];
    - Nous lisons chaque ligne du fichier à l'aide de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fin.getline(buf,MAX_LINE_LENGTH); //lecture
    - Pour pouvoir travailler avec les fonctions de la bibliothèque C++ <string>, nous convertissons ce buffer en std::string :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::string str;
    str = buf;
    - Ensuite, pour savoir si on est face à une ligne vide, nous utilisons :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if( strlen(str) == 0 ){
    //...
    }
    C 'est ici que tout se gâte! D'une part, sous linux, la fonction strlen n'est pas incluse dans string. Il faut donc rajouter cstring.

    Une fois rajoutée, le résultat est complètement différent de sous windows. Il semble qu'il y ait deux solutions possibles :
    - Soit "getline" supprime seule sous windows \r\n ou \n (std::endl d'un autre programme C++)
    - Soit "strlen" ne prend pas en compte les \r\n ou \n

    Quelle est selon vous la cause? Comment corriger ceci "proprement" ?

  2. #2
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,

    Généralement, il vaut mieux éviter les mic-mac C/C++.
    La librairie standard C est conçu pour marcher uniquement avec du C.
    La librairie standard C++ est conçu pour bien marcher avec du C++, tout en s'efforçant de garder la compatibilité avec le C, ce qui n'est pas toujours sans heurt.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::ifstream               fin; //déclaration
    fin.open(filename);              //ouverture du flux
    char buf[MAX_LINE_LENGTH];
    fin.getline(buf,MAX_LINE_LENGTH); //lecture
    std::string str;
    str = buf;
    Lire un fichier avec des flux C++ pour remplir des tableaux de char C, puis reconvertir ces tableaux en string C++, c'est tout à fait possible, mais un peu tortueux

    Le code de la faq passe directement d'un flux C++ à des string C++.
    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
     
    #include <string>
    #include <fstream>
    #include <iostream>
     
    int main()
    {
        // le constructeur de ifstream permet d'ouvrir un fichier en lecture
        std::ifstream fichier( "fichier.txt" );
     
        if ( fichier ) // ce test échoue si le fichier n'est pas ouvert
        {
            std::string ligne; // variable contenant chaque ligne lue
     
            // cette boucle s'arrête dès qu'une erreur de lecture survient
            while ( std::getline( fichier, ligne ) )
            {
                // afficher la ligne à l'écran
                std::cout << ligne << std::endl;
            }
        }
    }
    Plus étonnant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::string str;
    ...
    if( strlen(str) == 0 )
    {
    //...
    }
    Je ne connais pas bien GCC, mais ça me semble hautement suspicieux que strlen, fonction de la librairie standard C, puisse accepter sans sourciller une std::string, classe de la librairie standard C++ !! .
    D'ailleurs avec Visual C++, ça ne compile pas.
    Citation Envoyé par bretus
    Comment corriger ceci "proprement" ?
    Pour obtenir la taille d'une std::string, il faut utiliser sa fonction membre size().

  3. #3
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Bonsoir,

    Humph, c'est vrai que j'ai fait l'âne et j'ai pas assez fouiné assez longtemps dans les docs et que j'ai pas trop réfléchi... J'ai vu un exemple sur cppreference.com que je trouve assez pratique pour rechercher les prototypes de fonctions (dans C++ IO pourtant ) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     ifstream fin("tmp.dat");
     
        int MAX_LENGTH = 100;
        char line[MAX_LENGTH];
     
        while( fin.getline(line, MAX_LENGTH) ) {
          cout << "read line: " << line << endl;
        }
    Je me suis dit pourtant que c'était idiot de pas pouvoir envoyer direct dans une std::string... J'avais oublié cette fonction : std::getline que je cherchais en temps que membre de la classe "input file stream"... A priori, std::getline me supprimera proprement mes caractères de fin de ligne...

    Pour le strlen, c'est sur que ça mérite une torche... Elle semble être définie dans <cstring> pour ce compilo... C'est moche, mais elle ne devait pas poser problème logiquement, elle doit renvoyer le size() de la std::string en paramètre...

    Bref, merci beaucoup pour ces précisions et les corrections qui en découleront. J'essayerai d'être plus frileux sur les mixtures en C++/C quand j'ai le choix à l'avenir...

    Bonne soirée

    ps : J'avoue quand même que des fonctions d'une même lib d'un "même" compilo ne fasse pas la même chose, ça me choque...

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pourquoi ne pas utiliser directement une string?

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     ifstream fin("tmp.dat");
     
        string line;
     
        while( getline(fin, line) ) {
          cout << "read line: " << line << endl;
        }
    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.

  5. #5
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Bonjour, merci pour ta réponse.

    Citation Envoyé par Médinoc Voir le message
    Pourquoi ne pas utiliser directement une string?
    C'est ce que m'a fait remarquer Arzar

    Faudra que je me trouve la doc "officielle" de la STL avec le descriptif des éléments qu'elle contient, ça m'évitera de faire n'importe quoi...

    Bonne journée

  6. #6
    Membre Expert
    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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 26/09/2014, 13h08
  2. Comportement différent entre Windows et Linux
    Par Maisondouf dans le forum Interfaces Graphiques en Java
    Réponses: 2
    Dernier message: 05/09/2012, 10h10
  3. Réponses: 5
    Dernier message: 14/11/2010, 22h53
  4. GCC windows linux cross compiler
    Par sybe30 dans le forum Autres éditeurs
    Réponses: 7
    Dernier message: 22/01/2010, 17h48

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