说明:
EOF是文本文件结束的标志。在文本文件中,数据是以字符的ASCⅡ代码值的形式存放,普通字符的ASCⅡ代码的范围是32到127(十进制),EOF的16进制代码为0xFF(十进制为-1),因此可以用EOF作为文件结束标志。当把数据以二进制形式存放到文件中时,就会有-1值的出现,因此不能采用EOF作为二进制文件的结束标志。为解决这一个问题,ASCIC提供了feof( )函数,用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。feof(fp)如果文件结束则返回非0值,否则返回0,文件结束符只能被clearerr( )清除。
在C语言中有feof()函数,在VC数据库中有C++的eof()函数,二者作用一样,但是运作方式确实完全不同的。数据库中“eof( )”函数读取当前指针的位置,“C”语言的“feof( )”函数返回的是最后一次“读操作的内容”。“位置和内容”不能相混!
feof()多读出一次数据的解决办法:
将
while(!feof(fp)){
p = (Node*)malloc(sizeof(Node));
fscanf(fp,"%s",p->data); //读取数据
p->next = tail->next; //插入链表
tail->next = p;
tail = p;
p = NULL;
free(p);
}
改为
while(1){
//if(foef(fp)) break; //在fscanf之前判断,还是会多读一次数据到链表中
p = (Node*)malloc(sizeof(Node));
fscanf(fp,"%s",p->data); //读取数据
if(foef(fp)) break; //fscanf读取到EOF后文件读取指针移动到EOF尾部,数据为空,结束将数据插入链表
p->next = tail->next; //将数据插入链表
tail->next = p;
tail = p;
p = NULL;
free(p);
}
分析:为什么要在fscanf之后判断?
注意:这样的方法并没有改变feof(fp)对文件数据多一次的读取,仅仅是结束了多读数据的插入。因为并没有可以阻止feof(fp)多读一次的方法,这个函数本就是以读取为空时判断文件末尾的,在文件读取指针移动到文件末尾之前必须读取EOF标志。而读取EOF时,由于 feof( ) 是以读取数据是否为空(是否读取成功)来判断文件结尾的,此时的EOF也能读取成功,而EOF对p->data的赋值是失败的, fscaf( ) 返回-1。因此加入链表后的此结点的数据为默认值。
提示:(用VC 默认的Debug配置编译时,申请而未初始化的代码每个字节全部被赋为:0xCC。在汉字国标码GB-2312中,0xCCCC代表“屯”这个字,所以当显示unicode的程序显示这些未初始化的内存时就会是“屯”这个字 )
因为fscanf读取数据了EOF,文件位置指针移动到EOF之后,此时再用if(foef(fp)) 判断便没有数据,立即执行break。