4

在 C++ 中,为了处理错误的输入(例如当程序要求输入一个整数但您键入一个字符时),它应该能够做一些事情,然后循环重复输入。

当您在需要整数时输入字符时,我的循环会无限迭代,反之亦然:

#include<iostream>

int main()
{
    while (cout << "Enter a number" && !(cin >> num)) 
    {
        cin.sync(); 
        cin.clear();
        cout << "Invalid input; please re-enter.\n";
    }
}

我应该怎么做才能让程序再次提示输入新的输入?

4

3 回答 3

5

如果cin >> num失败,则需要从流中删除无效输入。我建议使用ignore而不是sync来完成此操作。原因是sync不能保证在标准库的所有实现中删除剩余的输入。

#include <iostream>
#include <limits>

int main()
{
    int num;
    while (cout << "Enter a number" && !(cin >> num)) 
    {
        cin.clear();    // clear the error

        // Remove input up to a new line
        cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
        cout << "Invalid input; please re-enter.\n";
    }
}

上面的示例std::numeric_limits<std::streamsize>::max()用于检索输入缓冲区可以容纳的最大字符数。这允许ignore()删除尽可能多的字符,直到新行。它是惯用的 C++,并且比使用可能只是隐藏您当前遇到的问题的幻数更可取。

这很好用,但不能处理输入在数字后包含额外字符的情况。为了处理这些情况,需要对循环进行一些更改以处理额外的验证。一种选择是从 读取整行cin,将其放入 a std::stringstream,从中读取数字,然后进行额外验证。但是,可能需要考虑一种特殊情况 - 数字后面唯一的字符是空格的行。幸运的是,标准库提供了流修饰符std::skipws,可以轻松处理这种情况。下面的示例显示了如何轻松做到这一点

#include <iostream>
#include <sstream>

int main()
{
    int num;

    for(;;)
    {
        std::cout << "Enter a number: " << std::flush;

        std::string line;
        std::getline(std::cin, line); // Read a line from console
        std::stringstream text(line); // store in a string stream

        char ch = 0;
        if(!(text >> num).fail() && (text >> std::skipws >> ch).fail())
        {
            break;
        }

        std::cout << "Invalid input; please re-enter.\n";
    }

    return 0;
}

该表达式(text >> std::skipws >> ch).fail()将跳过出现在数字之后的所有空格,然后尝试读取单个字符。如果没有可用的字符,则读取将失败,表明用户只输入了一个数字而没有输入其他内容。如果我们尝试这样做,cin即使输入有效,它也会等待用户输入更多文本。

于 2013-05-29T15:00:40.260 回答
2

使用cin.ignore()代替并从这个答案cin.sync()中查看原因

while (cout << "Enter a number" && !(cin >> num)) {
    cin.clear();           // clear error
    cin.ignore(100, '\n'); // ignore characters until next '\n' (or at most 100 chars)
    cout << "Invalid input; please re-enter.\n";
}

更多关于 cin.ignore

请注意,您可以将忽略字符数的范围扩大到最大值

    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
于 2013-05-29T14:48:29.007 回答
-1

您可以将输入读取为字符串,将其转换为整数并验证它..

#include <iostream>
#include <string>
using namespace std;
int main()
{
    int number = 0;
    string input;
    do {
        cout << "Enter a number: ";
        cin >> input;
        number = atoi(input.c_str()); // atoi returns 0 on error..
        if (number != 0 || input.compare("0") == 0) // but maybe the user really entered "0".
            break;
        cout << endl;
        cout << "Invalid input; please re-enter.\n";
    } while (1);
    cout << "You entered " << number << endl;
    return 0;
}

示例程序执行:

% ./foo
Enter a number: abc

Invalid input; please re-enter.
Enter a number: 2
You entered 2
% ./foo
Enter a number: 0
You entered 0

..虽然这可能不是最优雅的解决方案。

于 2013-05-29T14:56:23.580 回答