C中的 feof() 和 EOF
以linux平台下的vim创建的文件为例,当读取指定文件中的内容时,文件的格式为:
内容+EOF
其中 EOF为vim文件内容的结束标志。
每当用C语言读取文件内容时,文件指针要指向字符EOF之后才能判断文件已经结束。所以EOF内容会被读取,读取到的EOF通常会给我们带来困扰,如输出时会多输出一行。
为了解决多读取的EOF字符(在文件中不可见),我们用一个小小的逻辑算法来避免EOF字符带来的困惑,如打印读取的文件内容时不将读取到的EOF字符输出,或避免在读取到EOF字符(读取此字符不成功)后无判断文件是否结束的操作而又将上一次读取到的数据输出。
1.文件指针 文件内容
如data.in文件中的内容如下:
12345678
23456789
那么当用指针打开此文件并用相关的C语言文件操作函数来读取这个文件时,C语言文件指针执行过程(移位)如下:
- 当打开文件时,文件指针指向文件中的第一个字符
如FILE *fp = fopen("data.in", "r");要是打开data.in文件成功之后,文件指针fp就会指向文件中的第一个字符:'1'。
- 每根据 要求(读一个字符,一行字符串等) 读取一次文件内容时,文件指针将指向下一个(临近)的字符。
如data.in中的内容,此时用fgets(ar, 100, fp);语句后(读取文件中的一行字符串),文件指针将指向下一行的字符:'2'
- 当文件指针指向EOF时,并不会认为文件内容已经结束。当指针指向EOF后一位时(把EOF读取后),此时文件内容才算结束。
如在data.in中,把字符'9'成功读取后,文件指针指向EOF字符。此时若判断文件是否结束,则不为结束;只有把EOF字符读取之后(文件指针指向EOF后时),再判断文件是否结束时,才会判断为结束。
2.正确使用feof()
#include <stdio.h>
#define SIZE 100
#define FILENAME "data.in"
int main(void)
{
int ln;
FILE *fp;
char ar[SIZE];
ln = 0;
if( (fp = fopen(FILENAME, "r") ) == NULL){
printf("Can not open file: %s\n", FILENAME);
return -1;
}
while( !feof(fp) ){
fgets(ar, SIZE, fp);
//If read EOF,
//Do not record the line`s number,
//Do not print the content to screen
if( feof(fp) ){
break;
}
ln++;
printf("%s", ar);
}
printf("The file`s line is %d\n", ln);
fclose(fp);
return 0;
}
这是一个打开与本源程序在同一个目录下叫data.in文件的程序。并读取data.in中的全部内容,并统计行数。
data.in中的内容如1中所述。
编译、运行此程序后的结果为:
12345678
23456789
The file`s line is 2
分析结果:
(1)此程序将data.in中可见内容照样输出(用fgets函数读取文件内容时,ar数组已经包含回车符,故不需要在printf打印语句中再添加回车),并正确统计了其内容行数。
(2)能正确将文件内容输出的关键语句是"if( feof(fp) ){break;}"需要将此语句加在"行数自增,打印行内容(ln++;printf("%s", ar))"语句之前。
3.非正确使用feof()
若将2中代码中的"if( feof(fp) ){break;}"语句去掉或者是写到"ln++;printf("%s", ar)"之后,则程序将不会得到预期效果。
a.将2中代码中的"if( feof(fp) ){break;}"语句去屏蔽,再编译运行程序得到结果:
12345678
23456789
23456789
The file`s line is 3
b.将将2中代码中的"if( feof(fp) ){break;}"语句写到"ln++;printf("%s", ar)"语句之后,再编译运行程序得到结果:
12345678
23456789
23456789
The file`s line is 3
分析结果:
造成a,b结果的原因在于:当读取EOF字符时,文件指针已经指向EOF之后,但此时没有进行读取文件内容是否结束的判断,从而没有进一步中断while循环,使fgets()函数读取EOF字符读取失败(不能讲字符EOF读入到数组ar中),从而ar数组里面的内容还是上一次读取的内容。所以当输出ar时,ar的值为上一次字符串值,并且ln++语句得以执行。故而是多输出文件中最后一行数据的结果!
总结:
在用非手动输入数据的程序手段进行数据的获取时(如读文件时,需要结合文件内容格式和相应函数功能(操作过程)来获取准确的数据)。有时候一字符只差,全程序皆输也!
Note Over。
更多推荐
所有评论(0)