文件结束判定与feof函数
目录
文件结束判定:
方法1 :fget()函数返回EOF
方法2 :fgets()返回NULL
方法3 : 利用文件长度
方法4 : 二进制文件利用fread()返回值
feof函数
方法5:利用feof函数判断
EOF(End of file)是C/C++里面的宏定义,具体定义式是#define EOF-1
EOF是文件结束标志
但是,EOF并不是真实存在于文件末尾的一个数据, 若读取到文件末尾的时候, 即没有数据可供读取的时候, 读文件函数fgetc就会返回EOF值。(fgets函数会返回NULL)
所以判断文件是否到末尾可以利用函数的返回值, 例如:
方法1 :fget()函数返回EOF
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
int count = 0;
if ((fp = fopen("test2.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
while (fgetc(fp)!=EOF) {
count++;
}
printf("%d\n", count);
system("pause");
return 0;
}可以看到test2.txt有10个字符, 循环次数也是10


这种方法可以判定文件是否结束, 但需要不停地循环调用函数, 在执行效率较低
方法2 :fgets()返回NULL
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
int i;
char str1[4];
char str2[4];
char str3[4];
char str4[4];
char* str[4] = { str1,str2,str3,str4 };
if ((fp = fopen("test2.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
for (i = 0; fgets(str[i], 4, fp) != NULL; ++i) {
printf("str%d : %s\n", i + 1, str[i]);
}
printf("i = %d\n", i);
system("pause");
return 0;
}可以看到10个字符,fgets函数一次读三个字符, 读了四次完成, 读到文件末尾返回NULL

方法3 : 利用文件长度
利用fseek(), ftell()函数计算出文件长度(大小)
链接: fseek()和ftell()函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
int n;
char str[12] = { 0 };
if ((fp = fopen("test2.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
//
fseek(fp, 0, 2);//fp到文件末尾
n = ftell(fp);//fp到文件开头的偏移量, 这里就是文件长度
rewind(fp);//fp重新指向文件开头
//
for (int i = 0; ftell(fp) != n; ++i) {
str[i] = fgetc(fp);
}
printf("str : %s\n", str);
system("pause");
return 0;
}

方法4 : 二进制文件利用fread()返回值
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define SIZE 5
int main() {
FILE* fp;
double arr[SIZE] = { 1.1,2.2,3.3,4.4,5.5 };
double num;
if ((fp = fopen("test3.txt", "wb")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
fwrite(arr, sizeof(arr[0]), SIZE, fp);
fclose(fp);
fp = NULL;
if ((fp = fopen("test3.txt", "rb")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
while (fread(&num, sizeof(arr[0]), 1, fp)) {
printf("%.1f\n", num);
}
fclose(fp);
system("pause");
return 0;
}fread()函数会返回读取成功的个数, fread(&num, sizeof(arr[0]), 1, fp)中每次读取1个字节长为sizeof(arr[0])的数据, 若成功则返回返回成功的个数1, 若失败也就是成功0个, 返回0

feof函数
定义于头文件 <stdio.h>
int feof( FILE *stream )
检查是否已抵达给定文件流的结尾
当文件读取结束时, 若是遇到文件尾结束,则返回注意 : 在文件读取过程中,不能用feof函数的返回值直接用来判断是否遇到末尾结束。但可以用于当文件读取结束的时候,判断是读取失败结束(返回0值),还是遇到文件尾结束(返回非0值)。
即, 文件读取结束后, feof才能判断, 所以我们不能在进行读取文件时, 直接用feof()当做条件来判断,
我们来看下面几个例子 :
1.feof的经典错误
文件test1.txt为空
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
if ((fp = fopen("test1.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
if (feof(fp)) {
printf("test1.txt为空\n");
}
else {
printf("test1.txt不为空\n");
}
system("pause");
return 0;
}feof函数如果可以之间判断是否到文件尾, 应该会输出test1.txt为空, 结果却不是, 结果如图:
但如果我们在用feof()函数之前加上一个语句fgetc(fp)就会出现正确结果
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
if ((fp = fopen("test1.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
fgetc(fp);
if (feof(fp)) {
printf("test1.txt为空\n");
}
else {
printf("test1.txt不为空\n");
}
system("pause");
return 0;
}结果如图 :

我们再来看,test2.txt 如图 :
我们来看这段代码,
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
int count = 0;
if ((fp = fopen("test2.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
while (!feof(fp)) {
fgetc(fp);
printf("%d\t", ++count);
}
system("pause");
return 0;
}test2中共有10个字符, 结果应该输出 1 2 3 4 5 6 7 8 9 10, 循环十次. 实则不然, 循环了11次, 如图:
我们再来看
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
int n;
if ((fp = fopen("test2.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
while (! (n = feof(fp))) {
printf("feof(fp)=%d, ", n);
printf("%d\n", fgetc(fp));
}
printf("feof(fp)=%d", n);
system("pause");
return 0;
}运行结果如图, 输出feof的返回值和字符的ASCII码, 当fgetc读到文件末尾时返回EOF(-1), 此时 feof返回值为-1(非0)
通过这几段代码我们发现 , feof()是在别的函数读取到文件末尾后继续读取失败后才做出的文件读取结束的判断
我们可以这样来解决这个问题, 如以下代码:
方法5:利用feof函数判断
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
char c;
if ((fp = fopen("test2.txt", "r")) == NULL) {
printf("error\n");
system("pause");
return 0;
}
c = fgetc(fp);
while (! feof(fp)) {
printf("%c %d\n", c, c);
c = fgetc(fp);
}
system("pause");
return 0;
}运行结果如图 , 实际是c读取了-1的值但并未输出 .

目前就理解到这, 感觉并不是大彻大悟, 以后有新的理解再补充吧