with sirve que para c++ cin

c++ - sirve - std::cin



¿Por qué esta lectura de cin se atasca? (4)

En su programa, le pregunta al usuario:

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

Luego intenta leer en la línea que el usuario tipeó con

cin>>lineOfSyns;

Sin embargo, esto solo se lee hasta el primer espacio en blanco. Entonces, el segundo número ingresado por el usuario todavía está en el búfer cin cuando el

cin>>addAntonymAnswer1;

línea se ejecuta, por lo que los datos se leen en la cadena addAntonymAnswer1 . El usuario nunca tiene la oportunidad de escribir ''sí'' o ''no'' y sus pruebas de esos valores fallan.

Debería considerar cambiar a usar la sobrecarga de string para que getline() haga sus lecturas:

getline( cin, stringvar);

Esto probablemente sería mejor que usar cin.getline() , ya que no tiene una sobrecarga que toma string : con esa función miembro, necesita leer en una matriz de caracteres, que es mucho menos flexible que leer en una string .

He señalado un error en mi programa que me impide asignar un valor a la variable addAntonymAnswer1 . Intenté ejecutar cin.clear() antes de la declaración para que la cosa lea mi yes/no , pero el código simplemente no responde.

El bit de programa que está fallando se encuentra dentro de void dictionaryMenu(vector <WordInfo> &wordInfoVector) y lee

cin.clear(); cout<<">"; cin>>addAntonymAnswer1; // cin reading STUCK, why!?

Para llegar a ese punto del programa, el usuario debe elegir agregar una palabra y luego agregar un sinónimo.

La entrada para ejecutar el programa es:

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; }


Está "atascado" porque está esperando la entrada. cin está conectado al identificador de entrada estándar para el programa, debe escribir algo y presionar enter.


cin >> ... lee desde la entrada estándar hasta que encuentra un carácter de espacio en blanco. Cuando ingresa, digamos, 8 5 para la lista de sinónimos, 8 se lee en lineOfSyns y nada más. Cuando el programa llega a cin >> addAntonymAnswer1 , 5 se lee en addAntonymsAnswer1 . Su programa se comporta de forma inesperada ya que espera que yes o no pero tiene 5 .

Mira el uso de cin.getline() lugar de >> . Ver, por ejemplo, las secciones 18.2 y 18.3 de esta página .


cin.clear() no borra la entrada estándar. Lo que hace es borrar bits de error, como eofbit , failbit y otros, y establece la secuencia en un buen estado. ¿Tal vez esperabas que despejara algo en él? Si el usuario tipeó

yes no

Justo antes, y tú

cin >> someStringVariable;

Se leerá en no y la transmisión aún contendrá

no

La llamada para clear borra cualquier bit de error que esté activo. Entonces tu

cin>>addAntonymAnswer1;

Leerá el no que no fue comido en la lectura anterior, y la acción vuelve inmediatamente, sin esperar nueva entrada. Lo que debes hacer es hacer un clear seguido de un ignorar, hasta la próxima línea nueva. Usted le dice la cantidad de caracteres que debe ignorar al máximo. Esa cantidad debe ser la mayor cantidad posible:

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

Hacer eso hará que la secuencia se vacíe, y la siguiente lectura esperará a que escriba algo.

Otro problema surge si tienes un cin >> seguido de una línea getline : El cin dejará cualquier espacio en blanco (también líneas nuevas) después de su token de lectura, pero getline dejará de leer después de que llegue a dicha nueva línea. Veo que lo has dejado clear después de casi todo. Así que quiero mostrarte cuando lo necesites y cuando no. No lo necesita cuando secuencia múltiples cin >> Supongamos que tiene en su búfer: "foo / nbar / n". Luego haces las siguientes lecturas

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

Después de la primera, su búfer contendrá "/ nbar / n". Es decir, la nueva línea todavía está activada. La segunda cin>> saltará primero todos los espacios en blanco y las líneas nuevas, de modo que pueda hacer frente a /n estar en la parte delantera de la bar . Ahora, también puede secuenciar múltiples llamadas a getline :

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

Getline descartará el /n que lee al final de la línea, pero no ignorará las nuevas líneas o el espacio en blanco al comienzo. Entonces, después de la primera línea get, el buffer contiene "bar / n". El segundo getline leerá correctamente "bar / n" también. Ahora, consideremos el caso en el que necesita borrar / ignorar:

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

El primero dejará la secuencia como "/ nbar / n". La línea get verá inmediatamente el /n al principio, y pensará que leerá una línea vacía. Por lo tanto, continuará de inmediato y no esperará nada, dejando la transmisión como "bar / n". Entonces, si tiene una línea getline después de una cin>> , primero debe ejecutar la secuencia clear / ignore, para borrar la nueva línea. Pero entre getline o cin>> , no deberías hacerlo.