我用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";
}
答案 0 :(得分:39)
忽略正是这个名字所暗示的。
它没有扔掉&#34;你不需要的东西,它会忽略你调用它时指定的字符数,直到你指定为断点的字符。
它适用于输入和输出缓冲区。
基本上,对于std::cin
语句,您在执行getline
调用之前使用了ignore,因为当用户输入std::cin
的内容时,他们会按Enter键和'\n'
个字符进入cin
缓冲区。然后,如果您使用getline
,它将获取换行符char而不是您想要的字符串。所以你做了std::cin.ignore(1000,'\n')
并且应该将缓冲区清除到你想要的字符串。 (1000用于在指定的断点之前跳过特定数量的字符,在本例中为\ n换行符。)
答案 1 :(得分:12)
你正在以错误的方式思考这个问题。每次使用cin
或getline
时,您都会考虑采用逻辑步骤。防爆。先问一个号码,然后问一个名字。这是考虑cin
的错误方式。所以你遇到竞争条件,因为你假设每次请求输入时流都是清晰的。
如果你纯粹为输入编写程序,你会发现问题:
void main(void)
{
double num;
string mystr;
cin >> num;
getline(cin, mystr);
cout << "num=" << num << ",mystr=\'" << mystr << "\'" << endl;
}
在上面,你在想,“首先得到一个数字。”因此,您输入123
按Enter键,输出将为num=123,mystr=''
。这是为什么?这是因为在流中您有123\n
并且123
被解析为num
变量,而\n
仍然在流中。默认情况下,阅读getline
函数的文档会在istream
中查看,直到遇到\n
为止。在此示例中,由于\n
位于流中,因此它看起来像“跳过”它但它正常工作。
要使上述方法有效,您必须输入123Hello World
才能正确输出num=123,mystr='Hello World'
。那个,或者你在cin.ignore
和cin
之间添加getline
,这样它就会突破你期望的逻辑步骤。
这就是您需要ignore
命令的原因。因为你是在逻辑步骤而不是流形式中考虑它,所以你会遇到竞争条件。
采取学校常见的另一个代码示例:
void main(void)
{
int age;
string firstName;
string lastName;
cout << "First name: ";
cin >> firstName;
cout << "Last name: ";
cin >> lastName;
cout << "Age: ";
cin >> age;
cout << "Hello " << firstName << " " << lastName << "! You are " << age << " years old!" << endl;
}
以上似乎是合乎逻辑的步骤。首先询问名字,姓氏,然后是年龄。因此,如果您输入John
,然后Doe
输入,然后输入19
,则应用程序将执行每个逻辑步骤。如果您在“流”中想到它,您只需在“名字:”问题上输入John Doe 19
,它也会起作用,并且似乎跳过剩下的问题。为了使上述步骤符合逻辑步骤,您需要ignore
问题中每个逻辑中断的剩余流。
请记住考虑您的程序输入,因为它是从“流”读取而不是逻辑步骤。每次调用cin
时,都会从流中读取它。如果用户输入错误的输入,这会创建一个相当错误的应用程序。例如,如果您输入了预期为cin >> double
的字符,则应用程序将产生一个相当(看似)奇怪的输出。
答案 2 :(得分:5)
如果要手动从输入流中丢弃特定数量的字符。
一个非常常见的用例是使用它来安全地忽略换行符,因为cin有时会留下换行符,你将不得不转到下一行输入。
长话短说,它为您提供处理流输入时的灵活性。
答案 3 :(得分:1)
忽略功能用于跳过(丢弃/丢弃)输入流中的字符。忽略文件与文件istream相关联。 考虑下面的功能 例如:cin.ignore(120,'/ n'); 特定功能会跳过下一个120输入字符或跳过字符,直到读取换行符。
答案 4 :(得分:1)
简短答案
为什么?因为输入流中仍然留有空格(回车,制表符,空格,换行符)。
什么时候?当您使用某些功能时,它们本身并不会忽略前导空格。 Cin默认情况下会忽略并删除前导空格,但getline不会单独忽略前导空格。
现在有详细的答案。
您在控制台中输入的所有内容都将从标准流stdin中读取。当您输入某些内容时,假设您输入的是256,然后按Enter,则流的内容变为256\n
。现在,cin拾取256并将其从流中删除,并且\n
仍然保留在流中。
接下来,当您输入名称时,假设Raddicus
,流的新内容是\nRaddicus
。
现在是抓住了。
当您尝试使用getline读取行时,如果未提供任何分隔符作为第三个参数,则getline默认情况下会读取直到换行符,然后从流中删除换行符。
因此,在调用新行时,getline从流中读取并丢弃\n
,并导致在mystr中读取空字符串,这看起来像getline被跳过(但不是),因为流中已经存在换行符,getline将不提示输入,因为它已经读取了应该读取的内容。
现在,cin.ignore在这里有何帮助?
中的忽略文档摘录istream&忽略(streamsize n = 1,int delim = EOF);
从输入序列中提取字符并丢弃它们,直到 要么提取了n个字符,要么一个等于 德林。
如果文件结尾是 到达。如果过早达到(在提取n之前 字符或找到delim),该功能会设置eofbit标志。
因此,cin.ignore(256, '\n');
将忽略前256个字符或所有字符,直到遇到定界符(此处为\ n),以先到者为准(此处\ n为第一个字符,因此它将忽略直到\ n遇到)。
仅供参考,如果您不完全知道要跳过多少个字符,而您的唯一目的是清除流以准备使用getline或cin读取字符串,则应使用cin.ignore(numeric_limits<streamsize>::max(),'\n')
。
快速说明:它会忽略等于流的最大大小的字符,或者直到遇到'\ n'为止,以先发生的情况为准。
答案 5 :(得分:0)
正如许多其他用户所指出的那样。这是因为可能存在空格或换行符。
考虑以下代码,它将删除给定字符串中的所有重复字符。
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
cin.ignore(); //Notice that this cin.ignore() is really crucial for any extra whitespace or newline character
while(t--){
vector<int> v(256,0);
string s;
getline(cin,s);
string s2;
for(int i=0;i<s.size();i++){
if (v[s[i]]) continue;
else{
s2.push_back(s[i]);
v[s[i]]++;
}
}
cout<<s2<<endl;
}
return 0;
}
因此,您知道它会忽略那些不需要的输入并完成工作。
答案 6 :(得分:-2)
在cin&gt;&gt;之后,最好在c ++中使用scanf(&#34;%[^ \ n]&#34;,str)而不是cin.ignore()。声明。首先,你必须包括&lt; cstdio&gt;报头中。