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 :

getline cin comportements bizarres


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Points : 0
    Points
    0
    Par défaut getline cin comportements bizarres
    Bonjour à tous!
    J'utilise getline(cin,chaine) pour accepter d'office (ou pas!) la variable proposée ligne 22ou 27 ou 32.
    Si je supprime la ligne 19 le programme valide automatiquement la 22 et mais attend la validation normale à la ligne 27 puis celle de la ligne 32.
    Que se passe t-il?
    Je rappelle que ce forum a comme titre débuter...
    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
     
    string FhCmtr="CLCMTR"+departem+".rtf";//fichier dates des dmaj
    cout<<FhCmtr<<endl;
    int clcmtr=0;
    ifstream FhCmtrL(FhCmtr.c_str(),ios::in);
        std::vector<std::string>TblCmtr;
        string LignCmtr;
        while (getline(FhCmtrL,LignCmtr))
            {clcmtr++;
            TblCmtr.push_back(LignCmtr);
            cout<<clcmtr<<" "<<LignCmtr<<endl;}
            int szTblCmtr=0;
            szTblCmtr=TblCmtr.size();
            cout<<" "<<endl;//cin.get();
            string CmtrChxLe=CmtrListFhDeu.substr(0,1);
            string CmtrGrFam=CmtrListFhDeu.substr(1,2);
            string CmtrAnnee=CmtrListFhDeu.substr(3,4);
            cout<<"Clefs de recherches..:["<<CmtrChxLe<<"] et ["<<CmtrGrFam<<"] et ["<<CmtrAnnee<<"]"<<endl;
    cin.get();
            cout<<" "<<endl;
            cout<<"<E>=["<<CmtrChxLe<<"]    ou           l:";
            getline(cin,CmtrChxLe);
            if (CmtrChxLe == "" ) {CmtrChxLe = CmtrListFhDeu.substr(0,1);}
            if (CmtrChxLe == "l") {CmtrChxLe = CmtrListFhDeu.substr(0,1);}
     
            cout<<"<E>=["<<CmtrGrFam<<"]   ou ? ou b/lanc:";
            getline(cin,CmtrGrFam);
            if (CmtrGrFam == "b" ) {CmtrGrFam = "  ";}
            if (CmtrGrFam == ""  ) {CmtrGrFam = CmtrListFhDeu.substr(1,2);}
     
            cout<<"<E>=["<<CmtrAnnee<<"] ou ? ou b/lanc:";
            getline(cin,CmtrAnnee);
            if (CmtrAnnee == "b" ) {CmtrAnnee ="    ";}
            if (CmtrAnnee == ""  ) {CmtrAnnee = CmtrListFhDeu.substr(3,4);}
    Vidage de buffer?Le buffer se remplit où?Avant la ligne 1?

    A vous lire bientôt!
    Cordialement.
    Sen.

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    A quoi te sert cin.get() ?
    Ne faut-il pas plutôt utiliser cin.ignore ?


    Sinon, il y a en effet un buffer.
    Pour l'affichage, le buffer va se vider et afficher son contenu quand :
    - il est plein ;
    - on fait std::endl.

    Pour cin, il doit se remplir lorsqu'on fait un retour à la ligne.

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Points : 0
    Points
    0
    Par défaut
    merci;
    J'utilise partout cin.get() comme arrêt de déroulement de programmes.C'est pratique et permet de surveiller les déroulements.
    Ici je croyais qu'il servait uniquement à bloquer le déroulement pour lire la ligne 18.
    Quand je l'ai supprimé car ma ligne était au point j'ai eu le probléme qui m'a fait poster.Et je me suis apperçu que ce cin.get(); servait en réalité à bloquer la ligne 22 pour répondre à la question posée par le programme.
    Ce cin.get() ne servait pas à ce pourquoi je l'avait mis..............
    Ailleurs j'avais remarqué que cin.get() avait un effet buffer mais bof! il suffisait de le ré-écrire une fois comme on me l'avait conseillé sur ce forum.
    Quand j'ai pensé à cet effet buffer je me demandais qu'elle était la variable à vider d'ailleurs.
    Je vais donc essayer cin.ignore.
    Je reviens.
    J'ai essayé cin.ignore():pareil...!
    A+++.

    Ce que je veux réaliser c'est répondre par <Enter> ou entrer une autre variable à la ligne 5 puis idem à la ligne 10 sans que le programme passe directement à la ligne 10 par "effet buffer".
    (j'ai modifié un peu la ligne 6 car il y avait une erreur ici sans importance)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
            cout<<"Clefs de recherches proposées..:["<<CmtrChxLe<<"] et ["<<CmtrGrFam<<"] et ["<<CmtrAnnee<<"]"<<endl;
            cout<<" "<<endl;
            cout<<"<E>=["<<CmtrChxLe<<"]     ou? ou b/lanc:";
            getline(cin,CmtrChxLe);
            if (CmtrChxLe == "b" ) {CmtrChxLe = " ";}
            if (CmtrChxLe == "l" ) {CmtrChxLe = CmtrListFhDeu.substr(0,1);}
     
            cout<<"<E>=["<<CmtrGrFam<<"]    ou? ou b/lanc:";
            getline(cin,CmtrGrFam);
            if (CmtrGrFam == "b" ) {CmtrGrFam = "  ";}
            if (CmtrGrFam == ""  ) {CmtrGrFam = CmtrListFhDeu.substr(1,2);}
    cin.ignore() n'apporte rien de nouveau et semble avoir un "effet buffer".
    Merci pour ces réponses mais
    Cordialement.
    Sen.

  4. #4
    Membre averti
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Points : 307
    Points
    307
    Par défaut
    /mode pedantic

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ifstream FhCmtrL(FhCmtr.c_str(),ios::in);
    Ici, ios::in est mieux inutile (c'est un istream), au pire un bug, il faudrait utiliser ios_base::in

    Le code gagnerait en lisibilité avec de meilleurs noms de variables.
    Là, ça donne pas trop envie.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Points : 0
    Points
    0
    Par défaut
    merci.J'utiliserai ios_base dans ce cas.
    Mes noms de variables sont des noms standards qui facilitent la localisation des variables je trouve.La partie un/deu/troi donne la position dans la chaine d'écriture de la fonction et de l'appel de fonction parce que des noms ou des phrases ne sont pas toujours très différenciables:listedefichiers -à la française- ou fichiersliste - à l'anglaise- sont-ils la m^me chose ou différents?
    Un chien petit ou un petit chien?Voir Astérix ou Obélix qui se demandent comment parler l'anglais dans astérix chez les bretons!!!!L'anglais va du général au plus simple.Le français c'est l'inverse et même une expression A+B peu avoir un sens un peu différent de B+A(je n'ai pas d'exemple sous la main et ne suis pas linguiste)
    Pour en revenir à mes variables à la mise au point finale j'avais bien l'intention de les franciser.
    Et donc pour mon projet,je me cite:
    ------------------------------------
    Ce que je veux réaliser c'est répondre par <Enter> ou entrer une autre variable à la ligne 5 puis idem à la ligne 10 sans que le programme passe directement à la ligne 10 par "effet buffer".
    ------------------------------------
    quelle idée nouvelle apparaît?
    c'est quoi ceci:/mode pedantic en tête de message?
    Cordialement.
    Sen.

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Hylvenir Voir le message
    /mode pedantic

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ifstream FhCmtrL(FhCmtr.c_str(),ios::in);
    Ici, ios::in est mieux inutile (c'est un istream), au pire un bug, il faudrait utiliser ios_base::in
    Effectivement ios::in est redondant avec le type ifstream, mais ios::in ou ios_base::in sont identiques, ios dérive publiquement de ios_base; o/i stream dérivant eux-même publiquement de ios.
    Donc il n'y a aucunement lieu de s'alarmer quant à un (im)possible bug.

    cf http://www.cplusplus.com/reference/iostream/ios/
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Membre averti
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Points : 307
    Points
    307
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Effectivement ios::in est redondant avec le type ifstream, mais ios::in ou ios_base::in sont identiques, ios dérive publiquement de ios_base; o/i stream dérivant eux-même publiquement de ios.
    Donc il n'y a aucunement lieu de s'alarmer quant à un (im)possible bug.

    cf http://www.cplusplus.com/reference/iostream/ios/
    Sous HP-UX, en utilisant aCC, je crois me souvenir que ça faisait un core.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Et pour t'en assurer:

    http://www.cplusplus.com/reference/i...base/openmode/
    These constants are defined in the ios_base class as public members. Therefore, they can be refered to either directly by their name as ios_base members (like ios_base::in) or by using any of their inherited classes or instantiated objects, like for example ios::ate or cout.out.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre averti
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Points : 307
    Points
    307
    Par défaut
    Citation Envoyé par senvedgi Voir le message
    ------------------------------------
    Ce que je veux réaliser c'est répondre par <Enter> ou entrer une autre variable à la ligne 5 puis idem à la ligne 10 sans que le programme passe directement à la ligne 10 par "effet buffer".
    ------------------------------------
    quelle idée nouvelle apparaît?
    Pourrait-on avoir un exemple plus simple et complet qui montrerait le même problème ?
    J'en ai fait un simple qui fonctionne bien à priori. est-ce 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
     
    #include <iostream>
    #include <string>
    #include <fstream>
     
    using namespace std;
     
    int main()
    {
      ifstream file("getline2.cpp", ios::in);
      std::string line;
      while (getline(file, line))
      {
        cout << "Afficher ligne ? " << std::endl;
        std::string choice;
        getline(cin, choice);
        if (choice == "O") cout << line << endl;
      }
    }

    Citation Envoyé par senvedgi Voir le message
    c'est quoi ceci:/mode pedantic en tête de message?
    Ca veut dire, j'ai fait le chieur, sans apporter de réponse à ta question

  10. #10
    Membre averti
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Points : 307
    Points
    307
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Je n'ai plus accès à ce compilo/OS. Ca a sûrement évolué dans le bon sens depuis alors.
    J'ai pas réussi à trouver ça dans le standard (ils utilisent ios_base::in comme valeur d'"openmode" par défaut pour le basic_ifstream)

  11. #11
    Nouveau Candidat au Club
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Points : 0
    Points
    0
    Par défaut
    Très intêressants certes!
    Mais le pb à résoudre c'est la ligne 4.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    cout<<"Clefs de recherches proposées..:["<<CmtrChxLe<<"] et ["<<CmtrGrFam<<"] et ["<<CmtrAnnee<<"]"<<endl;
            cout<<" "<<endl;
    //ici
            cout<<"<E>=["<<CmtrChxLe<<"]     ou? ou b/lanc:";
            getline(cin,CmtrChxLe);
            if (CmtrChxLe == "b" ) {CmtrChxLe = " ";}
            if (CmtrChxLe == "l" ) {CmtrChxLe = CmtrListFhDeu.substr(0,1);}
     
            cout<<"<E>=["<<CmtrGrFam<<"]    ou? ou b/lanc:";
            getline(cin,CmtrGrFam);
            if (CmtrGrFam == "b" ) {CmtrGrFam = "  ";}
            if (CmtrGrFam == ""  ) {CmtrGrFam = CmtrListFhDeu.substr(1,2);}
    Si on pose ligne 4 un cin on a un arrêt qui lit la ligne 2
    puis des arrêts en 6 et 11 pour rentrer ce qu'on veut.Bien!
    Mais si on supprime le cin ligne 4 on passe l'arrêt ligne 2 non indispensable d'ailleurs
    ET ON PASSE directement à l'arrêt de la ligne 11.
    (Je rappelle que lig.6/11 getline(cin,xx) propose une solution vraisemblable mais modifiable)
    Cordialement.
    Sen.

  12. #12
    Membre averti
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Points : 307
    Points
    307
    Par défaut
    Est-ce que l'exemple que j'ai posté correspond au problème ?

    Comme ça, je ne vois pas d'erreur dans ton programme.

  13. #13
    Nouveau Candidat au Club
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Points : 0
    Points
    0
    Par défaut
    J'ai fini avec mes tous petits moyens par décortiquer et adapter à mon code ces lignes et cela semble résoudre ce que je cherche à faire.
    J'ai fait des découvertes d'écritures..
    Mais pour la bonne relecture de mes codes je n'en tient le plus possible à des écritures uniques:if(){}/cin.get()/cin.ignore() par exemples.
    Merci beaucoup.
    mais il faut continuer
    Cordialement.
    Sen.

  14. #14
    Nouveau Candidat au Club
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Points : 0
    Points
    0
    Par défaut
    je ressuscite le post: cin.ignore(); juste avant getline (..) résoud aussi mon problème!
    Cordialement.
    Sen.

  15. #15
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    On a une Q/A en attente qui traite ce sujet dans la FAQ.
    Citation Envoyé par Luc Hermitte Voir le message
    À reformatter, mettre en français, etc.

    Pourquoi std::getline ne lit rien, et qu'il faille l'exécuter deux fois pour que la ligne soit lue?
    Si vous constatez ce problème, il est fort probable que vous venez d'appeler "std::getline(std::cin)" juste après une lecture sur le flux avec l'opérateur d'extraction: "std::cin >>". (c'est parfaitement valable avec les flux fichiers également)

    Ce que vous observez est normal. L'opérateur d'extraction (>>) consomme ce qui vient sur le flux, mais il s’arrête juste avant le premier espace blanc (pas sûr du vocabulaire) ou saut de ligne -- voire encore avant selon le type de la donnée à extraire et de ce qui se trouve véritablement sur le flux (ex: l'extraction d'un int depuis "125douze").

    De fait, l'operator>> va s’arrêter avant le saut de ligne, et quand std::getline va vouloir extraire la ligne qui suit, en fait il va récupérer les caractères entre la position courante et la fin de la ligne avant de passer à la ligne suivante. Dans le cas d'une interaction avec l'utilisateur, une chaine vide sera obtenue, et le flux sera positionné à la ligne suivante. C'est pour cela qu'un double appel à std::getline fonctionne.

    " - Donc si je comprends bien il faut appeler deux fois std::getline()?"
    Seulement si vous voulez récupérer les miettes qui trainent après la dernière chose lue avec >>.
    En pratique on a le choix entre :
    - un simple std::cin.get() qui marchera uniquement si ce qui suit est un saut de ligne
    - ou purger le buffer clavier (cf entrée correspondante: http://cpp.developpez.com/faq/cpp/?p...e#SL_cin_clear) qui fonctionnera également si des miettes trainent et que l'on préfère les ignorer.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  16. #16
    Nouveau Candidat au Club
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Points : 0
    Points
    0
    Par défaut
    merci pour cette citation/confirmation:rien n'est simple en c++.
    Cordialement.
    Sen.

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

Discussions similaires

  1. Comportement bizarre de mes FPS
    Par Ekinoks dans le forum OpenGL
    Réponses: 7
    Dernier message: 22/08/2005, 15h14
  2. xsl:test .... avec comportement bizarre
    Par Blue LC dans le forum XMLRAD
    Réponses: 2
    Dernier message: 10/06/2005, 13h56
  3. [ACESS][MEMO][ISNULL]Comportement bizarre
    Par seb.49 dans le forum ASP
    Réponses: 2
    Dernier message: 09/06/2004, 10h44
  4. [HttpClient] comportement bizarre, saute des catch()...
    Par iubito dans le forum Développement Web en Java
    Réponses: 4
    Dernier message: 04/02/2004, 15h25
  5. [Sybase] Comportement bizarre d'une table
    Par sdozias dans le forum Sybase
    Réponses: 4
    Dernier message: 03/02/2004, 10h39

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