使用 "while" 语法的 scanf("%d",a) 绕过 scanf

scanf("%d",a) with a "while" grammar bypass the scanf

如果没有初始化 ("mod=0") ,这段代码会无限循环。 我不明白为什么这段代码会循环,即使我使用了 getchar(); 擦除缓冲区。 当我先输入“1”,然后再输入 "a" 时,就会出现无限循环。 任何人都可以帮助我了解这种情况吗?

int main()
{
    srand((unsigned)time(NULL));
    int mod = 0;
    int val = 0;
    do {    
        printf("\t-----------------------------\n");
        printf("\t|%5s %5s %5s %5s|\n", "1.create", "2.modify", "3.print", "4.quit");
        printf("\t|%15s","Input command  : ");
        scanf("%d", &mod);
        printf("\t-----------------------------\n");
        switch (mod){
        case 1:     random();           val++;      break;
        case 2:     if(val != 0) { modify();    break; }
        case 3:     if(val != 0) { print();     break; }
        default:    getchar(); printf("\tUnknown Command!! Retry!! \n");    break;
        }
    } while (mod != 4);
}

我用 Visual Studio 2015 编译了这段代码。

当您输入 a 时,mod 的输入无效,因为 scanf() 期望 %dint。所以不是读成mod。所以 mod 留下了在上一次迭代中输入的 mod 的值。

它进入无限循环的原因是因为 scanf() 不丢弃无效输入。因此反复尝试读取 a 并失败并继续循环。

检查 scanf() 的 return 值并丢弃任何无效输入。 scanf() 对于读取用户输入来说是出了名的糟糕,正确处理输入失败通常更难使用它。

更好的方法是使用 fgets() and then parse it using sscanf().

读取 输入
do {
    ...

    printf("\t|%15s","Input command  : ");

    fgets(line, sizeof line, stdin);
    char *p = strchr(line, '\n');
    if(p) *p = 0; /* remove tailing newline, if present */
    if( sscanf(line, "%d", &mod) != 1) {
       printf("Invalid input\n");
       continue;
    }

    printf("\t-----------------------------\n");
    ....

   }while (mod != 4);

你的代码的问题是,一旦你输入了一个数字,这是一个有效的菜单选项,变量 mod 总是等于你第一次输入的同一个数字输入它,如果你输入错误的第二次输入。这种行为来自于

scanf(%d, &mod);

尝试读取整数,但是当您输入 'a' 作为第二个选项时,输入无法从您的标准输入中读取整数。因此它不会进入您的 switch 方法的默认情况,因为变量 mod 等于您输入的第一个有效输入的输入。