【问题标题】:C do while loop repeats 2 times before checking conditionC在检查条件之前执行while循环重复2次
【发布时间】:2022-01-18 21:46:46
【问题描述】:

为什么我的 do/ while 循环在检查条件之前重复了 2 次?

int main() {

    char quit;
    quit = getchar();
    do {
        printf("Next state: ");
        clock_t start = clock();
        count_values(a, b);
        clock_t end = clock();
        float seconds = (float)(end - start) / CLOCKS_PER_SEC;
        print_state(b);
        printf("\nTime: %f\n", seconds);
        swap(a, b);
        printf("Press enter to print next generation. To quit, enter 'q'.");
        quit = getchar();
    } while(quit != 'q');
    
    return 0;
}

只有在循环重复 2 次后,getchar() 才等待输入,为什么?如何解决?

【问题讨论】:

  • getchar() 在第一次通话后离开换行符,然后您在第二次通话时阅读。
  • @dunlop 这是因为调用 getchar quit = getchar();还读取换行符'\n';
  • 因为您的第一个输入是q 和一个换行符。所以你的quit 等于q 从循环外的第一个getchar 直到你在循环内第二次调用getchar,它用换行符覆盖它。
  • 简单修复,使用fgets()
  • 旁白:没有理由使用float seconds。建议double 类型和数学。

标签: c loops while-loop do-while


【解决方案1】:

您可能手动输入,因此当您按下Enter 键时,会留下一个换行符,然后第二个getchar() 调用会使用该换行符。

要绕过这个,你可以使用fgets()

   char quit[100];

   fgets(quit, sizeof(quit), stdin);

    do {
        printf("Next state: ");
        clock_t start = clock();
        clock_t end = clock();
        float seconds = (float)(end - start) / CLOCKS_PER_SEC;
        printf("\nTime: %f\n", seconds);
        printf("Press enter to print next generation. To quit, enter 'q'.");
        fgets(quit, sizeof(quit), stdin);
    } while(quit[0] != 'q');

虽然上面的代码应该可以完成这项工作,但可以通过键入以q 开头的任何内容来轻松欺骗该程序。

解决方案是使用strcmp() 来检查字符串是否只包含"q"

请注意,fgets() 还将换行符存储在缓冲区中,以绕过您需要将其替换为 NULL 字节。

   char quit[100];

    do {
        printf("Next state: ");
        clock_t start = clock();
        clock_t end = clock();
        float seconds = (float)(end - start) / CLOCKS_PER_SEC;
        printf("\nTime: %f\n", seconds);
        printf("Press enter to print next generation. To quit, enter 'q'.");
        fgets(quit, sizeof(quit), stdin);
        quit[strcspn(quit, "\n")] = '\0'; /* get rid of \n */
    } while(strcmp(quit, "q") != 0);

【讨论】:

    【解决方案2】:

    它确实在检查条件之前重复两次。 您可以通过稍微修改代码来检查这一点,这也使它成为一个最小的可重现示例:

    #include <stdio.h>
    
    int test(char c) {
        printf("Testing input: %d\n", c);
        return c != 'q';
    }
    
    int main() {
        char quit;
        quit = getchar();
        do {
            printf("Press enter to print next generation. To quit, enter 'q'.\n");
            quit = getchar();
        } while(test(quit));
    
        return 0;
    }
    

    您可以看到在第一个循环之后已经对输入进行了测试。不是'q',如果您输入q,则输入[enter]q 将被 quit = getchar(); before 循环使用。然后在条件中检查换行符(十进制10),它不是q

    所以你的假设是错误的。

    【讨论】:

      猜你喜欢
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 2017-04-03
      • 1970-01-01
      • 2013-04-25
      • 2018-04-16
      • 2019-09-03
      • 2020-07-21
      相关资源
      最近更新 更多