为什么这个cin阅读卡住?
我在我的程序上选择了一个失败,阻止我为变量 addAntonymAnswer1
分配一个值。我试过在语句之前运行 cin.clear()
来读取我的 yes / no
但是代码只是不会响应。
I've singled out a failure on my program that prevents me from assigning a value to the variable addAntonymAnswer1
. I've tried running cin.clear()
before the statement to get the thing read my yes/no
answer, but the code just won't respond.
失败的程序位位于 void dictionaryMenu(vector< WordInfo>& wordInfoVector)
cin.clear();
cout<<">";
cin>>addAntonymAnswer1;
// cin reading STUCK, why!?
到达程序的这一点,用户必须选择添加一个单词,然后添加
to get to that point of the program the user has to choose to add a word, and then add a synonym.
运行程序的输入是:
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;
}
cin.clear()
不清除标准输入。它所做的是清除错误位,如 eofbit
, failbit
和其他,并将流设置为良好状态。也许你期望它清除它里面的东西吗?如果用户键入
cin.clear()
doesn't clear the standard input. What it does is clearing error bits, like eofbit
, failbit
and others, and sets the stream into a good state. Maybe you expected it to clear out anything in it? If the user typed
yes no
刚才之前,你
cin >> someStringVariable;
它会读取 no
流仍会包含
no
$ b b
然后调用 clear
,清除任何被激活的错误位。然后,您的
The call to clear
then clears any error bits being active. Then, your
cin>>addAntonymAnswer1;
将读取 no
由上一次读取吃掉,并且动作立即返回,不等待新的输入。你应该做的是做一个清除
后跟一个忽略,直到下一个换行符。你告诉它应该最大程度忽略的字符数量。该金额应为可能的最高金额:
Will read the no
that wasn't eaten by the previous read, and the action immediately returns, not waiting for new input. What you should do is doing a clear
followed by an ignore, up to the next newline. You tell it the amount of characters it should ignore maximally. That amount should be the highest number possible:
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
这样做会使流为空,下面的读取将等待您输入内容。
Doing that will make the stream empty, and a following read will wait for you to type something in.
如果您有 cin ;< / c $ c>之后跟随一个
getline
:cin将在其读取令牌后留下任何空格(也换行),但 getline
将在它命中这样一个换行符后停止阅读。我看到你已经把清除
几乎一切。所以我想告诉你,当你需要它,而不是。当您对多个 cin>>>
进行排序时,不需要它。假设你在你的缓冲区:foo \\\
bar \\\
。然后执行以下读取
Another problem arises if you have got a cin >>
followed by a getline
: The cin will leave any whitespace (also newlines) after its read token, but getline
will stop reading after it hits such a newline. I see you have put clear
after nearly everything. So i want to show you when you need it and when not. You don't need it when you sequence multiple cin >>
. Assume you have in your buffer: "foo\nbar\n". Then you do the following reads
cin >> a; // 1
cin >> b; // 2
第一次之后,缓冲区将包含\\\
bar \\\
。也就是说,换行符仍在。第二个 cin>>
将首先跳过所有空格和换行符,以便它可以处理 \ n
位于 bar
的前面。现在,您还可以排序多个 getline
调用:
After the first, your buffer will contain "\nbar\n". That is, the newline is still in. The second cin>>
will first skip all whitespace and newlines, so that it can cope with \n
being at the front of bar
. Now, you can also sequence multiple getline
calls:
getline(cin, a);
getline(cin, b);
Getline会丢弃 \\\
它读取行末尾,但不会在开始时忽略换行符或空格。所以,在第一个getline之后,缓冲区包含bar\\\
。第二个getline也会正确读取bar\\\
。现在,让我们考虑你需要clear / ignore的情况:
Getline will throw away the \n
that it reads at the line end, but won't ignore newlines or whitespace at the begin. So, after the first getline, the buffer contains "bar\n". The second getline will correctly read "bar\n" too. Now, let's consider the case where you need the clear/ignore:
cin >> a;
getline(cin, b);
第一个将流保留为\\\
bar \\\
。 getline然后会在开始时立即看到 \\\
,并认为它读取了一个空行。因此,它将立即继续,不等待任何东西,将流保留为bar\\\
。因此,如果在 cin>>
之后有一个 getline
,则应首先执行clear / ignore序列,清除换行符。但在 getline
或 cin>>
之间,您不应该这样做。
The first will leave the stream as "\nbar\n". The getline then will see immediately the \n
at the begin, and will think it read an empty line. Thus, it will immediately continue and not wait for anything, leaving the stream as "bar\n". So, if you have a getline
after a cin>>
you should first execute the clear/ignore sequence, to clear out the newline. But between getline
or cin>>
's, you should not do it.