fgetc()和fgets()的区别是什么?

5

我知道fgetc()会从由参数指定的FILE指针所指向的文件中读取一个字符。

fgets()会在参数列表中指定的大小范围内读取整个字符串,但是当遇到行尾时,fgetc()返回EOF,而fgets()返回NULL。那么为什么有两个让人困惑的事情要记住呢?


你刚刚用一句话总结了C标准库中最常用的两个函数,包括它们之间的比较差异。那么这些函数到底有什么“令人困惑”的地方呢? - WhozCraig
不同的人需要不同的东西,不同的情况需要不同的工具,我想这就是全部。 - Lee Duhem
如果出现“文件结束”,fgetc()将返回EOF吗? - anatolyg
3个回答

14
一个函数返回EOF,另一个函数返回NULL的原因是两个函数的返回类型不同:一个返回int,而另一个返回char*
当读取到输入流的结尾时,这两个函数都需要返回一个“特殊”的值。所谓“特殊”,指的是在合法的输入中不会出现的值。对于指针来说,在大多数情况下,特殊值是NULL,因此这就是fgets返回的值。但是,你不能使用NULL来标记fgetc的输入结束,因为零字符的字符码可以合法地出现在输入中,这就是为什么在返回单个字符的I/O函数中使用EOF作为“特殊值”的原因。

2
答案可能是:"我们不知道C语言会变得如此受欢迎, 而且持续这么长时间。"
C标准中的其他错误包括creat()(没有e,为什么?),strtok()(默认情况下不安全!),sprintf()(如果没有可能的缓冲区溢出,你很少会使用它,否则它就像一个过大的锤子),atoi()(几乎不可能正确检查错误),等等!

请参考dasblinkenlight的答案,了解为什么fgetc/fgets的区别不是错误。 - Wojtek Surowka
请注意,creat 不在 C 标准库中,而是在 UNIX/POSIX 中。 - Kninnug
@WojtekSurowka:就我个人而言,我认为这有点合理化(尽管合理)。API可以用另一种方式实现,例如fgetc()可以返回char*,EOF时返回NULL,否则返回一个指向内部(类似于strtok!)两个字符数组的指针:来自流的一个字符,后跟一个\0以方便使用。然后这两个函数将返回相同的东西(C字符串),并使用相同的哨兵值。我不是说那会是一个更好的API,但在OP提出问题的框架下,它可能是一个更一致的API。 - John Zwinck

1

当然,您需要向C标准库的原始设计者询问,不确定他们是否还在。

在我看来,许多接受字符串缓冲区的标准函数返回相同的缓冲区,因此从这个角度来看,fgets()的行为是完全规律和可预测的。

如果您不害怕NULL,那么它返回指针意味着该函数可以链接:

char buf[128];
printf("you said '%s'\n", fgets(buf, sizeof buf, stdin));

上述情况在 fgets() 失败时是未定义的,但如果用一些对 NULL 有明确定义处理方式的东西来替换 printf(),你就能理解我的意思了。
当然,fgetc() 返回指针是没有意义的,因为它更低级,只需要返回单个字符或 EOF,而 int 是标准类型。

“具有明确定义的 NULL 处理方式”,哈哈,你是说像 C 标准库函数中的几乎没有吗? - John Zwinck
@JohnZwinck 或许是这样,但你也可以编写自己的函数。 :) - unwind

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