2009-01-25 5 views
2

J'ai noté un échec sur mon programme qui m'empêche d'attribuer une valeur à la variable addAntonymAnswer1. J'ai essayé d'exécuter cin.clear() avant la déclaration pour obtenir la chose lire ma réponse yes/no, mais le code ne répondra tout simplement pas.Pourquoi cette lecture est-elle bloquée?

Le bit de programme qui est défaillant est situé à l'intérieur void dictionaryMenu(vector <WordInfo> &wordInfoVector) et lit

  cin.clear(); 

     cout<<">"; 
     cin>>addAntonymAnswer1; 

     // cin reading STUCK, why!? 

pour arriver à ce point du programme, l'utilisateur doit choisir d'ajouter un mot, puis ajouter un synonyme.

L'entrée pour l'exécution du programme est:

dictionary.txt 
1 cute 
2 hello 
3 ugly 
4 easy 
5 difficult 
6 tired 
7 beautiful 
synonyms 
1 7 
7 1 
3 2 
antonyms 
1 3 
3 1 7 
4 5 
5 4 
7 3 

#include <iostream> 
#include <fstream> 
#include <string> 

#include <sstream> 
#include <vector> 


using namespace std; 



class WordInfo{ 

     public: 

      WordInfo(){} 

      WordInfo(string newWord){ 
          word=newWord;     
      } 

      ~WordInfo() { } 

      int id() const {return myId;} 

      void readWords(istream &in) 
      { 
       in>>myId>>word;  
      } 

      vector <int> & getSynonyms() { 

        return mySynonyms; 
      } 

      vector <int> & getAntonyms() { 

        return myAntonyms; 
      } 

      string getWord() { 
        return word; 
        } 


      void dictionaryMenu (vector <WordInfo> &wordInfoVector){ 

      cout<<endl<<"Would you like to add a word?"<<endl; 
      cout<<"(yes/no)"<<endl; 
      cout<<">"; 
      string addWordAnswer; 
      cin>>addWordAnswer; 

      if (addWordAnswer=="yes") 
      // case if the guy wants to add a word 
      { 
      cout<<endl;     
      cout<<"Please, write the word "<<endl;     

      string newWord; 
      cout<<">"; 
      cin>>newWord; 
      cout<<endl;   

      WordInfo newWordInfo (newWord); 

      int newWordId = wordInfoVector.size() +1; 

      newWordInfo.myId=newWordId; 

      cout<<"The id of "<<newWordInfo.word<<" is "<<newWordInfo.myId<<endl<<endl; 

      wordInfoVector.push_back(newWordInfo); 


      cout<<"Would you like to define which words on the existing dictionary are" <<endl 
      <<"synonyms of "<<newWordInfo.word<<"?"<<endl; 


      cout<<"(yes/no)"<<endl; 

      string addSynonymAnswer, addAntonymAnswer1, addAntonymAnswer2; 
      cout<<">"; 
      cin>>addSynonymAnswer; 




      if (addSynonymAnswer=="yes") 
      { 

      cout<<endl; 
      cout<<"Please write on a single line the ids for the synonyms of " 
      <<newWordInfo.word<<endl<<"starting with its id, which is "<<newWordInfo.myId<<endl<<endl; 

      cout<<"For example, to define that the synonym of the word 'cute', which has an id 1, is" 
      <<"'beautiful', which has an id 7, you should write: 1 7"<<endl<<endl; 

      cout<<"In the case of "<<newWordInfo.word<<" you should start with "<<newWordInfo.myId<<endl; 

      cin.clear(); 
      string lineOfSyns; 
      cout<<">"; 

      cin>>lineOfSyns; 

      newWordInfo.pushSynonyms(lineOfSyns, wordInfoVector); 

      cin.clear();  


       cout<<"Would you like to define which words on the existing dictionary are" <<endl 
       <<"antonyms of "<<newWordInfo.word<<"?"<<endl; 

        //##HERE THE CIN READING OF addAntonymAnswer1 FAILS, WHY? 

       cin.clear(); 
       cout<<">"; 
       cin>>addAntonymAnswer1; 

       // cin reading STUCK, why!? 


       if (addAntonymAnswer1=="yes"){ }       

        else if (addAntonymAnswer1=="no"){ 
         // END DICTIONARY MENU 
         }     
      } 
      else if (addSynonymAnswer=="no"){ 

       cout<<"Would you like to define which words on the existing dictionary are" <<endl 
       <<"antonyms of "<<newWordInfo.word<<"?"<<endl; 


       cout<<">"; 
       cin>>addAntonymAnswer2; 

       if (addAntonymAnswer2=="yes"){ }       

        else if (addAntonymAnswer2=="no"){ 
         // END DICTIONARY MENU 
         } 

      } 


      } // if addWordAnswer == "no" 

      else if (addWordAnswer=="no"){ 

       // ######RETURN TO MAIN MENU############ 
       }   






      } 

