从fgets()函数未获得预期输出

3

这里有一段简单的代码,但我得不到期望的输出。

#include<stdio.h>

int main()
{
   char buf[1024];
   while(1)
   {
      fgets(buf,strlen(buf),stdin);
      printf("%s",buf);
      printf("hello");
   }
}

在上面的代码中,我希望无论我从键盘输入什么字符串,都能将其原样打印出来然后输出hello。 据我所知,fgets()是一个阻塞函数,直到我从键盘输入一串字符串并按下ENTER键时,它才会阻塞程序。所以当我运行它时,我的期望结果如下:
$ ./a.out
I input some text here <ENTER>
I input some text here 
hello

但实际上,我得到的输出是在终端上无限循环打印“hello”。为什么我的fgets()不能阻塞程序呢?有什么想法吗?

4个回答

6
问题在于strlen(buf)返回0,因为buf[0]恰好为0(不保证)。你应该使用sizeof(buf)代替:
fgets(buf,sizeof(buf),stdin);

2

fgets()调用更改为:

fgets(buf,sizeof(buf),stdin)
//        ^^^^^^

在未初始化的buf上调用strlen()会返回不确定的结果。有可能strlen()会返回0,在这种情况下fgets()会立即返回。


2
这是因为您的缓冲区 strlen 可能为零。您应该使用 sizeof ,它给出了数组(1024)的大小,而不是它包含的字符串的长度(在此处不确定)。在您的情况下,它可能是一个零大小的字符串(* buf =='\ 0'),因为 fgets 调用根本不会阻塞。实际上,它也可以有长度为1,因为标准规定:

fgets函数从流指针指向的流中读取不超过由n指定的字符数减少1个, 将其写入指向s的数组中。在换行符(保留)或文件结尾后不会再读取任何其他字符。 null字符被立即写入读入到数组中的最后一个字符之后。

事实上,作为一个未初始化的局部变量, buf 可能包含任何,所以依赖它是不明智的(如果它根本不包含空终止符,则甚至可能发现自己转储核心,因为 strlen 越界)。
如果你想要一个经过验证的输入函数,请参见这里。它具有缓冲区溢出保护、提示、去掉末尾的换行符以及在事件过长时清除行剩余部分。我将在下面重复这些代码,使本答案更加自包含。
#include <stdio.h>
#include <string.h>

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '\0';
    return OK;
}

0
你应该使用 sizeof(buf) 而不是像这样使用 strlen(buf) :
 fgets(buf,sizeof(buf),stdin); 

或者直接:

 fgets(buf,1024,stdin);

不是特别喜欢神奇数字。如果数组大小发生变化,使用 sizeof 更好。如果你将其更改为 char buf[512] 而没有调整你的 fgets(1024),那么你会遭受痛苦的折磨。 - paxdiablo
1
当然可以,但这只是为了解释fgets将处理的值是什么。 - Camille G.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接