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

mlnl4t2r  于 2023-01-06  发布在  其他
关注(0)|答案(7)|浏览(154)

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

}
ghhkc1vu

ghhkc1vu1#

ignore做的正是它的名字所暗示的。
它不会“丢弃”你不需要的东西,而是忽略你在调用它时指定的字符数,最多忽略你指定作为分隔符的字符。
它可以与输入和输出缓冲器一起工作。
本质上,对于std::cin语句,在调用getline之前使用ignore,因为当用户用std::cin输入内容时,他们按下Enter键,'\n'字符进入cin缓冲区。它得到的是换行符,而不是你想要的字符串,所以你执行了std::cin.ignore(1000,'\n'),这会清空缓冲区,直到你想要的字符串。(1000放在那里是为了跳过指定分隔符(在本例中为'\n'换行符)之前的特定字符数。)

hpxqektj

hpxqektj2#

你的思路不对。每次使用cingetline时,你都是按照逻辑步骤来思考的。例如,首先要求输入一个数字,然后要求输入一个名称。这是思考cin的错误方式。因此,你会遇到争用情况,因为你认为每次要求输入时,流都是干净的。
如果你编写的程序纯粹是为了输入,你会发现问题:

int main()
{
    double num;
    string mystr;

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

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

在上面的例子中,你想的是“先得到一个数字”,所以你输入123,按回车键,你的输出将是num=123,mystr='',为什么呢?因为在流中你有123\n,而123被解析成num变量,而\n还在流中。默认情况下,阅读getline函数的文档时,它将在istream中查找,直到遇到\n。在本例中,由于\n在流中,因此看起来像是“跳过”了它,但它工作正常。
为了让上面的代码工作,你必须输入123Hello World,它将正确地输出num=123,mystr='Hello World',或者你在cingetline之间放一个cin.ignore,这样它将按照你所期望的逻辑步骤进行分解。
这就是为什么您需要ignore命令,因为您是以逻辑步骤而不是流的形式来考虑它的,所以会遇到争用情况。
以另一个在学校中常见的代码示例为例:

int main()
{
    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的地方输入了一个字符,应用程序将产生一个看起来奇怪的输出。

mv1qrgav

mv1qrgav3#

    • 简短回答**

为什么?因为在输入流中仍然有空白(回车,制表符,空格,换行符)。
什么时候?当你使用一些函数时,它们本身并不忽略前导空格。Cin默认忽略并删除前导空格,但是getline本身并不忽略前导空格。

    • 现在详细回答。**

在控制台中输入的所有内容都是从标准流stdin中读取的。当您输入某个内容时,比如说256,然后按Enter键,流的内容变为256\n。现在cin会选择256并将其从流中删除,而\n仍然保留在流中。接下来,当您输入您的姓名时,比如说Raddicus。流的新内容是\nRaddicus
这里有一个陷阱,当你尝试使用getline读取一行时,如果没有提供任何分隔符作为第三个参数,getline默认读取到换行符,并从流中移除换行符。getline从流中读取并丢弃\n,导致在mystr中读取空字符串,看起来像跳过了getline(但它没有)因为流中已经有一个换行符,getline不会提示输入,因为它已经读取了它应该读取的内容。

    • 现在,cin. ignore如何帮助您?**

根据cplusplus.com中的忽略文档摘录-

    • i流&忽略(流大小n = 1,整数分隔符= EOF);**

从输入序列中提取字符并丢弃它们,直到提取了n个字符,或者比较结果等于delim。
如果到达文件末尾,函数也会停止提取字符。如果过早到达(在提取n个字符或找到delim之前),函数会设置eofbit标志。
因此,cin.ignore(256, '\n');忽略前256个字符或所有字符,直到遇到分隔符(在您的示例中为\n),以先出现者为准(这里\n是第一个字符,因此忽略直到遇到\n)。
仅供参考,如果你不知道要跳过多少字符,并且你的唯一目的是清除流,为使用getline或cin读取字符串做准备,那么你应该使用cin.ignore(numeric_limits<streamsize>::max(),'\n')

    • 快速解释:**它忽略等于流的最大大小的字符或直到遇到"\n",以先发生的情况为准。
0vvn1miw

0vvn1miw4#

当您要手动从输入流中丢弃特定数量的字符时。
一个非常常见的用例是使用它来安全地忽略换行符,因为cin有时会留下换行符,您必须越过这些字符才能到达下一行输入。
长话短说,它在处理流输入时为您提供了灵活性。

o7jaxewo

o7jaxewo5#

Ignore函数用于跳过(丢弃/扔掉)输入流中的字符。Ignore文件与文件istream关联。考虑下面的函数,例如:cin.忽略(120,“/n”);该特定函数跳过下一个120输入字符或跳过这些字符直到读取到换行符。

pvcm50d1

pvcm50d16#

正如许多其他用户所指出的那样,这是因为可能有空格或换行符。
考虑下面的代码,它从给定的字符串中删除所有重复的字符。

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

所以,你得到的点,它会忽略那些不需要的输入,并会得到工作完成.

uurv41yg

uurv41yg7#

在c++中使用scanf(“%[^\n]",str)比在cin〉〉语句后使用cin.ignore()更好。要做到这一点,首先必须包含< cstdio >头。

相关问题