      void pushSynonyms (string synline, vector<WordInfo> &wordInfoVector){ 


      stringstream synstream(synline); 

      vector<int> synsAux; 

      // synsAux tiene la línea de sinónimos 

      int num; 

      while (synstream >> num) {synsAux.push_back(num);} 

      int wordInfoVectorIndex; 

      int synsAuxCopyIndex; 



      if (synsAux.size()>=2){ // takes away the runtime Error 



      for (wordInfoVectorIndex=0; wordInfoVectorIndex <wordInfoVector.size(); wordInfoVectorIndex++) 
      { 


       if (synsAux[0]==wordInfoVector[wordInfoVectorIndex].id()){ 


        // this is the line that's generating a Runtime Error, Why?              
        for (synsAuxCopyIndex=1; synsAuxCopyIndex<synsAux.size(); synsAuxCopyIndex++){ 

        // won't run yet  
        wordInfoVector[wordInfoVectorIndex].mySynonyms.push_back(synsAux[synsAuxCopyIndex]);  
         }               
       }  
      } 

      }// end if size()>=2 


      } // end pushSynonyms 








      void pushAntonyms (string antline, vector <WordInfo> &wordInfoVector) 
      { 



      stringstream antstream(antline); 

      vector<int> antsAux; 

      int num; 

      while (antstream >> num) antsAux.push_back(num); 


      int wordInfoVectorIndex; 

      int antsAuxCopyIndex; 



      if (antsAux.size()>=2){ // takes away the runtime Error    

      for (wordInfoVectorIndex=0; wordInfoVectorIndex <wordInfoVector.size(); wordInfoVectorIndex++) 
      { 


       if (antsAux[0]==wordInfoVector[wordInfoVectorIndex].id()){ 


        // this is the line that's generating a Runtime Error, Why?              
        for (antsAuxCopyIndex=1; antsAuxCopyIndex<antsAux.size(); antsAuxCopyIndex++){ 

        // won't run yet  
        wordInfoVector[wordInfoVectorIndex].myAntonyms.push_back(antsAux[antsAuxCopyIndex]);  
         }               
       }  
      } 

      }// end if size()>=2 





      } 

      //--dictionary output function 

      void printWords (ostream &out) 
      { 
       out<<myId<< " "<<word;  
      } 



      //--equals operator for String 
      bool operator == (const string &aString)const 
      { 
          return word ==aString; 

      } 


      //--less than operator 

      bool operator <(const WordInfo &otherWordInfo) const 
      { return word<otherWordInfo.word;} 

      //--more than operator 

      bool operator > (const WordInfo &otherWordInfo)const 
      {return word>otherWordInfo.word;} 

      public: 

        vector<int> mySynonyms; 
        vector <int> myAntonyms; 


        string word; 
        int myId; 


     }; 

     //--Definition of input operator for WordInfo 
     istream & operator >>(istream &in, WordInfo &word) 
     { 
     word.readWords(in); 

     } 



     //--Definition of output operator 

     ostream & operator <<(ostream &out, WordInfo &word) 
     { 
      word.printWords(out); 

     } 





     int main() { 

      string wordFile; 
      cout<<"enter name of dictionary file: "<<endl; 
      getline (cin,wordFile); 

      ifstream inStream (wordFile.data()); 

      if(!inStream.is_open()) 
      { 
      cerr<<"cannot open "<<wordFile<<endl; 
      exit(1);      

      } 

      vector <WordInfo> wordInfoVector; 

      WordInfo aword; 





      while (inStream >>aword && (!(aword=="synonyms"))) 
      { 
       wordInfoVector.push_back(aword); 


      } 

      inStream.clear(); 









      vector <int> intVector; 
      string synLine; 






      while (getline(inStream, synLine)&&(synLine!=("antonyms"))){ 

       aword.pushSynonyms(synLine, wordInfoVector); 

       } 



      int theIndex; 



      string antLine; 

      while (getline(inStream,antLine)){ 

       aword.pushAntonyms(antLine, wordInfoVector); 
       }  



      cout<<endl<<"the words on the dictionary are: "<<endl; 

      int h=0;   
      while (h<wordInfoVector.size()){ 
       cout<<wordInfoVector[h]<<endl; 
       h++; 
       } 

      aword.dictionaryMenu(wordInfoVector); 

      system("PAUSE"); 

      return 0; 
     } 

Répondre

13

cin.clear() n'efface pas l'entrée standard. Ce qu'il fait est effacer les bits d'erreur, comme eofbit, failbit et d'autres, et définit le flux dans un bon état. Peut-être que vous vous attendiez à ce qu'il y ait quelque chose? Si l'utilisateur a tapé

yes no 

Juste avant, et vous

cin >> someStringVariable; 

Il lit jusqu'à no et le flux contiendra encore

no 

L'appel à clear puis efface toute erreur bits étant actifs. Ensuite, votre

cin>>addAntonymAnswer1; 

lirons le no qui n'a pas été mangé par la lecture précédente, et l'action retourne immédiatement, sans attendre une nouvelle entrée. Ce que vous devez faire est de faire un clear suivi d'un ignorer, jusqu'à la prochaine ligne de retour. Vous lui dites la quantité de caractères qu'il devrait ignorer au maximum. Ce montant devrait être le plus grand nombre possible.

