一. C 中的 ferror()
函数
在 C 语言中,ferror()
是一个内置函数,用于在文件操作期间检查文件是否发生错误。它提供了一种简单的方法,在你的 C 程序中进行文件操作时不会中断。
1.ferror 语法
ferror()
是一个标准库函数,定义在头文件 <stdio.h>
中。
c
ferror(fptr)
**参数:**
接收一个文件流指针作为参数。
**返回值:**
- 如果文件有错误,返回一个非零值。
- 否则,返回 0。
**注意:** 要使用 `ferror()` 检查文件错误,文件必须先打开。
2.ferror()
的示例
示例 1:写入数据时检查错误
c
#include <stdio.h>
int main() {
FILE *fptr = fopen("gfg.txt", "w");
// 向文件写入数据
fprintf(fptr, "Hello, GFG!");
// 写入后检查是否有错误
if (ferror(fptr) == 0)
printf("数据写入成功。");
fclose(fptr);
return 0;
}
输出:
数据写入成功。
示例 2:读取数据时检查错误
c
#include <stdio.h>
int main() {
FILE *fptr = fopen("gfg.txt", "w+");
fprintf(fptr, "GeeksForGeeks!");
rewind(fptr);
char d[14];
while (fscanf(fptr, "%s", d) != EOF)
// 读取后检查是否有错误
if (ferror(fptr) == 0) {
for (int i = 0; i < sizeof(d); i++) {
printf("%c", d[i]);
}
printf("\n没有错误,数据读取成功");
}
fclose(fptr);
return 0;
}
输出:
GeeksForGeeks!
没有错误,数据读取成功
二. C 中的 EOF
、getc()
和 feof()
1.什么是 EOF
?
在 C 中,EOF
是一个常量宏,定义在头文件 <stdio.h>
中,用于表示文件结束。它被多个文件读取函数使用,比如 fread()
、gets()
、getc()
等。 EOF
的值是由实现定义的,但通常是 -1
。
2.getc()
函数
getc()
函数用于从给定的文件流中读取一个字符。它是以宏的形式在 <stdio.h>
中实现的。
语法:
c
getc(fptr);
#### 参数:
- `fptr`:指向要读取数据的文件流的指针。
#### 返回值:
- 返回从文件流中读取的字符。
- 如果发生错误或到达文件末尾,返回 `EOF`。
3.feof()
函数
feof()
函数用于检查文件指针是否指向文件末尾。如果到达文件末尾,它返回一个非零值;否则返回 0。
语法:
c
feof(fptr);
#### 参数:
- `fptr`:指向要读取数据的文件流的指针。
#### 返回值:
- 如果到达文件末尾,返回非零值(通常是 1)。
- 否则返回 0。
4.为什么需要 feof()
?
getc()
在到达文件末尾时会返回 EOF
,但它在读取失败时也会返回 EOF
。因此,仅靠比较 getc()
的返回值和 EOF
并不足以判断是否真的到了文件末尾。为了解决这个问题,C 提供了 feof()
函数。
示例 1:无法区分错误还是文件结束
c
#include <stdio.h>
int main() {
FILE *fptr = fopen("file.txt", "w");
char ch;
// 尝试用 getc() 读取一个字符
ch = getc(fptr);
// 处理 EOF 返回值
if (ch == EOF)
printf("文件结束或无法读取");
else
printf("读取的字符:%c", ch);
fclose(fptr);
return 0;
}
输出:
文件结束或无法读取
在上述程序中,文件是以"只写"模式打开的,
getc()
无法读取数据,但它仍然返回EOF
,这使得我们难以判断错误的来源。此时可以使用feof()
来明确判断是否到达文件末尾。
示例 2:使用 feof()
明确判断文件结束
c
#include <stdio.h>
int main() {
FILE *fptr = fopen("file.txt", "w");
char ch;
// 尝试用 getc() 读取一个字符
ch = getc(fptr);
// 处理 EOF 返回值
if (ch == EOF) {
// 检查是文件结束,还是读取失败
if (feof(fptr))
printf("文件结束");
else
printf("无法读取");
} else
printf("读取的字符:%c", ch);
fclose(fptr);
return 0;
}
输出:
无法读取
三. C 中的 clearerr()
函数
在 C 语言中,文件操作中的错误可以通过 ferror()
和 feof()
函数来检测。但这些错误标志一旦设置就会一直保留 ,直到被显式清除。clearerr()
是一个标准库函数,用于在你进行文件读写操作时手动清除这些错误标志。
语法 : clearerr()
是定义在头文件 <stdio.h>
中的标准库函数。
c
clearerr(fptr);
#### 参数:
- `fptr`:指向文件流的文件指针。
#### 返回值:
- 该函数**没有返回值**(`void`)。
示例 1:
c
#include <stdio.h>
int main() {
FILE *fptr = fopen("gfg.text", "rw+");
// 清除错误和 EOF 标志
clearerr(fptr);
if (!feof(fptr))
printf("EOF 重置成功");
return 0;
}
输出:
EOF 重置成功
示例 2:清除 EOF 标志的实际用法
c
#include <stdio.h>
int main() {
FILE *fptr = fopen("gfg.txt", "w+");
fprintf(fptr, "GeeksForGeeks!");
// 不断读取直到遇到 EOF
while (fgetc(fptr) != EOF);
if (feof(fptr)) {
printf("遇到 EOF\n");
}
// 使用 clearerr() 清除 EOF 标志
clearerr(fptr);
if (!feof(fptr)) {
printf("EOF 已成功重置");
}
fclose(fptr);
return 0;
}
输出:
遇到 EOF
EOF 已成功重置
总结:
clearerr()
用于清除文件流的错误标志和 EOF 标志。- 它不会返回任何值,只是重置状态。
- 常用于重复读写文件 或调试文件操作时。
四. C 语言文件操作中的错误处理
文件操作是 C 编程中的常见任务,但可能遇到各种错误,需要优雅地处理。良好的错误处理能让程序在面对"文件缺失""权限不足"等突发情况时不至于崩溃。本文将学习如何在 C 语言文件操作中处理这些常见错误。
常见文件操作错误一览
错误 | 原因 |
---|---|
文件未找到 | 试图打开一个不存在的文件 |
权限被拒绝 | 对文件访问权限不足 |
磁盘已满 | 写入时磁盘空间耗尽 |
文件已存在 | 用 "w" 模式创建已存在的文件 |
无效文件指针 | 使用 NULL 或非法 FILE* 进行读写 |
已到文件尾 (EOF) | 读操作越过文件末尾 |
文件未打开 | 在未成功打开的文件上继续操作 |
若不做错误检查,程序可能出现异常行为:提前终止或输出错误结果。
错误处理技巧(不一定非要这么处理,只是简单建议,要灵活处理)
1. 处理 "文件未找到"
以只读 "r" 或追加 "a" 模式打开文件时,若文件不存在,fopen 返回 NULL。用 perror 打印系统提示。
c
#include <stdio.h>
int main(void) {
FILE *file = fopen("file.txt", "r");
if (file == NULL) {
perror("Error");
return 1;
}
fclose(file);
return 0;
}
输出:
Error: No such file or directory
2. 处理 "权限被拒绝"
文件存在但无权限时,fopen 同样返回 NULL,perror 会输出 "Permission denied"。
c
FILE *file = fopen("/restricted/file.txt", "w");
if (file == NULL) {
perror("Permission denied");
}
3. 处理 "磁盘已满"
写入后通过 ferror 检测流错误。
c
#include <stdio.h>
int main(void) {
FILE *fptr = fopen("file.txt", "w");
if (fptr == NULL) {
perror("Error opening file");
return 1;
}
fprintf(fptr, "Writing to file");
if (ferror(fptr)) {
perror("Error writing to file");
}
fclose(fptr);
return 0;
}
输出示例:
Error writing to file: Permission denied
4. 处理 "文件已存在"
用 "wx" 模式创建新文件;若文件已存在,fopen 返回 NULL 并置 errno 为 EEXIST。
c
#include <stdio.h>
#include <errno.h>
int main(void) {
FILE *fptr = fopen("test.text", "wx");
if (fptr == NULL) {
if (errno == EEXIST)
printf("File already exist\n");
return 1;
}
fprintf(fptr, "This is a new file.");
fclose(fptr);
return 0;
}
输出:
File already exist
5. 处理 "无效文件指针"
任何读写前都先判断指针是否为 NULL。
c
FILE *file = NULL;
if (file == NULL) {
printf("Invalid file pointer. File operations cannot proceed.\n");
}
6. 处理 "已到文件尾 (EOF)"
读取时用 feof 区分"正常读完"与"读取出错"。
c
#include <stdio.h>
int main(void) {
FILE *file = fopen("test.txt", "r");
int ch;
while ((ch = fgetc(file)) != EOF)
putchar(ch);
if (feof(file))
printf("End of file reached.");
else if (ferror(file))
printf("Error reading the file.");
fclose(file);
return 0;
}
输出:
End of file reached.
7. 处理 "文件未打开"
fopen 返回 NULL 即表示打开失败,直接判断即可。
c
#include <stdio.h>
int main(void) {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
printf("File could not be opened.\n");
} else {
printf("File opened successfully.\n");
fclose(file);
}
return 0;
}
输出:
File could not be opened.
8. 处理 "关闭文件失败"
fclose 返回 -1 表示关闭出错。
c
#include <stdio.h>
int main(void) {
FILE *fptr = fopen("test.txt", "w");
fprintf(fptr, "Writing to file");
if (fclose(fptr) == -1)
printf("File closing error");
else
printf("File closed");
return 0;
}
输出:
File closing error