我用C++编写了一个非常基本的程序,要求用户输入一个数字,然后输入一个字符串。令我惊讶的是,当运行程序时,它从来没有停下来要求输入字符串。它只是跳过它。在阅读了一些关于StackOverflow的内容后,我发现我需要添加一行,内容如下:
cin.ignore(256, '\n');
在获取字符串输入的行之前。添加它修复了问题并使程序工作。我的问题是为什么C++需要cin.ignore()
行,以及我如何预测何时需要使用cin.ignore()
?
下面是我写的程序:
#include <iostream>
#include <string>
using namespace std;
int main()
{
double num;
string mystr;
cout << "Please enter a number: " << "\n";
cin >> num;
cout << "Your number is: " << num << "\n";
cin.ignore(256, '\n'); // Why do I need this line?
cout << "Please enter your name: \n";
getline (cin, mystr);
cout << "So your name is " << mystr << "?\n";
cout << "Have a nice day. \n";
}
7条答案
按热度按时间ghhkc1vu1#
ignore
做的正是它的名字所暗示的。它不会“丢弃”你不需要的东西,而是忽略你在调用它时指定的字符数,最多忽略你指定作为分隔符的字符。
它可以与输入和输出缓冲器一起工作。
本质上,对于
std::cin
语句,在调用getline
之前使用ignore
,因为当用户用std::cin
输入内容时,他们按下Enter键,'\n'
字符进入cin
缓冲区。它得到的是换行符,而不是你想要的字符串,所以你执行了std::cin.ignore(1000,'\n')
,这会清空缓冲区,直到你想要的字符串。(1000放在那里是为了跳过指定分隔符(在本例中为'\n'
换行符)之前的特定字符数。)hpxqektj2#
你的思路不对。每次使用
cin
或getline
时,你都是按照逻辑步骤来思考的。例如,首先要求输入一个数字,然后要求输入一个名称。这是思考cin
的错误方式。因此,你会遇到争用情况,因为你认为每次要求输入时,流都是干净的。如果你编写的程序纯粹是为了输入,你会发现问题:
在上面的例子中,你想的是“先得到一个数字”,所以你输入
123
,按回车键,你的输出将是num=123,mystr=''
,为什么呢?因为在流中你有123\n
,而123
被解析成num
变量,而\n
还在流中。默认情况下,阅读getline
函数的文档时,它将在istream
中查找,直到遇到\n
。在本例中,由于\n
在流中,因此看起来像是“跳过”了它,但它工作正常。为了让上面的代码工作,你必须输入
123Hello World
,它将正确地输出num=123,mystr='Hello World'
,或者你在cin
和getline
之间放一个cin.ignore
,这样它将按照你所期望的逻辑步骤进行分解。这就是为什么您需要
ignore
命令,因为您是以逻辑步骤而不是流的形式来考虑它的,所以会遇到争用情况。以另一个在学校中常见的代码示例为例:
以上看起来是逻辑步骤。首先询问名字,姓氏,然后年龄。所以如果你做了
John
输入,然后Doe
输入,然后19
输入,应用程序工作的每一个逻辑步骤。如果你认为它在“流”,你可以简单地输入John Doe 19
的“名字:“问题,它会工作得很好,似乎跳过其余的问题。为以上工作在逻辑步骤,你需要ignore
其余的流为每个逻辑中断的问题。只要记住把你的程序输入看作是从一个“流”中阅读,而不是按照逻辑步骤。每次你调用
cin
时,它都是从一个流中读取的。如果用户输入了错误的输入,这将创建一个相当有缺陷的应用程序。例如,如果你在应该是cin >> double
的地方输入了一个字符,应用程序将产生一个看起来奇怪的输出。mv1qrgav3#
为什么?因为在输入流中仍然有空白(回车,制表符,空格,换行符)。
什么时候?当你使用一些函数时,它们本身并不忽略前导空格。Cin默认忽略并删除前导空格,但是getline本身并不忽略前导空格。
在控制台中输入的所有内容都是从标准流stdin中读取的。当您输入某个内容时,比如说256,然后按Enter键,流的内容变为
256\n
。现在cin会选择256并将其从流中删除,而\n
仍然保留在流中。接下来,当您输入您的姓名时,比如说Raddicus
。流的新内容是\nRaddicus
。这里有一个陷阱,当你尝试使用getline读取一行时,如果没有提供任何分隔符作为第三个参数,getline默认读取到换行符,并从流中移除换行符。getline从流中读取并丢弃
\n
,导致在mystr中读取空字符串,看起来像跳过了getline(但它没有)因为流中已经有一个换行符,getline不会提示输入,因为它已经读取了它应该读取的内容。根据cplusplus.com中的忽略文档摘录-
从输入序列中提取字符并丢弃它们,直到提取了n个字符,或者比较结果等于delim。
如果到达文件末尾,函数也会停止提取字符。如果过早到达(在提取n个字符或找到delim之前),函数会设置eofbit标志。
因此,
cin.ignore(256, '\n');
忽略前256个字符或所有字符,直到遇到分隔符(在您的示例中为\n),以先出现者为准(这里\n是第一个字符,因此忽略直到遇到\n)。仅供参考,如果你不知道要跳过多少字符,并且你的唯一目的是清除流,为使用getline或cin读取字符串做准备,那么你应该使用
cin.ignore(numeric_limits<streamsize>::max(),'\n')
。0vvn1miw4#
当您要手动从输入流中丢弃特定数量的字符时。
一个非常常见的用例是使用它来安全地忽略换行符,因为cin有时会留下换行符,您必须越过这些字符才能到达下一行输入。
长话短说,它在处理流输入时为您提供了灵活性。
o7jaxewo5#
Ignore函数用于跳过(丢弃/扔掉)输入流中的字符。Ignore文件与文件istream关联。考虑下面的函数,例如:cin.忽略(120,“/n”);该特定函数跳过下一个120输入字符或跳过这些字符直到读取到换行符。
pvcm50d16#
正如许多其他用户所指出的那样,这是因为可能有空格或换行符。
考虑下面的代码,它从给定的字符串中删除所有重复的字符。
所以,你得到的点,它会忽略那些不需要的输入,并会得到工作完成.
uurv41yg7#
在c++中使用scanf(“%[^\n]",str)比在cin〉〉语句后使用cin.ignore()更好。要做到这一点,首先必须包含< cstdio >头。