cin.clear(); 
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

Faire qui fera le flux vide, et une lecture suivante vous attendra de taper quelque chose dans


Un autre problème se pose si vous avez a obtenu un cin >> suivi d'un getline: Le cin laissera tout espace (aussi les nouvelles lignes) après son jeton de lecture, mais getline s'arrêtera de lire après avoir frappé un tel retour à la ligne. Je vois que vous avez mis clear après presque tout. Donc, je veux vous montrer quand vous en avez besoin et quand ce n'est pas le cas. Vous n'en avez pas besoin lorsque vous séquencez plusieurs cin >>. Supposons que vous avez dans votre tampon: "foo \ nbar \ n". Ensuite, vous faites les lectures suivantes

cin >> a; // 1 
cin >> b; // 2 

Après le premier, votre tampon contiendra "\ nbar \ n". Autrement dit, le retour à la ligne est toujours en cours.La deuxième cin>> va d'abord passer tous les espaces et les sauts de ligne, de manière à pouvoir faire face à \n être à l'avant de bar. Maintenant, vous pouvez également plusieurs séquences getline appels:

getline(cin, a); 
getline(cin, b); 

GetLine jetteront l'\n qu'il lit à la fin de la ligne, mais ne l'ignorer ou des sauts de ligne des espaces au début. Ainsi, après le premier getline, le buffer contient "bar \ n". La seconde getline lira correctement "bar \ n". Maintenant, considérons le cas où vous avez besoin clair/Ignore:

cin >> a; 
getline(cin, b); 

Le premier quittera le flux comme « \ nbar \ n ». Le getline verra alors immédiatement le \n au début, et pensera qu'il a lu une ligne vide. Ainsi, il continuera immédiatement et n'attendra rien, laissant le flux comme "bar \ n". Donc, si vous avez un getline après un cin>> vous devez d'abord exécuter la séquence clear/ignore, pour effacer le retour à la ligne. Mais entre getline ou cin>>, vous ne devriez pas le faire.

1

Il est "coincé", car il est en attente d'entrée. Cin est attaché à la poignée d'entrée standard pour le programme, vous devez taper quelque chose et appuyez sur Entrée.

+0

je veux dire « coincé » dans le sens où il ne « quelque chose et frappé de type entrer » me laisse pas. La console présente immédiatement "Appuyez sur n'importe quelle touche pour continuer". – andandandand

+1

Je ne pense pas qu'il mérite une downvote. "rester coincé" signifie qu'il ne continue pas, ce que je pense qu'il a correctement interprété. Au lieu de cela, changez peut-être le libellé de votre question. –

+1

il suppose que l'affiche ne sait pas que "cin s attaché à la poignée d'entrée standard pour le programme, vous devez taper quelque chose et appuyez sur Entrée", que je trouve limite offensive, le gars n'a même pas lu mon code. – andandandand

1

cin >> ... lit l'entrée standard jusqu'à ce qu'il trouve un caractère d'espacement. Lorsque vous entriez, dites, 8 5 pour la liste des synonymes, 8 est lu dans lineOfSyns et rien de plus. Lorsque le programme atteint cin >> addAntonymAnswer1, 5 est lu dans addAntonymsAnswer1. Votre programme se comporte de façon inattendue car il attend yes ou no mais il a 5.

Regardez en utilisant cin.getline() au lieu de >>. Voir, par exemple, les sections 18.2 et 18.3 de this page.

+0

Merci, j'utilise getline maintenant en raison de votre suggestion. – andandandand

1

Dans votre programme, vous demandez à l'utilisateur:

Please write on a single line the ids for the synonyms of test 
starting with its id, which is 8 

For example, to define that the synonym of the word 'cute', which has an id 1, i 
s'beautiful', which has an id 7, you should write: 1 7 

In the case of test you should start with 8 

Ensuite, vous essayez de lire dans la ligne de l'utilisateur tapé avec

cin>>lineOfSyns; 

Cependant, cela ne lit au premier espace. Ainsi, le 2ème numéro tapé par l'utilisateur est toujours dans la mémoire tampon cin lorsque la ligne

cin>>addAntonymAnswer1; 

est exécuté, de sorte que les données est lu dans la chaîne addAntonymAnswer1. L'utilisateur n'a jamais la possibilité de taper «oui» ou «non» et vos tests pour ces valeurs échouent.

Vous devriez envisager de changer d'utiliser la surcharge string pour getline() faire votre lit:

getline(cin, stringvar); 

Ce serait probablement mieux que d'utiliser cin.getline(), car cela n'a pas une surcharge qui prend string - avec ce membre fonction, vous devez lire dans un tableau de caractères, ce qui est beaucoup moins flexible que de lire dans un string.

+0

Merci, c'était utile. – andandandand

+0

Vous devriez envisager de passer à l'utilisation de la surcharge 'string' pour getline() pour faire vos lectures: getline (cin, stringvar); –

+0

Bien sûr, je l'ai déjà fait. – andandandand

Questions connexes