如果输入的大小和格式特定,为什么会忽略fgets调用?

4
我能帮忙翻译。以下是一段用C语言编写的代码。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main(void)
{
    char buf1[8];
    char buf2[1024];
    int n;

    fgets(buf1, 6, stdin);
    n = atoi(buf1);

    fgets(buf2, 16, stdin);

    return 0;
}

每当第一个fgets收到长度超过4个字符的输入时,第二个fgets就会在没有等待输入的情况下退出。
如果第一个输入为1000,则第二个fgets会挂起并等待输入。然而,如果输入有5个字符,例如10000,则第二个fgets存在并且程序结束。
这种行为的解释是什么?

1
我无法复制你遇到的问题。如果我输入 1000 + 'Enter',那么程序会等待另一个 Enter 被键入。 - KamilCuk
您的意思是“超过6个字符”吗? - Vlad from Moscow
1
fgets(以及其他stdio输入函数)的意思是“从输入流中获取字符”,而不是“等待输入”。只有在没有足够的字符来满足请求时才会发生等待。 - M.M
你为什么要丢弃 fgets() 的返回值呢?它可能读取的比你要求的少,所以你需要利用那个值。 - Toby Speight
fgets返回一个指向数据写入的缓冲区的指针。不幸的是,它不返回读取的字符数。因此,如果缓冲区在实际字符串结束之前包含'\0',那么就没有简单的方法来知道读取的确切字符数。 - anegru
2个回答

5
如果在调用fgets时,输入内容超过指定大小减1,例如:
char buf1[8];

fgets(buf1, 8, stdin);

输入内容为:

1234567

当输入缓冲区中未读取到与按下“Enter”键相对应的新行字符“\n”时,它将不会被读取。

字符数组f1将包含以下内容。

{ '1', '2', '3', '4', '5', '6', '7', '\0' }

因此,输入缓冲区保持非空状态,第二个fgets调用读取输入缓冲区的尾部而无需等待更多用户输入。

当输入小于指定大小减1时,换行符'\n'将被读入字符数组,输入缓冲区将为空。

例如,对于此调用:

fgets(buf1, 8, stdin);

用户输入
123456

如果是字符数组,那么该字符数组将会包含:

{ '1', '2', '3', '4', '5', '6', '\n', '\0' }

2

当你输入4个字符时,(至少在Windows中)你会读到以下6个字符:

1 2 3 4 '\r' '\n'

您的缓冲区只有6个字节大小,而且还需要适配一个尾随的零字节。因此,第一次调用fgets()函数会放置

"1234\r\0"

如果第一次调用fgets()读取了一个不完整的行,将该行读入缓冲区,然后进行第二次调用,仍然会得到\n,它终止该行并导致第二个fgets()将其放置。

"\n\0"

将数据复制到第二个缓冲区并立即返回。 因此,在计数时,您需要考虑行尾(Windows为"\r\n",Linux为"\n")和零字节。

2
当从stdin读取时,不应该有任何\r,因为它是一个文本流。 - AProgrammer

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