【问题标题】:scanf("%d",a) with a "while" grammar bypass the scanf带有“while”语法的scanf("%d",a) 绕过scanf
【发布时间】:2016-01-01 21:39:52
【问题描述】:

如果没有初始化 ("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 编译了这段代码。

【问题讨论】:

  • scanf 之后添加一个print 语句只是为了验证事情是否符合您的预期,或者附加一个调试器。
  • 出于好奇,您为什么输入char 而变量是int

标签: c switch-statement scanf


【解决方案1】:

当您输入a 时,对于mod,这是一个无效的输入,因为scanf() 需要为%d 输入一个int。所以它不是读入mod。所以mod 留下了上一次迭代中输入的mod 的值。

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

检查scanf() 的返回值并丢弃任何无效输入。 众所周知,scanf() 不适合读取用户输入,而且使用它通常更难正确处理输入故障。

更好的方法是使用fgets() 读取 输入,然后使用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);

【讨论】:

    【解决方案2】:

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

    scanf(%d, &mod);
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 2014-05-30
      • 2015-07-30
      • 2017-08-19
      • 2022-01-22
      • 2017-07-27
      • 2016-07-22
      相关资源
      最近更新 更多