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

时间:2014-08-24 19:17:27

标签: c++ cin getline 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";

}

7 个答案:

答案 0 :(得分:39)

忽略正是这个名字所暗示的。

它没有扔掉&#34;你不需要的东西,它会忽略你调用它时指定的字符数,直到你指定为断点的字符。

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

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

答案 1 :(得分:12)

你正在以错误的方式思考这个问题。每次使用cingetline时,您都会考虑采用逻辑步骤。防爆。先问一个号码,然后问一个名字。这是考虑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.ignorecin之间添加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在这里有何帮助?

根据cplusplus.com-

中的忽略文档摘录
  

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;报头中。