【问题标题】:while loop gets() twice in Cwhile循环在C中获得()两次
【发布时间】:2013-05-31 15:48:08
【问题描述】:

我知道这种 while 循环问题很常见,通常是由输入流中的换行符引起的。但是,我无法修复我的 while 循环,而且我真的不明白为什么会发生这种情况。

考虑以下示例:

 int main()
 {
   int option = -1;
   char buffer[100];
   while (option != 10)
    {
     while(printf("Enter menu choice: \n"), gets(buffer), option < 0)
           {
             some code here dealing with buffer and assigning input to option...
           }
     printf("something\n");
     }
    return 0;
  }

忽略此代码的实现(例如,将输入存储为整数而不是字符串等),因为它只是我的 while 循环案例的简化版本。让我担心的是,在它真正通过循环之前,我必须输入两次数字。

输出:

进入菜单选择: 1

进入菜单选择: 1

所有灯都亮着 灯光设置:1111 1111 1111 1111

我不确定为什么会在这种情况下发生...谢谢!

更新:感谢您的回答。我通过重写我的 while() 条件修复了代码

while(printf("\nEnter menu choice: \n"), gets(buffer),  option = checkMenuOption(buffer), option < 0 && strcmp(buffer, ""));

【问题讨论】:

  • 您没有在任何地方修改option。在printf("something\n"); 之后添加option++,如果它是一个特定值,或者在某个时候为其分配10。
  • 现在这是一种在while() 循环条件下重复打印的奇怪方法。非常难以阅读。
  • 实际上我是从 char buffer[100] 中取出整数并将其分配给 int 选项。
  • 你能发布那个代码吗?我们无法确定问题是否不存在:)
  • return 0”后缺少分号

标签: c while-loop gets


【解决方案1】:

我可以建议您使用fgets 而不是gets 吗?它更安全,可用于防止缓冲区溢出。

另外,我已经稍微重写了你的代码,这会做你感兴趣的事情吗?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int option = -1;

    char buffer[100];

    while (option != 10)
    {
        printf("Enter menu choice: \n");

        fgets(buffer, 100, stdin); /* get input from the standard input
                                      and save it in the buffer array */

        option = atoi(buffer); /* convert input to integer */
    }

    return 0;
}

如果用户输入'10',程序将退出:

$ ./a.out 
Enter menu choice: 
10
$

如果你想在这里保留旧代码:

#include <stdio.h>
#include <stdlib.h>


int main()
{
    int option = -1;
    char buffer[100];
    while (option != 10)
    {
        while(printf("Enter menu choice: \n"), gets(buffer), option = atoi(buffer), option < 0)
        {

        }
        printf("something\n");
    }
    return 0;
}

问题是您没有在循环条件中分配 option 任何内容。在第一次测试期间,option 仍然不是 10,它只是在正文中变为 10。在第一次运行选项被分配 10(或您输入的任何内容)之后,while 循环仍然没有评估它,这就是为什么它再次打印该语句并要求您输入一个值。

您可以像这样重写循环来测试我的声明(确保更新 option 的代码仍在正文中):

while(option &lt; 0 &amp;&amp; printf("Enter menu choice: \n") &amp;&amp; gets(buffer))

最后,不要使用逗号,因为用逗号分隔的语句将始终被执行(我假设这不是你想要的,在其他情况下它可能完全没问题),它只是列表中的最后一个成员测试真/假。看看this

【讨论】:

  • 感谢您的解释。我发现如果我想保留我的原始代码,我需要在 while() 条件下评估输入。
  • 是的,请记住使用逗号分隔列表和将每个部分都视为要评估为真/假的语句之间的区别。在前一部分中,正如您自己所见,每次循环迭代时都会评估除最后一条语句之外的所有内容。在后者中,您可以避免这种情况,正如我向您展示的那样。
  • 我知道这个事实,因为这就是我想要得到的,但感谢您的建议!
  • 很高兴能帮上忙,我自己很少在循环初始化中遇到逗号分隔的列表,你可以很容易地用它打动(或混淆)不太主动的灵魂:)
  • 除了笨拙之外,没有什么“令人印象深刻”的。
【解决方案2】:

printf() 和 gets() 在 while 测试中,在评估 option 之前。

事实上,根据当前的行为,您实际上不必输入两次数字:您必须输入一次数字然后输入任何内容,这样gets() 就会返回。

编辑:我添加了一些关于它如何运行的细节:

  • 指令指针到达while 语句的最开头,开始评估其条件
    • 调用 printf()
    • 调用gets()
    • 评估option &lt; 0,这是真的。
  • while 语句的正文
    • 代码解析字符串,将option 设置为大于零的值。
  • 指令指针循环返回以评估条件
    • 调用 printf()
    • 调用gets()
    • 评估option &lt; 0,这是错误的。
  • while 循环终止
    • 致电printf("something\n");

在这里可以看到,缓冲区一旦被gets()填充,只能在第一次迭代中被代码读取,而在第二次迭代中被忽略。

【讨论】:

  • 哦,我明白了。我通过将实际代码置于 printf() 和 gets() 之后的 while() 条件下解决了我的问题。但是,您能详细说明一下吗?为什么 printf() 和 gets() 在这里运行两次?
  • 感谢您的回答。现在我明白问题出在哪里了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 2022-01-16
相关资源
最近更新 更多