如何使用fgets()通过c中的用户输入来控制while循环的执行?

时间:2017-05-27 10:23:45

标签: c fgets

我正在尝试在c中编写一个程序,其中我可以通过stdin的用户输入来控制while循环执行。我通过scanf和getchar函数成功完成了它。现在我试图使用fgets()函数复制它,这被广泛推荐使用而不是scanf()函数。我写了以下代码:

#include<stdio.h>
#include<string.h>

int main()
{
 char loop[4]= "yes";

 printf("%s\n",loop);
 while(strcmp(loop,"yes")==0)
    {
     printf("Do you want to continue? [yes|no]: ");
     fgets(loop,4,stdin);
    }
}

在终端的输出中,我得到以下内容:

Do you want to continue? [yes|no]: yes
Do you want to continue? [yes|no]: 

我得到继续循环的提示,当我输入'no'时,它会停止,但是只要我输入'yes',循环执行一次然后停止。

我想问题是,只要按下回车键,fgets()就会将其存储到循环变量中,这就是while循环终止的原因。我在思考正确的方向吗?如果是,我怎么能摆脱这种额外的字符,在这种情况下是“回车”。

1 个答案:

答案 0 :(得分:2)

更改此:

fgets(loop, 4, stdin);

对此:

fgets(loop, 5, stdin);

当然,在将缓冲区的大小设置为5之后,例如char loop[5]= "yes";,为了存储单词“ yes”的3个字符,换行符fgets()将会读取(因为是读行,对吧?)和字符串NULL终止符(如您所知)。


要解释代码的行为,您必须了解@DavidBowling的注释:

  

请注意,通过使用fgets(loop, 4, stdin);,当输入“是”时,换行符将留在输入流中,因此下一个输入呼叫将接听该换行符。

使用此程序演示:

#include<stdio.h>
#include<string.h>

int main()
{
  char loop[4]= "yes";

  while(strcmp(loop,"yes")==0)
  {
    printf("Do you want to continue? [yes|no]: ");
    fgets(loop, 4, stdin);
    printf("|%s|\n",loop);    // I surrounded the output, in order to catch the newline
  }
  return 0;
}

输出:

Do you want to continue? [yes|no]: yes
|yes|
Do you want to continue? [yes|no]: |
|

表示换行符保留在标准输入(STDIN)缓冲区中,并在第二次调用fgets()时被占用。从方法的参考:

  

从流中读取字符并将它们作为C字符串存储到str中,直到已读取(num-1)个字符或到达换行符或到达文件末尾为止,以先到者为准。

     

在复制到str的字符之后会自动附加一个终止的空字符。

让我们一步一步看看:

您键入yes,然后按Enter,这将使“标准输入”缓冲区看起来像这样:

------------------
| y | e | s | \n |
------------------

,现在执行对fgets(loop, 4, stdin);的第一次调用,这意味着该方法将尝试从STDIN读取3(4-1)个字符。它读取yes,将它们从STDIN的缓冲区移到您声明的名为loop的程序的缓冲区中,然后附加字符串NULL终止符。

现在STDIN缓冲区是:

------------------
| \n |   |   |   |
------------------

并且在用户有机会输入之前,fgets(loop, 4, stdin);将要执行(这样做是方法的职责,因为它们是STDIN缓冲区中等待消耗的数据-如果没有数据,那么该方法将耐心等待用户输入内容...)。

现在,它将换行符复制到loop中,然后停止在此,因为现在STDIN缓冲区为空,并最终向loop(在索引1)附加了字符串NULL终止符。

现在STDIN缓冲区为空:

-----------------
|   |   |   |   |
-----------------

由于用户没有更多输入-代码循环在while循环之后移动,因为当loop是一个以换行符为第一个字符的字符串时,循环的条件为false。 >


PS:Removing trailing newline character from fgets() input