如何理解"程序忽略我的输入请求"从C ++常见问题解答?

时间:2015-04-07 16:46:16

标签: c++ iostream

我想了解这个项目:

Why is my program ignoring my input request after the first iteration?

来自C ++ FAQ。

我编译了测试程序:

#include <iostream>

int main()
{
        char name[1000];
        int age;
        for (;;) 
        {
                std::cout << "Name: ";
                std::cin  >> name;
                std::cout << "Age: ";
                std::cin  >> age;
        }
        return 0;
}

一切似乎都运转良好。然而,作者说有一个问题:

  

因为数字提取器在输入中留下了非数字   缓冲液中。

并且正确的源代码应为:

int main()
{
        char name[1000];
        int age;
        for (;;) 
        {
                std::cout << "Name: ";
                std::cin  >> name;
                std::cout << "Age: ";
                std::cin  >> age;
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
        return 0;
}

请您解释一下该计划的预期行为,以及如何解决不良行为?

编辑:

问题是我没想到程序应该处理错误,例如在预期数字输入时输入10b。实际上,作者的修改处理了这样的错误,但是没有处理用户输入错误的错误。 b10

3 个答案:

答案 0 :(得分:2)

在第一个例子中,如果您为名称输入a,然​​后输入10b作为年龄,则程序的输出为

Name: a
Age: 10b
Name: Age: 

现在我们得到这个的原因是10b中的b留在流中,然后下次std::cin >> name;被调用它抓住b并继续询问年龄。在第二个例子中,std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');将删除数字后的字母,程序将正常运行。

答案 1 :(得分:1)

在您的第一个代码中,对于age,如果您输入的是字符而不是数字,那么cin会将其保留在输入流中,而下一个cin会尝试读取那。所以,它不需要输入。

让我们简单地运行代码,进行for循环的三次迭代,

输入和输出

Name: ar
Age: a
Name: Age:
Name: Age:

如您所见,如果您为age输入字符,则不会再向用户询问值。要防止这种情况,并刷新缓冲区以清除缓冲区中不需要的字符,请使用

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

但我个人认为使用cin.clear();也是一件好事。

std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

这将消除缓冲区中所有剩余的不需要的字符。

答案 2 :(得分:0)

考虑以下代码:

int main()
{
    char name[1000];
    int age;
    char name2[1000];

    std::cout << "Name: ";
    std::cin >> name;
    std::cout << "Age: ";
    std::cin >> age;
    std::cin >> name2;

    std::cout << "Name: \"" << name << "\"" << std::endl;
    std::cout << "Age: \"" << age << "\"" << std::endl;
    std::cout << "Name2: \"" << name2 << "\"" << std::endl;

    return 0;
}

如果您输入:
John
23 Doe

name2作为Doe读入。如果您在阅读agename2之间执行代码,可能会发生奇怪的事情。通过清除读取之间的缓冲区,这不会发生。