C: Scanf 在类型不匹配中被忽略

C: Scanf Ignored in Type Mismatch

是的,SO 上已经有类似的问题 scanf() 在“解释”回车键之前不等待用户输入,但我的问题是这个问题只发生在扫描时——这是 %ld(前面有一个 space)——读取一个字符串而不是另一个长数字。如果此摘要看起来令人费解,请在下面查看详细信息。

我在 C 中有以下程序:

#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    long int cardnum, tmp;
    int num_of_digits;
    bool validate; // valid value
    LOOP:do
    {
        printf("Number: ");
        scanf(" %ld", &cardnum);

        tmp = cardnum, num_of_digits = 0;
        while (tmp != 0)
        {
            tmp /= 10;
            ++num_of_digits;
        }

        if (num_of_digits != 16)
        {
            printf("INVALID\n");
            goto LOOP;
        }

        validate = false;
        // ... (validate will be processed here, and there will be a case where "validate" will be true)
    }
    while (validate != true);
}

输入:

Number: INVALID
Number: INVALID
Number: INVALID
...

我在别处读到 scanf 会忽略最后一行缓冲区(或其他内容),但在我的例子中,只有当 scanf 没有从用户那里收到正确的输入类型时才会发生。有人可以帮忙吗?

提前致谢。

how not all invalid inputs will result in this bug!)

如果您输入的不是数字,则 scanf 将失败。因此,检查它是否无法扫描数字,如果扫描失败,则忽略输入直到行尾,例如。注意 - 你也应该处理 EOF

if (scanf(...) != 1) {
    int c;
    // ignore input
    while ((c = getchar()) != EOF) {
        // until a newline!
        if (c == '\n') {
            break;
        }
    }
    // when eof
    if (c == EOF) {
        // then exit our program with a failure!
        printf("ERROR: End of input!");
        exit(-1);
    }
    // if not eof, means user is ready to enter yet another line
    printf("you inputted an invalid line - please input a line consisting of digits only!");
    continue;
}

请参阅 cppreference scanf 中的 return 值说明。


LOOP:do {goto LOOP; 看起来像一个可怕的想法 - 不要在那里使用 goto,看起来很混乱。相反,您更喜欢重构您的代码,这样您就不必使用 goto。例如:

for (;;) {
    if (some_check) {
         continue;
    }
    if (some_another_check) {
         continue;
    }
    // if we get here, means all checks succeeded - so we need to break
    break;
}

goto 有很好的用途,它恰好被使用 - 参见前例。 https://www.kernel.org/doc/html/v4.10/process/coding-style.html#centralized-exiting-of-functions .

如果您输入的不是整数,那么您需要从输入缓冲区中删除无效输入。

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    long int x;
    int valid;
    
    do
    {
        if ( !( valid = ( scanf( " %ld", &x ) == 1 ) ) && valid != EOF )
        {
            scanf( "%*[^\n]%*c");
        }
    } while ( !valid );
    
    printf( "x = %ld\n", x );
    
    return 0;
}

控制台输出可能类似于

A
12
x = 12

请注意,使用 goto 语句是一种糟糕的编程风格。相反,您可以使用我的程序中显示的 do-while 语句。这实际上是您程序中的 goto 语句是多余的。