当提示输入整数值时,为什么在输入字符时程序会被破坏?

时间:2013-12-23 14:55:00

标签: c++

示例:

int i=0;
do {
    cin >> i;
    if(!isdigit(i)) cout << "Error. Must be an integer\n\n";
}
while(cin.fail());

如果用户输入了字符而不是整数,程序会因某种原因而中断并进入某个无限循环。为什么是这样?有没有办法防止它发生? isdigit()函数似乎不适用于int个变量,只适用于char个变量。

3 个答案:

答案 0 :(得分:3)

您似乎对输入的工作原理感到困惑。当你写

std::cin >> i;

iint,输入流将提取文本 一个整数值:它将跳过空格,然后提取 一个可能的符号,然后是一个或多个数字。然后它会转换 将此文本转换为int,并将其存储在请求的位置。如果它 没有找到相应格式的文本,它会设置一个 错误状态(failbit),在您清除之前将保持设置状态 它。它将修改i;你必须经常检查 在使用变量输入之前输入已成功。

另一方面,

isdigit具有未定义的行为,除非 传递的整数在[0,UCHAR_MAX]范围内。 (注意 那个范围。这意味着您不能简单地将其传递给char。)

目前尚不清楚你在这里要做什么。如果只是 输入int

int i;
while ( !(std::cin >> i) ) {
    std::cout << "Error: integer wanted" << std::endl;
    std::cin.clear();       //  Clear error...
    std::cin.ignore( INT_MAX, '\n' );   //  And ignore characters which caused it 
                                        //  (up until next '\n')
}

如果你想要一个数字:

int i = std::cin.get();
while ( i != EOF && !isdigit( i ) ) {
    std::cout << "Error, single digit wanted" << std::endl;
    i = std::cin.get();
}
char ch = i;        //  NOW (and only now) can you convert into int.

std::cin.get()会返回int,以便处理 带值EOFint保证在范围内 [0...UCHAR_MAX],或EOF,因此您可以直接传递它 到isdigit。只有在你完成这些测试后才应该 将其转换为char(因为数字是一个字符)。

答案 1 :(得分:2)

始终需要在> 之后检查输入是否成功,例如

if (std::cin >> i) {
    // process input
}

如果输入失败,则设置std::ios_failbit。设置此标志时,流将不接受任何输入并转换为false。要清除错误标记,请使用

std::cin.clear();

清除错误标志不会删除有问题的字符。你需要摆脱它们,例如,使用

std:: ignore();

答案 2 :(得分:0)

上面的代码肯定不会创建无限循环。但是循环通常发生在预期数字并且给出非数字时,因此缓冲区中的字符将保留在那里并且流处于错误状态。这将在流被适当清除之前发生,以便stdio可以根据格式规范继续读取。当然循环必须在我们的程序中完成,因为stdio不是自己循环。

要清除输入和输入内容,您可以使用:

std::cin.clear();
std::cin.ignore();