前言
在文件操作函数(二)中,我们介绍了一系列的与文件的顺序读写有关的函数,它们调用成功与失败时的返回值各不相同,为了能更好地记忆这些函数,我们将这些函数的返回值进行了总结,并列入表格:
函数 | 调用成功时的返回值 | 调用失败时的返回值 |
---|---|---|
fputc | 返回输出字符的ASCII码值 | EOF |
fgetc | 返回输入字符的ASCII码值 | EOF |
fputs | 非负值 | EOF |
fpets | 返回输入字符串的首地址 | NULL |
fprintf | 返回输出的字节个数 | 负值 |
fscanf | 成功转换和分配的字段数 | EOF |
fwrite | 要求写入的完整项的数目 | 小于要求写入的完整项的数目 |
fread | 要求读取的完整项的数目 | 小于要求读取的完整项的数目 |
这样一一列举出来后,看似已经非常清楚明了,实际却还有一些小细节:
- fgetc函数返回EOF时,可能是读取数据时发生错误,也可能是已经读取到文件末尾了。
- fgets函数返回NULL时,可能是读取数据时发生错误,也可能是已经读取到文件末尾了。
- fscanf函数返回EOF时,可能是读取数据时发生错误,也可能是在第一次转换之前到达文件流的末尾。
- fread函数返回的值小于要求读取的完整项的数目时,可能是读取数据时发生错误,也可能是在达到读取的规定数目之前遇到文件结尾。
这些不同的情况返回的却是同一个值,当fgetc函数返回EOF时,我们不能断定一定是读取数据时发生错误了,当fscanf函数返回EOF时,我们也不能断定它就是文件读取结束了。所以,出现了一类函数,它们的功能就是,判断文件操作函数是以一种什么方式结束。
注意:以下介绍的函数的功能不是判断文件操作函数是否调用失败,而是在文件操作函数已经调用失败的情况下,判断文件操作函数调用失败的原因。
ferror函数
int ferror( FILE *stream );
ferror函数的功能就是判断使用某一文件指针的过程中,是否发生错误,若使用时没有发生错误,则ferror函数返回0;否则,ferror函数将返回一个非零的值。调用ferror函数时,我们只需将待检查的文件指针传入即可。
if (ferror)
{
printf("文件指针使用时,发生错误\n");
}
feof函数
int feof( FILE *stream );
feof函数的功能也是判断使用某一文件指针的过程中,是否读取到文件末尾,若使用时没有读取到文件末尾,则feof函数返回0;否则,feof函数将返回一个非零的值。调用feof函数时,也只需将待检查的文件指针传入即可。
if (feof(pf))
{
printf("文件指针使用时,读取到文件末尾\n");
}
ferror函数和feof函数搭配使用
当前言中说到的文件操作函数调用失败时,我们就可以同时运用ferror函数和feof函数,来判断文件操作函数调用失败的准确原因。
例如,文件data.txt文件中的数据为"abcdef",我们要用fgetc函数读取data.txt文件中的数据,当数据读取完之后,我们就可以用ferror函数和feof函数,来判断最后一次fgetc函数调用失败的原因:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//读取文件中的数据
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c", ch);
}
if (ferror(pf))
{
printf("文件指针使用时,发生错误而结束\n");
}
else if (feof(pf))
{
printf("文件指针使用时,读取到文件末尾而结束\n");
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}