为什么fread()在c中读取额外的'#newlines'字符?

问题描述:

虽然我试图使用fread()将文件复制到字符串中,但我从文件中获得了与新行数完全相同的额外字符。 这里是我的代码:为什么fread()在c中读取额外的'#newlines'字符?

#include <stdio.h> 
#include <stdlib.h> 
#define LEN 5000000 

int main() 
{ 
    char *in = (char*) malloc(LEN); 
    FILE *f=fopen("in.txt","r"); 
    fread(in,5000000,1,f); 
    printf("%ld\n", ftell(f)); 
    in[ftell(f)]=0; 
    int l; 
    for(l=0;true;l++) 
    { 
     if(in[l]<10) 
     break; 
     printf("%d ",in[l]); 
    } 
    printf("\n"); 
} 

输入此程序是:

1 
2 
<newline> 

链接,输入:https://paste.fedoraproject.org/388281/46780193/
对于输出我正在打印字符的ASCII值改为:

6 
49 10 50 10 13 10 

如果输入是:

1 
2 
3 
<newline> 

链接,输入:https://paste.fedoraproject.org/388280/
则输出为:人物

9 
49 10 50 10 51 10 51 13 10 

我看到一些其他的测试cases.In每个测试用例额外数量总是新的行数。我有几个问题:
- 为什么模式是这样的?
- 这是怎么回事,新行占用2个字节的窗口?
- 如何摆脱这些额外的字符?
我搜索了类似的问题,但没有找到答案。请解释一下?

+2

为什么?因为这正是文件中的内容。换行符('\ n')需要在那里表示一个*新行*。有很多方法可以摆脱换行符。最好的方法取决于你想要达到的目标。请参阅例如[从fgets()输入]中删除尾随换行符(请参见http://*.com/questions/2693776/removing-trailing-newline-character-from-fgets-input) – kaylum

+0

请显示文件的确切内容。 – 2501

+0

另外,为什么不使用'LEN',而是专门定义的,而不是在'fread()'调用中输入数字? – Magisch

在以文本模式打开的流上调用ftell(例如在您的示例中)无意义。

函数fread的用法不正确,大小和计数参数被切换。这意味着读取始终是部分的,因为您的文件中没有5000000个字符。因此,调用后数组中元素的值具有不确定的值。 (您的案例中的逻辑元素是大小为5000000的单个元素。)

您看到的结果没有意义。读取不确定的值可能导致未定义的行为。

阅读您的文件正确的方法是正确的参数传递给FREAD和使用返回值来确定成功读取字符数:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <assert.h> 

int main() 
{ 
    unsigned char in[500] = { 0 } ; 
    FILE *f=fopen("in.txt","r"); 
    assert(f) ; 

    const size_t read = fread(in,1,500,f); 
    printf("read: %zu\n" , read); 

    for(size_t index = 0 ; index < read ; index++) 
    { 
     printf("%hhu " , in[index]); 
    } 

    fclose(f); 
} 

使用这种正确的程序,当文件中有内容(点不是文件的一部分):

. 
1 
2 
3 

. 

将读取并打印正确的值:

read: 7 
49 10 50 10 51 10 10 

一个换行符,代表的值为10,对于每个数字,并且在结尾处增加一个换行符。


(引自:ISO:IEC 9899:201X 7.21.9.4的FTELL功能2)
对于文本流,它的文件位置指示器包含未指定 信息,由用于FSEEK功能可用将流的 的文件位置指示符返回到它在全部呼叫时的位置;两个这样的返回值之间的差异不一定是写入或读取的字符数量的有意义的度量。

(引自:ISO:IEC 9899:201X 7.21.8.1 fread函数2)
如果部分元件被读取时,它的值是不确定的。

在windows文件中,换行符由两个字符表示:13,10。回车符和换行符。但是当以文本模式阅读文件时,换行符总是换行符:10.由于程序的行为没有意义,因此您看到了字符13。如果(正确)打开并以二进制模式读取文件,则会看到由两个字符表示的换行符。

如果您使用的是Windows和编辑in.txt使用一些编辑器,附加CR-LF(回车,换行)((ASCII)13,10),以每个换行符这必将发生的文件。尝试通过程序编写in.txt然后阅读它。这将如预期般完成。或者使用不附加CR-LF的编辑器(行尾)。对不起,我不知道没有这样的编辑器[但是一些Linux编辑会工作。]。