当我尝试使用 fread()将文件复制到字符串时,我从文件中获取额外的字符,这与新行的数量完全相同。 这是我的代码:
#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
我看到了其他一些测试用例。在每个测试用例中,额外的字符数始终是新行的数量
我有几个问题:
为什么这种模式是这样的呢?
- 这是否与新行在窗口中占用2个字节这一事实有关?
- 如何摆脱那些额外的角色?
我搜索了类似的问题,但没有找到答案。请有人解释一下吗?
答案 0 :(得分:2)
在以文本模式打开的流上调用ftell,例如在您的示例中没有意义 1 。
函数fread
的用法不正确,size和count参数被切换。这意味着读取始终是部分的,因为您的文件中没有5000000个字符。因此,调用后数组中元素的值具有不确定的 2 值。 (在您的情况下,逻辑元素是一个大小为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
表示 3 ,最后加一个换行符。
1 (引用自:ISO:IEC 9899:201x 7.21.9.4 ftell功能2)
对于文本流,其文件位置指示符包含未指定
信息,可由fseek函数用于返回文件位置指示符
在ftell电话时流到它的位置;两个这样的区别
返回值不一定是写入或读取的字符数的有意义的度量。
2 (引自:ISO:IEC 9899:201x 7.21.8.1 fread功能2)
如果读取了部分元素,则其值是不确定的。
3 在Windows文件中,换行符由两个字符表示:13,10。回车符和换行符。但是当以文本模式阅读文件时,换行符始终只是换行符:10。由于程序的行为没有意义,因此您看到了字符13。如果您(正确地)打开并以二进制模式读取文件,您将看到由两个字符表示的换行符。
答案 1 :(得分:-1)
如果您正在使用Windows并使用某个编辑器编辑文件in.txt,该编辑器将CR-LF(回车,LINE-FEED)((ASCII)13,10)附加到每个换行符,这肯定会发生。尝试通过程序编写in.txt然后阅读它。这将按预期进行。或者使用没有将CR-LF附加到eol(行尾)的编辑器。抱歉,我不知道没有这样的编辑器[但是有些Linux编辑器会工作。]。