将字符串输入到期望整数值的变量时无限循环

Endless while loop when input a string to a variable that expected integer value

我的C代码如下

int main() {
    int userInput = 0;

    while (userInput != 4) {
        printf("Enter a number : ");
        scanf("%d", &userInput);
    };
    return 0;
}

这通常在输入整数值时有效。但是当输入 一个字符串值 时,它不会再次询问输入。它进入无限循环打印“输入数字”短语。然后,我尝试了如下代码。

int main() {
    int userInput = 0;

    while (userInput != 4) {
        userInput = 0;             // reset the userInput value
        printf("Enter a number : ");
        scanf("%d", &userInput);
    };
    return 0;
}

即使这样也没有解决我的问题。为什么会这样?如何修复?

您需要从无效数据中释放输入缓冲区。类似于以下内容。

do
{
    printf("Enter a number : ");
    if ( scanf("%d", &userInput) != 1 )
    {
        scanf( "%*[^\n]" );
        userInput = 0;
    }
} while ( userInput != 4 );

另一种方法是使用函数fgets读取字符数组中的整个字符串,然后使用strtol将其转换为整数并检查转换是否成功。

"This normally work when input a integer value. But when input a string value it not asking again to a input."

如果数据扫描未被 scanf() 转换,则输入流(在本例中为 stdin)未被推进。再次调用 scanf() 时,它将尝试从相同的错误输入扫描并转换相同的数据,并得到相同的结果。这就是导致无限循环的原因。当 `scanf() 设置为转换数字字符时,输入字母字符总是会失败。

好消息是 scanf() return 一个值表示有多少项已成功转换。 alpha 使用 %d 格式说明符扫描的输入,应导致转换零项。使用 scanf() 的代码应始终检查它的 return 值:

int num_converted = scanf("%d", &userInput);
if(num_converted != 1) 
{
     //handle error 
     ...
}

顺便说一句,scanf() 被许多人认为是 sub-optimal method for handling user input。例如

"...it will tell you whether it succeeded or failed, but can tell you only approximately where it failed, and not at all how or why. You have very little opportunity to do any error recovery."
(jamesdlin).

考虑使用 fgets() 的替代方法。

以下将整个输入行读入缓冲区,消除不需要的白色 space 并验证输入。只有这样它才会将输入缓冲区转换为指定类型...

int main(void) {
    int userInput = 0;
    char inBuf[20] = {0};
    
    printf("Enter a number : ");
    //int num = scanf("%d", &userInput);
    while (fgets(inBuf, sizeof inBuf, stdin)) {
        inBuf[strcspn(inBuf, "\r\n")] = 0;//remove unwanted white space
        if(digits_only(inBuf))//example validation for numeric only input
        {
            userInput = atoi(inBuf);
            printf("\n%d entered, and converted!\n\nctrl-c to exit\n...Or enter a number : \n", userInput);
        }
        else
        {
            printf("\n%s contains non-numeric characters, it cannot be converted.\n\nctrl-c to exit\n...Or enter a number : \n", inBuf);
        }
    };
    return 0;
}

//test for numeric only input   
//(note that other validations can be coded with expansions 
//to accommodate float or double, alpha only, etc.)    
bool digits_only(const char *in)
{
    while(*in)
    {
        if(!isdigit(*in)) return false;
        in++;
    }
    return true;
}