卡在无限循环中

时间:2013-05-29 14:35:54

标签: c++ while-loop int iostream infinite-loop

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

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

#include<iostream>

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

我该怎么办才能让程序再次提示输入新内容?

3 个答案:

答案 0 :(得分: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 ++,并且优于使用magic numbers,这可能只是隐藏您当前遇到的问题。

这很有效但不处理输入在数字后面包含额外字符的情况。为了处理这些情况,需要稍微改变循环以处理附加验证。一种选择是从cin读取整行,将其放入std::stringstream,从中读取数字,然后进行其他验证。有一个特殊情况可能需要考虑 - 一条线,其中数字后面的唯一字符是空格。幸运的是,标准库提供了流修饰符std::skipws,可以轻松处理这种情况。以下示例显示了如何在没有太多effor

的情况下执行此操作
#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执行此操作,即使输入有效,它也会等待用户输入更多文本。

答案 1 :(得分:2)

使用cin.ignore()代替cin.sync()并查看原因from this answer

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

More on cin.ignore

请注意,您可以扩展忽略字符数的范围,最大为

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

答案 2 :(得分:-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

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