什么时候以及为什么需要在C ++中使用cin.ignore()?

我用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";

}
Raddicus asked 2020-02-12T07:53:06Z
6个解决方案
46 votes

正是名称所隐含的含义。

它不会“丢弃”您不需要的东西,而是会忽略您在调用它时指定的字符数,直到指定为断点的char为止。

它适用于输入和输出缓冲区。

本质上,对于std::cin语句,在执行getline调用之前,请使用ignore,因为当用户使用std::cin输入内容时,它们会按Enter键,并且'\n' char进入cin缓冲区。 然后,如果您使用getline,它将获取换行符char而不是所需的字符串。 因此,您执行了std::cin.ignore(1000,'\n'),这应该清除缓冲区直到所需的字符串。 (将1000放在此处可跳过指定断点(在本例中为\ n换行符)之前特定数量的字符。)

savageWays answered 2020-02-12T07:53:33Z
15 votes

您正在以错误的方式思考。 每次使用cincin >> double时,您都在按逻辑步骤进行思考。 例如 首先要求一个数字,然后要求一个名称。 考虑19的方式是错误的,因此您遇到了竞争问题,因为您假设每次请求输入时流都是干净的。

如果仅出于输入目的编写程序,则会发现问题:

void main(void)
{
    double num;
    string mystr;

    cin >> num;
    getline(cin, mystr);

    cout << "num=" << num << ",mystr=\'" << mystr << "\'" << endl;
}

在上面,您正在思考“首先获得一个数字”。 因此,您输入cin,按Enter键,您的输出将是cin >> double。为什么? 这是因为在流中您有19,并且John Doe 19被解析为ignore变量,而\n仍在流中。 默认情况下,读取getline函数的文档时,它将在istream中查找,直到遇到\n。 在此示例中,由于\n在流中,因此它看起来像在“跳过”它,但是它正常工作。

为了使以上方法起作用,您必须输入cin,这将正确输出cin >> double。也就是说,或者您将19放在John Doe 19ignore之间,以使其分解为您期望的逻辑步骤。

这就是为什么您需要cin命令的原因。 因为您是在逻辑步骤而不是在流形式中考虑它,所以您遇到了竞争状况。

再举一个学校里常见的代码示例:

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;
}

以上似乎是合乎逻辑的步骤。 首先询问名字,姓氏,然后询问年龄。 因此,如果您输入了cin,然后输入了cin >> double,然后输入了19,则应用程序将执行每个逻辑步骤。 如果您在“信息流”中想到它,则只需在“名字:”问题上输入John Doe 19,它同样可以正常工作,并且似乎跳过了其余的问题。 为了使以上内容按逻辑步骤工作,您需要为每个逻辑上的问题中断提供ignore的剩余流。

只需记住您的程序输入是从“流”中读取的,而不是逻辑步骤。 每次调用cin都会从流中读取它。 如果用户输入了错误的输入,则会创建一个有问题的应用程序。 例如,如果输入的字符应为cin >> double,则该应用程序将产生相当(看似)奇怪的输出。

Dan answered 2020-02-12T07:54:30Z
5 votes

当您想手动从输入流中丢弃特定数量的字符时。

一个非常常见的用例是使用它安全地忽略换行符,因为cin有时会留下换行符,您将不得不移至新的输入行。

长话短说,它为您提供处理流输入时的灵活性。

shafeen answered 2020-02-12T07:55:00Z
4 votes

简短答案

为什么? 因为在输入流中还剩下空格(回车,制表符,空格,换行符)。

什么时候? 当您使用某些功能时,它们本身并不会忽略前导空格。 Cin默认情况下会忽略并删除前导空格,但是getline不会单独忽略前导空格。

现在详细回答。

您在控制台中输入的所有内容都将从标准流stdin中读取。 当您输入内容时,假设您的情况是256,然后按Enter键,则流中的内容变为cin.ignore(numeric_limits<streamsize>::max(),'\n')。现在cin拾取256并将其从流中删除,而\n仍保留在流中。接下来,当您输入名称时,假设Raddicus,流的新内容为\nRaddicus

现在来了。当您尝试使用getline读取行时,如果未提供任何分隔符作为第三个参数,则getline默认情况下会读取直到换行符,然后从流中删除换行符。因此,在调用新行时,getline从流中读取并丢弃cin.ignore(numeric_limits<streamsize>::max(),'\n'),并导致在mystr中读取空字符串,这看起来像被跳过了getline(但并非如此),因为流中已经存在换行符,getline不会提示输入 因为它已经阅读了应该阅读的内容。

现在,cin.ignore在这里有何帮助?

根据忽略文档,摘录自cplusplus.com-

istream&忽略(streamsize n = 1,int delim = EOF);

从输入序列中提取字符并丢弃它们,直到   要么提取了n个字符,要么一个等于   德林

如果文件结尾为,该函数还将停止提取字符   到达。 如果过早达到(在提取n之前   字符或查找delim),该功能会设置eofbit标志。

因此,cin.ignore(numeric_limits<streamsize>::max(),'\n')将忽略前256个字符或所有字符,直到遇到定界符(在本例中为\ n),以先到者为准(此处,\ n为第一个字符,因此它将忽略,直到遇到\ n)。

仅供参考,如果您不完全知道要跳过多少个字符,而您的唯一目的是清除流以准备使用getline或cin读取字符串,则应使用cin.ignore(numeric_limits<streamsize>::max(),'\n')

快速说明:它将忽略等于流的最大大小的字符,或者直到遇到'\ n'为止(以先发生的情况为准)。

Himanshu Sharma answered 2020-02-12T07:56:20Z
1 votes

忽略功能用于跳过(丢弃/丢弃)输入流中的字符。 忽略文件与文件istream关联。考虑下面的功能例如:cin.ignore(120,'/ n');特定功能将跳过下一个120个输入字符,或者跳过这些字符,直到读取换行符为止。

vinod answered 2020-02-12T07:56:44Z
-3 votes

在cin >>语句之后,最好在c ++中使用scanf(“%[^ \ n]”,str)而不是cin.ignore()。为此,首先必须包含<cstdio>标头。

Mahmud_28 answered 2020-02-12T07:57:04Z
translate from https://stackoverflow.com:/questions/25475384/when-and-why-do-i-need-to-use-cin-ignore-in-c