fgets() 总是用 终止 char 缓冲区吗?

问题描述 投票:0回答:5

即使已经达到 EOF,fgets() 是否总是终止 char 缓冲区?看起来确实如此(在 ANSI K&R 书中介绍的实现中确实如此),但我想我应该要求确认一下。

我想这个问题也适用于其他类似的函数,例如 gets()。

编辑:我知道这是在“正常”情况下附加的,我的问题是针对 EOF 或错误条件。例如:

FILE *fp;
char b[128];
/* ... */
if (feof(fp)) {
    /* is \0 appended after EACH of these calls? */
    fgets(b, 128, fp);
    fgets(b, 128, fp);
    fgets(b, 128, fp);
}
c fgets
5个回答
17
投票

fgets
总是向读取缓冲区添加“ ”,因此它最多从流中读取
size - 1
个字符(
size
是第二个参数)。

永远不要使用

gets
,因为你永远不能保证它不会溢出你给它的任何缓冲区,所以虽然它在技术上总是终止读取字符串,但这实际上没有帮助。


8
投票

切勿使用获取!!

 7.19.7.2 fgets 函数
    概要
1 #包括 
            char *fgets(char * 限制 s, int n,
                 文件*限制流);
    描述
2 fgets函数读取最多比字符数少1个
    由n指定从stream指向的流到指向的数组
    至 s.换行符后不会读取任何其他字符
    (被保留)或在文件结束之后。写入空字符
    紧接着读入数组的最后一个字符之后。
    退货
3 如果成功,fgets 函数返回 s。如果遇到文件结尾
    并且没有字符被读入数组,数组的内容
    保持不变并返回空指针。如果发生读取错误
    在操作过程中,数组内容是不确定的并且为空
    指针被返回。

所以,,当

fgets()
不返回NULL时,目标数组总是有一个空字符。

如果

fgets()
返回 NULL,则目标数组可能已更改并且可能没有空字符。从
fgets()
获取 NULL 后切勿依赖数组。


编辑添加示例

$ cat fgets_error.c
#包括

无效 print_buf(char *buf, size_t len) {
  整数 k;
  printf("%02X", buf[0]);
  对于 (k=1;k

看到了吗? buf 中没有 NUL :)

男人fgets:

fgets() 从流中最多读入一个小于 size 的字符并将它们存储到 s 指向的缓冲区中。读取在 EOF 或换行符后停止。如果读取新行,则将其存储到缓冲区中。 “ ”存储在缓冲区中最后一个字符之后。

如果您确实以二进制模式“rb”打开文件,并且如果您想使用 fgets 逐行读取文本,则可以使用以下代码来保护您的软件不会丢失文本,如果文本错误地包含 ' ' 字节。 但最后就像其他人提到的那样,如果流包含 ' ',通常你不应该使用

fgets


size_t filepos=ftell(stream);
fgets(buffer, buffersize, stream);
len=strlen(buffer);
/* now check for > len+1 since no problem if the 
   last byte is 0 */
if(ftell(stream)-filepos > len+1) 
{
    if(!len) filepos++;
    if(!fseek(stream, filepos, SEEK_SET) && len)
    {
        fread(buffer, 1, len, stream);
        buffer[len]='\0';
    }
}

是的,确实如此。来自CPlusPlus.com

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

换行符使 fgets 停止读取,但它被视为有效字符,因此包含在复制到 str 的字符串中。

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


4
投票

男人fgets:

fgets() 从流中最多读入一个小于 size 的字符并将它们存储到 s 指向的缓冲区中。读取在 EOF 或换行符后停止。如果读取新行,则将其存储到缓冲区中。 “ ”存储在缓冲区中最后一个字符之后。


2
投票

如果您确实以二进制模式“rb”打开文件,并且如果您想使用 fgets 逐行读取文本,则可以使用以下代码来保护您的软件不会丢失文本,如果文本错误地包含 ' ' 字节。 但最后就像其他人提到的那样,如果流包含 ' ',通常你不应该使用

fgets


size_t filepos=ftell(stream);
fgets(buffer, buffersize, stream);
len=strlen(buffer);
/* now check for > len+1 since no problem if the 
   last byte is 0 */
if(ftell(stream)-filepos > len+1) 
{
    if(!len) filepos++;
    if(!fseek(stream, filepos, SEEK_SET) && len)
    {
        fread(buffer, 1, len, stream);
        buffer[len]='\0';
    }
}

1
投票

是的,确实如此。来自CPlusPlus.com

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

换行符使 fgets 停止读取,但它被视为有效字符,因此包含在复制到 str 的字符串中。

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

© www.soinside.com 2019 - 2024. All rights reserved.