每当用C语言读取文件内容时,文件指针要指向字符EOF之后才能判断文件已经结束。所以EOF内容会被读取,读取到的EOF通常会给我们带来困扰,如输出时会多输出一行。
为了解决多读取的EOF字符(在文件中不可见),我们用一个小小的逻辑算法来避免EOF字符带来的困惑,如打印读取的文件内容时不将读取到的EOF字符输出,或避免在读取到EOF字符(读取此字符不成功)后无判断文件是否结束的操作而又将上一次读取到的数据输出。
一、EOF (END OF FILE)是指文件的结束符,是一个宏定义。对于getchar(), 一般会返回一个我们键入的符号值。只有当遇到文本结束标记(ASC||码值==26)才会返回EOF。
假如有“data.txt"文件内容:
123456
456789
那么用指针打开此文件,指针的移动过程如下:
1.打开文件时,FILE指针指向文件里的第一个字符,比如打开"data.txt",指针会指向‘1‘。
2.每根据需要(读一个字符,一行字符串等 ) 读取一次文件内容时,文件指针将指向下一个(临近)的字符。
比如"data.txt"中的内容,用fgets(ar,50,fp);语句读取了一行字符串后,fp将指向‘4‘。// fgets可以从文件中读取一行字符串,存进先前定义的char数组里(如ar[50])。注意fget的格式。
3.当文件指针指向EOF时,并不会认为文件内容已经结束。当指针指向EOF后一位时(把EOF读取后),此时文件内容才算结束。
如在data.txt中,把字符‘9‘成功读取后,文件指针指向EOF字符。此时若判断文件是否结束,则不为结束;只有把EOF字符读取之后(文件指针指向EOF后时),再判断文件是否结束时,才会判断为结束。
二、feof()
能正确将文件内容输出的关键语句是 "if( feof(fp) ){break;}" 需要将此语句加在"行数自增,打印行内容(ln++;printf("%s", ar))"语句之前。见一个例子
1 while( !feof(fp) ){ 2 fgets(ar, SIZE, fp); //fgets()函数自带回车符 // fgets可以从文件中读取一行字符串,存进先前定义的char数组里(如ar[50])。注意fget的格式。 3 4 //If read EOF, 5 //Do not record the line`s number, 6 //Do not print the content to screen 7 if( feof(fp) ){ 8 break; 9 } 10 ln++; 11 printf("%s", ar); 12 }
假如把" if( feof(fp) ) {break;}" 放在printf语句后面,最后一行字符”456789“ 就会被打印两次,最终输出的行数则+1.
造成这种结果的原因在于:读取EOF字符时,FILE指针已经指向了EOF的后面,但这时没有判断 文件内容的读取 是否已结束,从而没有终止while循环,使fgets()函数读取EOF字符失败(不能说字符EOF被读入到数组ar中),因此ar数组里还是上一次读取的内容。所以会有这样的输出。
总结来说,feof(fp) 就是判断fp是否已经读取了EOF字符。如果已读取,返回true值,while将break。
主要笔记来源: https://blog.csdn.net/misskissc/article/details/8219979
P.S. 此外,EOF还可用于循环判断条件,如while(scanf("%d",&x)!=EOF) [等同于while(cin>>x)]
原文地址:https://www.cnblogs.com/CSbolgofmyown/p/8892743.html