我在我的程序中发现了一个失败,导致我无法为变量addAntonymAnswer1
赋值。我已经尝试在语句之前运行cin.clear()
来让事情读取我的yes/no
答案,但代码不会响应。
失败的程序位位于void dictionaryMenu(vector <WordInfo> &wordInfoVector)
内并读取
cin.clear();
cout<<">";
cin>>addAntonymAnswer1;
// cin reading STUCK, why!?
要达到程序的那一点,用户必须选择添加一个单词,然后添加一个同义词。
运行程序的输入是:
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;
}
答案 0 :(得分:14)
cin.clear()
未清除标准输入。它的作用是清除错误位,如eofbit
,failbit
等,并将流设置为良好状态。也许你期望它清除它里面的任何东西?如果用户输入
yes no
就在此之前,你
cin >> someStringVariable;
它将读取no
,并且流仍将包含
no
对clear
的调用会清除所有处于活动状态的错误位。那么,你的
cin>>addAntonymAnswer1;
将读取前一次读取未被吃掉的no
,并立即返回操作,而不是等待新输入。你应该做的是做一个clear
然后忽略,直到下一个换行符。你告诉它应该最大限度地忽略的字符数量。该金额应该是可能的最高数量:
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
这样做会使流空,并且以下读取将等待您输入内容。
如果你有cin >>
后跟getline
,则会出现另一个问题:cin会在读取令牌后留下任何空格(也是换行符),但getline
将在之后停止读取它打了这样一个换行符。我看到你已经把clear
放在了几乎所有的东西之后。所以我想在你需要的时候告诉你,什么时候不需要。排序多个cin >>
时,您不需要它。假设你有缓冲区:“foo \ nbar \ n”。然后你执行以下读取
cin >> a; // 1
cin >> b; // 2
在第一个之后,您的缓冲区将包含“\ nbar \ n”。也就是说,换行符仍然存在。第二个cin>>
将首先跳过所有空格和换行符,以便它可以处理位于\n
前面的bar
。现在,您还可以对多个getline
来电进行排序:
getline(cin, a);
getline(cin, b);
Getline将丢弃它在行尾读取的\n
,但不会在开头忽略换行符或空格。因此,在第一个getline之后,缓冲区包含“bar \ n”。第二个getline也会正确读取“bar \ n”。现在,让我们考虑一下你需要clear / ignore的情况:
cin >> a;
getline(cin, b);
第一个将流保留为“\ nbar \ n”。然后getline将立即看到开头的\n
,并认为它读取空行。因此,它会立即继续而不是等待任何事情,将流保留为“bar \ n”。因此,如果在getline
之后有cin>>
,则应首先执行清除/忽略序列,以清除换行符。但是在getline
或cin>>
之间,您不应该这样做。
答案 1 :(得分:1)
因为正在等待输入而被“卡住”。 cin被附加到程序的标准输入句柄,你必须输入一些内容并点击回车。
答案 2 :(得分:1)
cin >> ...
从标准输入读取,直到找到空格字符。当您为同义词列表输入8 5
时,8
会被lineOfSyns
读入,仅此而已。当程序到达cin >> addAntonymAnswer1
时,5
会被读入addAntonymsAnswer1
。您的程序会出现意外行为,因为它预计会yes
或no
,但会得到5
。
请使用cin.getline()
代替>>
。例如,参见this page的第18.2和18.3节。
答案 3 :(得分:1)
在你的程序中,你问用户:
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
然后您尝试读取用户输入的行
cin>>lineOfSyns;
但是,这只能读取第一个空格。因此,当
时,用户键入的第二个数字仍在cin
缓冲区中
cin>>addAntonymAnswer1;
执行行,以便将数据读入addAntonymAnswer1
字符串。用户永远不会有机会输入“是”或“否”,并且您对这些值的测试失败。
您应该考虑更改为使用string
getline()
重载进行读取:
getline( cin, stringvar);
这可能比使用cin.getline()
更好,因为它没有带string
的重载 - 使用该成员函数,你需要读入一个字符数组,这远远少于比阅读string
更灵活。