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 :

Problème avec mon getLine() ?


Sujet :

C++

  1. #1
    Membre régulier

    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 118
    Points : 81
    Points
    81
    Par défaut Problème avec mon getLine() ?
    Bonjour,

    Je souhaiterai saisir des vers, puis afficher ma strophe, comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
        Strophe S1;
        cin >> S1;
        cout << S1 << endl;
    }
    Voici une partie de mon (micro)projet.
    (j'ai supprimé les #include)

    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
    class Vers {
     
        private:
            string suiteMots;
            string rime;
     
        public:
            Vers();
            Vers(string s);
            Vers(string s, string r);
            virtual ~Vers();
            virtual string getSuiteMots() const;
            virtual void saisie(istream& is);
            void affiche(ostream& os) const;
    };
     
    ostream& operator<<(ostream& os, const Vers& v);
    istream& operator>>(istream& is, Vers& v);
    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
    Vers::Vers(){}
    Vers::Vers(string sm){ suiteMots=sm;}
    Vers::Vers(string sm, string r) { suiteMots=sm; rime= r;}
    Vers::~Vers(){}
     
    void Vers::saisie(istream& is) { 
        cout << "Entrez le vers." << endl; 
        getline(is,suiteMots); 
    }
     
    void Vers::affiche(ostream& os) const { os << "<<" << suiteMots << ">>";}
     
    ostream& operator<<(ostream& os, const Vers& v) {
        v.affiche(os);
        return os;
    }
     
    istream& operator>>(istream& is, Vers& v) {
        v.saisie(is);
        return is;
    }

    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
    class Strophe {
     
        private:
            Vers** suiteVers;
            int nbVers;
     
        public:
            Strophe();
            virtual ~Strophe();
            virtual void saisie(istream& is);
            virtual void affiche(ostream& os) const;
    };
     
    ostream& operator<<(ostream& os, const Strophe& s);
    istream& operator>>(istream& is, Strophe& s);
    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
    Strophe::Strophe(){suiteVers=NULL; nbVers=0;}
    Strophe::~Strophe(){if (suiteVers) delete[] suiteVers;}
     
    void Strophe::saisie(istream& is) {
        if (suiteVers) delete[] suiteVers;
        cout << "Entrer le nombre de vers : " << endl;
        is >> nbVers;
        suiteVers = new Vers*[nbVers];
        for (int i=0; i<nbVers; i++) {
            Vers *v = new Vers();
            v->saisie(is);
            suiteVers[i] = v;
        }
    }
     
    void Strophe::affiche(ostream& os) const {
        for (int i=0; i<nbVers; i++) {
            suiteVers[i]->affiche(os); os << endl;
        }
    }
     
    ostream& operator<<(ostream& os, const Strophe& s) {
        s.affiche(os);
        return os;
    }
     
    istream& operator>>(istream& is, Strophe& s) {
        s.saisie(is);
        return is;
    }
    Au début lorsque je saisissai un vers, seul le premier mot était stocké.
    Après une petite recherche, j'ai compris fallait utiliser getline().

    Sauf que maintenant j'ai un autre problème, lorsque je dis a mon programme que je veux saisir x vers. Il va laisser le 1er vide et me demander de saisir les x-1 autres...

    Concrètement,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Entrer le nombre de vers
    3                         // saisie au clavier
    Entrer le vers.
    Entrer le vers.
    Vers 1                  // saisie au clavier
    Entrer le vers.
    Vers 2.                // saisie au clavier
    // affichage de ma strophe
    <<>>
    <<Vers 1>>
    <<Vers 2>>
    Je pense que le problème vient de mon "getline(is,suiteMots)" parce que si je le replace par "is >> suiteMots" je n'ai plus de ce problème.

    Quelqu'un peut m'éclairer?

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    >> et getline ont parfois du mal à travailler ensemble :

    Ton cin >> i ne va pas vider du tampon le caractère de saut de ligne. getline va donc lire le reste de la ligne : rien.

    Utilise std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); Pour vider le tampon avant le premier getline.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre régulier

    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 118
    Points : 81
    Points
    81
    Par défaut
    Op.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Strophe::saisie(istream& is) {
        if (suiteVers) delete[] suiteVers;
        cout << "Entrer le nombre de vers : " << endl;
        is >> nbVers;
        suiteVers = new Vers*[nbVers];
        cin.ignore(256,'\n');
        for (int i=0; i<nbVers; i++) {
            Vers *v = new Vers();
            v->saisie(is);
            suiteVers[i] = v;
        }
    }
    Ca marche! Je te remercie.

    Cependant, je vois pas de quel saut de ligne on parle, en fait.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par Jéjé34 Voir le message
    Cependant, je vois pas de quel saut de ligne on parle, en fait.
    Eh bien, typiquement, une entrée clavier est terminée par l'appui <enter>. Cet appui a pour double résultat de placer le caractère de retour chariot '\n' après le dernier caractère ajouté, et de signaler au flux qu'il est temps de se mettre à jour.

    C'est de ce '\n' que l'on parle

    Ceci dit, tu ne devrais pas utiliser une valeur arbitraire comme 256 pour cin.ignore. La raison est toute simple : tu ne sais jamais ce que l'utilisateur pourra effectivement avoir voulu encoder, ni si la taille que tu indiques vouloir ignorer sera suffisante (l'utilisateur peut toujours vouloir ignorer la valeur arbitraire +1 caractères ).

    C'est la raison pour laquelle il est préférable d'utiliser std::numeric_limits<size_t>::max(), qui nous assure que la valeur arbitraire utilisée sera celle de la plus grande valeur numérique pouvant représenter une taille possible
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre régulier

    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 118
    Points : 81
    Points
    81
    Par défaut
    Merci.

    J'ai introduit la saisie de rimes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Vers::saisie(istream& is) {
        cout << "Entrez le vers puis la rime." << endl;
        getline(is,suiteMots);
        is >> rime;
    }
    Et utilisé numeric_limits<size_t>::max() comme vous me l'avez conseillé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Strophe::saisie(istream& is) {
        if (suiteVers) delete[] suiteVers;
        cout << "Entrer le nombre de vers : " << endl;
        is >> nbVers;
        suiteVers = new Vers*[nbVers];
        for (int i=0; i<nbVers; i++) {
            Vers *v = new Vers();
            cin.ignore(numeric_limits<size_t>::max(),'\n');
            v->saisie(is);
            suiteVers[i] = v;
        }
    }
    Mais ca ne fonctionne pas.
    Pour un petit programme qui me demande de saisir une strophe puis l'affiche, ca me donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Entrer le nombre de vers
    2        // saisie
    Entrer le vers puis la rime
    Vers 11       // saisie du vers
    Entrer le vers puis la rime
    Vers 12       // saisie du vers
    // affichage
    <<>>
    << 11>>
    Bref, il me laisse pas saisir mes rimes et m'affiche n'importe quoi. Alors que si je mets 256 qui est certes arbitraire et pas très logique mon programme fonctionne correctement:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Entrer le nombre de vers
    2        // saisie
    Entrer le vers puis la rime
    Vers 11       // saisie du vers
    11              // saisie de la rime
    Entrer le vers puis la rime
    Vers 12       // saisie du vers
    12             // saisie de la rime
    // affichage
    <<Vers 11>>
    <<Vers 12>>

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Il ne faut pas mettre le ignore dans ta boucle. Si tu mets ignore entre 2 getline, ça ne marchera pas.... Il est juste utile entre un << et un getline.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre régulier

    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 118
    Points : 81
    Points
    81
    Par défaut
    J'ai testé de le mettre ici.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Vers::saisie(istream& is) {
        cout << "Entrez le vers puis la rime." << endl;
        cin.ignore(256,'\n');
        getline(is,suiteMots);
        is >> rime;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void Strophe::saisie(istream& is) {
        if (suiteVers) delete[] suiteVers;
        cout << "Entrer le nombre de vers : " << endl;
        is >> nbVers;
        suiteVers = new Vers*[nbVers];
        for (int i=0; i<nbVers; i++) {
            Vers *v = new Vers();
            v->saisie(is);
            suiteVers[i] = v;
        }
    }
    Ca ne fonctionne toujours pas.

    Dès que j'appuie sur Entrée après avoir saisie un vers, il passe directement au vers suivant sans me demander de saisir le rime.
    Et lorsque j'affiche ma Strophe, elle est vide, aucun vers que j'ai saisie n'apparait.

    Alors que si je met 256, ça fonctionne...
    Ca doit donc venir du numeric_limits<size_t>::max(), mais pourquoi...

Discussions similaires

  1. Réponses: 3
    Dernier message: 21/06/2006, 19h48
  2. [Mail] Problème avec mon script d'envoi de mail
    Par leroivert dans le forum Langage
    Réponses: 18
    Dernier message: 02/12/2005, 00h26
  3. Problème avec mon service mysql et PhpMyAdmin
    Par Fixazo dans le forum Outils
    Réponses: 1
    Dernier message: 28/08/2005, 18h02
  4. problème avec mon lecteur CD
    Par leo13 dans le forum Périphériques
    Réponses: 3
    Dernier message: 16/08/2005, 11h21
  5. Problème avec mon firewall ...
    Par Wis dans le forum Tomcat et TomEE
    Réponses: 15
    Dernier message: 06/04/2004, 08h46

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