标准函数
fgets
在即将推出的C23标准中是这样指定的:
7.23.7.2 fgets 函数
剧情简介
#include <stdio.h> char *fgets(char * restrict s, int n, FILE * restrict stream);
函数最多将fgets
指定的字符数从n
指向的流中读取到stream
指向的数组中。在换行符(保留)之后或文件结尾之后不会读取任何其他字符。在读入数组的最后一个字符后立即写入空字符。s
退货
如果成功,
函数将返回fgets
。如果遇到文件结尾并且没有字符读入数组,则数组的内容保持不变并返回空指针。如果操作过程中发生读取错误,则数组成员有未指定的值,并返回空指针。s
除了 C99 中添加的
restrict
关键字之外,此规范自原始 ANSI-C 文档以来没有任何变化。
为
n
指定的类型为 int
,这与采用数组长度或对象计数(类型为 size_t
)的所有其他 C 库函数不一致。如果不潜在地破坏使用指向 fgets
的函数指针或为 n
传递负值的程序,则无法解决此问题。 fread
和 fwrite
,以及许多其他标准函数,在原始 Unix 文档中过去将其数字参数和返回值指定为 int
,但在 ANSI-C 之前进行了更改,这就引出了一个问题:为什么fgets
未包含在本次更新中,那么是否有任何令人信服的理由以不同方式对待 fgets()
?
此外,有些案例似乎没有指定的行为:
n <= 1
,fgets()
应该返回s
而不尝试从流中读取吗?n == 1
,尽管没有字符被读入数组,但是否应该将s[0]
设置为空字符?n <= 0
,我们可以为s
传递一个空指针吗?关于
n <= 1
的行为:
在本规范的上下文中没有“成功”的正式定义,唯一想到的失败情况与从流中读取并收到错误或到达文件末尾有关,这两种情况都在规范中解决. 由于
fgets()
最多读取比
n
指定的字符数少 1 个字符,因此它不应该读取
n <= 1
的任何字符,因此不会尝试从流中进行任何输入。因此,在这种情况下,fgets()
应返回 s
。似乎未指定是否必须修改 s
以及如果
s[0]
则将 n == 1
设置为空字符,尽管我有权访问其源代码的所有 C 库都以这种方式运行。由于存在这个潜在问题,似乎建议避免使用低于 fgets()
的值来调用
2
作为参数 n
。注意snprintf
也有类似的问题:
7.23.6.5and a null character is write at the end of the characteracted into the array剧情简介
snprintf
函数
#include <stdio.h> int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
snprintf
函数与
等效,只不过输出被写入数组(由参数fprintf
指定)而不是流中。如果s
为零,则不写入任何内容,并且n
可能是空指针。否则,超出第s
st 的输出字符将被丢弃,而不是写入数组,并在实际写入数组的字符末尾写入空字符。如果复制发生在重叠的对象之间,则行为未定义。退货n-1
snprintf
函数返回如果
足够大则将写入的字符数,不包括终止空字符,或者如果发生编码错误则返回负值。因此,当且仅当返回值均为非负且小于n
时,空终止输出才被完全写入。 如果实际上没有将任何字符写入数组,则句子n
有点含糊,要么是因为输出为空,要么因为它已被完全丢弃。 尽管存在这种歧义,但似乎不可能争论给定空格式字符串的
snprintf
可能不会在
s
中生成空字符串,前提是 n
不为零。对于 snprintf
的情况,使用更精确的
fgets
和 n == 1
规范会很有帮助,确保将 s[0]
设置为空字符。