【问题标题】:Do while loop not exiting despite expression becoming false尽管表达式变为假,但不要退出while循环
【发布时间】:2015-01-04 12:28:08
【问题描述】:

我在这里有一个程序,它在指定的 void 方法中包含一个 do-while 循环。我试图退出函数内的循环,以便 do-while 循环实际上按预期工作。除了在我运行程序并且发生其中一种情况之后,尽管我的 while 语句指出它应该只在(userInput!= 1)时工作,但程序继续运行。 我不能使用全局变量来解决这个问题,因为我的任务限制了我使用这些技术,因此非常感谢任何帮助!

这是我的代码的 sn-p:

void functionTest()
{
    int gameOver = 0;
    int userInput;

    do
    {
        printf("please enter a number 1-3");
        scanf("%d",&userInput);

        switch(userInput)
        {
            case 1:
               printf("You entered %d",userInput);
               gameOver = 1;
               break;

            case 2:
               printf("You entered %d",userInput);
               gameOver = 1;
               break;

            case 3:
               printf("You entered %d",userInput);
               gameOver = 1;
               break;
        }
    }
    while(gameOver!= 1);
}
}

【问题讨论】:

  • 为什么要大写c?
  • 无法复制:ideone.com/BRS5rx
  • 发布完整的代码,它在您的程序中的方式,因为它按预期工作。
  • 无法重现该问题。在 while 循环的末尾放置一个printf("%d\n", gameOver); 并查看打印的内容。也许这是一个scanf 问题。 scanf 在不遵守输入格式时会做出奇怪的反应。
  • 调试器说什么

标签: c switch-statement break do-while


【解决方案1】:

问题在于,如果在可以读取整数之前输入流中存在其他字符(不是整数的一部分),scanf() 将失败并且永远不会清除不可用的数据......这会导致一个无限循环(scanf() 反复无法读取与整数相同的字符,一遍又一遍)。

因此,当scanf() 失败时,或者作为格式的一部分,您需要读取无效字符。

一个简单的解决方法是将您的 scanf 从:

scanf("%d",&userInput);

到:

scanf("%*[^0-9]%d",&userInput);

在读取整数之前读取(并丢弃)输入流中不是数字 0-9 的任何字符......但这仍然不能检查 scanf 是否因任何其他原因而失败(如关闭的输入流)。

你可以用这样的东西替换它:

int scanfRes,c;
do {
    scanfRes = scanf("%d",&userInput); /* try to read userInput */
    /* ..then discard remainder of line */
    do {
        if ((c = fgetc(stdin)) == EOF)
            return; /* ..return on error or EOF */
    } while (c != '\n');
} while (scanfRes != 1); /* ..retry until userInput is assigned */

..它将重试scanf(),直到分配了该字段,每次尝试后丢弃该行的其余部分,如果fgetc()在这样做时遇到错误或EOF,则退出该函数。

【讨论】:

    【解决方案2】:

    问题可能出在您使用scanf() 时。您在按 Enter 之前输入的内容不是 1、2 或 3。您能告诉我们当它要求您输入选项时您输入的确切内容吗?

    有时,在使用新的 scanf() 之前需要刷新标准输出。在 scanf 行之前尝试 fflush(stdout) 。 见older question 1older question 2

    编辑: 如果我输入除“1”、“2”或“3”以外的任何内容,我可以很容易地重现问题......

    我建议,在执行 switch 语句之前,请执行以下操作:

    1. 在 scanf() 之前添加 fflush(stdout)
    2. 接受作为字符串 (%s) 而不是数字的输入。 (需要 char [])
    3. 修剪尾随和前导空格的字符串。
    4. 使用库函数转换为数字
    5. 然后根据该数字切换大小写

    【讨论】:

    • 很难说没有看到完整的代码,但你可能是正确的。 scanf() 有时可能是个无情的野兽 :)
    • 判断scanf是否成功读取输入很容易:检查返回值。
    • 我同意。该程序在触发开关盒之前当然需要大量的输入验证/按摩,但这可能比 OP 目前拥有的经验更多。
    • "有时,在使用新的 scanf() 之前需要刷新标准输出" 我对此表示怀疑。为什么这个?如果,为什么只有“sometimes”? Out is out and in is in,它们不是耦合的。
    • scanf() 之前不刷新stdout 可能会导致显示乱序,但不会导致这里出现无限循环。
    猜你喜欢
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多