21

即使已经达到 EOF, fgets() 是否总是以 \0 终止字符缓冲区?看起来确实如此(在 ANSI K&R 书中介绍的实现中确实如此),但我想我会要求确定。

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

编辑:我知道 \0 在“正常”情况下附加,我的问题是针对 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);
}
4

5 回答 5

15

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

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

于 2009-11-02T09:38:50.647 回答
8

永远不要使用gets!!

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

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

如果fgets()返回 NULL,则目标数组可能已更改并且可能没有空字符。从fgets().


添加了编辑示例

$ 猫 fgets_error.c
#include <stdio.h>

无效 print_buf(char *buf, size_t len) {
  诠释 k;
  printf("%02X", buf[0]);
  for (k=1; k<len; k++) printf(" %02X", buf[k]);
}

诠释主要(无效){
  字符 buf[3] = {1, 1, 1};
  字符 *r;

  printf("输入 CTRL+D:");
  fflush(标准输出);
  r = fgets(buf, sizeof buf, stdin);
  printf("\nfgets 返回 %p, buf 有 [", (void*)r);
  print_buf(buf, 大小的 buf);
  printf("]\n");

  返回0;
}
$ ./a.out
输入 CTRL+D:
fgets 返回 (nil), buf 有 [01 01 01]
$

看?buf 中没有 NUL :)

于 2009-11-02T09:42:36.593 回答
4

人 fgets:

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

于 2009-11-02T09:42:26.543 回答
2

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


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';
    }
}
于 2015-08-15T11:54:54.017 回答
1

是的,它确实。来自CPlusPlus.com

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

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

在读取的字符之后会在 str 中自动附加一个空字符,以表示 C 字符串的结束。

于 2009-11-02T09:38:34.743 回答