1

今天看了一篇名为“a bug of fread?”的博文,没找到原因,就贴在这里,等哪位高手。

首先,程序的目的是读取文件(readme.txt)并打印内容,我用Visual Studio 2010对其进行了测试。

自述文件的内容是:

1234;
abcd;
ABCD;

自述文件的十六进制值为:

31 32 33 34 3b 0d 0a 61 62 63 64 3b 0d 0a 41 42 43 44 3b

这是代码:

#include <stdio.h>
#include <string.h>

#define BUF_SIZE 1024

int main()
{
    FILE *fp = NULL;
    int rcnt = 0;

    char rbuf[BUF_SIZE];

    fp = fopen("readme.txt", "r");
    if (NULL == fp)
    {
        printf("fopen error.\n");
        return -1;
    }

    printf("--------------------------\n");
    memset(rbuf, 0, BUF_SIZE);
    fseek(fp, 0, SEEK_SET);
    rcnt = fread(rbuf, 1, BUF_SIZE, fp);
    printf("read cnt = %d\n", rcnt);
    printf("%s\n", rbuf);

    return 0;
}

这样一个简单的代码,预期的结果是:

--------------------------
read cnt = 17
1234;
abcd;
ABCD;

总共 17 个计数包括 15 个字符和 2 个“\n”。
但我得到了以下结果:

--------------------------
read cnt = 17
1234;
abcd;
ABCD;D;

PS:如果用“rb”调用fopen函数,或者如果将宏BUF_SIZE定义得更小,我得到了正确的结果。

4

2 回答 2

1

fread()不返回 NUL 终止的字符串,但printf("%s")要求 NUL 终止的字符串。

您必须在读取缓冲区的末尾添加一个 '\0' : rbuf[rcnt] = '\0'。并记住读取比缓冲区大小少一个字节,以便为 NUL 字节留出空间。

于 2012-12-20T14:34:29.963 回答
0

我认为将二进制读取 API 与文本文件一起使用fread()是错误的。默认模式(如果你只是说)是文本。"r"

请注意,FILE *文本模式下的 I/O 通常会进行行终止转换,因此您可以假装行\n以实际上可能以物理结尾的方式结束\r\n(就像您的那样)。

这种转换可能会在某处引入混乱;这就是为什么切换到二进制模式使其再次工作的原因,因为在二进制模式下不会发生这种转换。

于 2012-12-20T14:30:18.437 回答