我们为什么使用:
1)cin.ignore
2)cin.clear
?
只是:
1)忽略(提取和丢弃)流中不需要的值
2)清除流的内部状态。使用cin.clear之后,内部状态再次设置为goodbit,这意味着没有“错误”。
长版:
如果在“流”(cin)上放了东西,那么必须从那里拿走。“获取”是指从流中“使用”,“删除”,“提取”。流有流。数据像流动的水一样在cin上流动。您根本无法阻止水流;)
看例子:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
如果用户回答:第一个问题是“ Arkadiusz Wlodarczyk”,该怎么办?
运行该程序,亲自看看。
您将在控制台“ Arkadiusz”上看到,但程序不会要求您输入“年龄”。打印“ Arkadiusz”后,它将立即完成。
并且未显示“ Wlodarczyk”。好像不见了(?)*
发生了什么?;-)
因为在“ Arkadiusz”和“ Wlodarczyk”之间有一个空格。
名称和姓氏之间的“空格”字符是计算机的标志,表示有两个变量正在等待在“输入”流上提取。
计算机认为您要发送多个输入变量。这个“空间”标志是他用这种方式解释的标志。
因此,计算机将“ Arkadiusz”分配给“名称”(2),并且由于您在流(输入)上放置了多个字符串,因此计算机将尝试将值“ Wlodarczyk”分配给变量“年龄”(!)。用户将没有机会在第6行的'cin'上放置任何内容,因为该指令已被执行(!)。为什么?因为仍然有东西在流。正如我之前所说,流正在流动中,因此必须尽快将所有内容从流中删除。当计算机看到cin >>年龄时,可能性就来了;
计算机不知道您创建了一个存储某人年龄的变量(第4行)。“年龄”仅仅是一个标签。对于计算机,“年龄”可以这样称呼:“ afsfasgfsagasggas”,并且它是相同的。对他来说,这只是一个变量,他将尝试分配“ Wlodarczyk”给您,因为您在第(6)行中命令/指示计算机这样做。
这样做是错误的,但是嘿,是你做的!这是你的错!好吧,也许是用户,但仍然...
好吧好吧 但是如何解决呢?
让我们尝试一下该示例,然后再适当修复它,以学习更多有趣的东西:-)
我更喜欢采取一种我们了解事物的方法。不知道我们如何做而修复的东西并不能使您满意,您不认为吗?:)
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate();
调用上述代码后,您将注意到流(cin)的状态等于4(第7行)。这意味着其内部状态不再等于goodbit。东西弄乱了。很明显,不是吗?您试图将字符串类型值(“ Wlodarczyk”)分配给int类型变量'age'。类型不匹配。现在该通知某些问题了。而计算机则通过更改流的内部状态来实现。就像:“你这家伙,请修理我。我'好心地'告诉你;-)“
您根本无法再使用“ cin”(流)。卡住了 就像您将大木头原木放在水流上一样。您必须先对其进行修复,然后才能使用它。无法再从该流(cin)中获取数据(水),因为原木(内部状态)不允许您这样做。
哦,所以,如果有障碍物(原木),我们可以使用专用的工具将其清除吗?
是!
cin的内部状态设置为4就像是发出啸叫声并发出声音的警报。
cin.clear将状态恢复为正常(goodbit)。就像您来静音了一样。你只是把它推迟。您知道发生了什么,所以您说:“可以停止发出声音,我知道已经出了问题,请闭嘴(清除)”。
好吧,让我们这样做吧!让我们使用cin.clear()。
使用“ Arkadiusz Wlodarczyk”作为第一个输入来调用以下代码:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;
cin.clear();
cout << cin.rdstate()<< endl;
在执行上述代码后,我们可以肯定地看到状态等于goodbit。
太好了,问题解决了吗?
使用“ Arkadiusz Wlodarczyk”作为第一个输入来调用以下代码:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;;
cin.clear();
cout << cin.rdstate() << endl;
cin >> age;
即使在第9行之后将状态设置为goodbit,也不会要求用户提供“年龄”。程序停止。
为什么?!
噢,伙计...您刚刚放下了警报,水里的木头原木呢?*回到我们谈论“ Wlodarczyk”的文字时,据说它是怎么消失的。
您需要从流中除去那块木头“ Wlodarczyk”。关闭警报根本无法解决问题。您刚刚将其静音,您认为问题已经解决了吗?;)
现在是时候使用其他工具了:
cin.ignore可以与带有绳索的特殊卡车相提并论,该绳索可以去除堵塞溪流的原木。它清除了程序用户创建的问题。
那么,即使在警报响起之前我们也可以使用它吗?
是:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
cin >> age;
在第7行发出声音之前,将删除“ Wlodarczyk”。
什么是10000和'\ n'?
它说删除10000个字符(以防万一),直到满足'\ n'(ENTER)。顺便说一句,使用numeric_limits可以做得更好,但这不是此答案的主题。
因此,造成问题的主要原因在发出噪音之前就已经消失了……
那为什么我们需要“清除”?
如果有人在第6行中要求“给我您的年龄”问题,例如:“二十岁”而不是写20,该怎么办?
类型不再匹配。计算机尝试将字符串分配给int。然后警报开始。您甚至没有机会对这种情况做出反应。cin.ignore不会对您有帮助。
因此,在这种情况下,我们必须使用clear:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
cin >> age;
cin.clear();
cin.ignore(10000, '\n');
但是,您是否应该“以防万一”清除状态?
当然不是。
如果出现问题(cin >> age;)指令将通过返回false来通知您。
因此,我们可以使用条件语句来检查用户是否在流中输入了错误的类型
int age;
if (cin >> age)
cout << "You put integer";
else
cout << "You bad boy! it was supposed to be int";
好的,这样我们可以解决我们的初始问题,例如:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n');
int age;
cout << "Give me your age:" << endl;
if (cin >> age)
cout << "Your age is equal to:" << endl;
else
{
cin.clear();
cin.ignore(10000, '\n');
cout << "Give me your age name as string I dare you";
cin >> age;
}
当然,这可以通过例如使用循环while来做您有问题的事情来改善。
奖金:
您可能想知道。如果我想从用户的同一行中获取姓名和姓怎么办?如果cin将用“空格”分隔的每个值解释为不同的变量,是否甚至可以使用cin?
当然,您可以通过两种方式做到这一点:
1)
string name, surname;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin >> surname;
cout << "Hello, " << name << " " << surname << endl;
2)或通过使用getline函数。
getline(cin, nameOfStringVariable);
就是这样的:
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
第二种选择可能会适得其反,以防您在getline之前使用'cin'之后使用它。
让我们来看看:
一种)
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
如果您输入“ 20”作为年龄,则不会要求您输入nameAndSurname。
但是,如果您这样做:
b)
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endll
一切都很好。
什么?!
每次在输入(流)上输入内容时,您都会在末尾的白色字符ENTER('\ n')后面留下,您必须以某种方式输入值以进行控制台。因此,如果数据来自用户,则一定会发生。
b)cin特征是它忽略空格,因此当您从cin读取信息时,换行符'\ n'无关紧要。它被忽略。
a)getline函数将整个行取到换行符('\ n'),当换行符为第一行时,getline函数将获得'\ n',这就是全部。您提取在行3中将“ 20”放在流中的用户留在流中的换行符。
因此,为了修复它,总是调用cin.ignore();。每次使用cin来获取任何值(如果要在程序中使用getline()的话)。
因此正确的代码将是:
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cin.ignore();
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
希望您知道更多信息。
哈,请让我安静!:-)