目录
1 检查或复位状态简介
2 feof()函数
2.1 feof()函数简介
2.2 示例程序
3 ferror()函数
4 clearerr()函数
4.1 clearerr()函数简介
4.2 示例程序
1 检查或复位状态简介
调用 fread()
函数读取数据时,如果返回值小于参数 nmemb
所指定的值,这通常意味着发生了两种情况之一:要么是读取过程中遇到了文件末尾(end-of-file,EOF),要么是发生了某种错误。然而,fread()
函数本身并不提供足够的信息来区分这两种情况。有几种方法确定具体的原因:
- 一种方法是检查错误标志,这可以通过调用
ferror()
函数实现,它会返回一个非零值如果文件流遇到了错误。 - 另一种方法是检查文件结束标志,这可以通过调用
feof()
函数来完成,它会在到达文件末尾时返回一个非零值。
通过结合使用 ferror()
和 feof()
函数,可以更准确地判断 fread()
返回较小值的具体原因,从而采取相应的处理措施。
2 feof()函数
2.1 feof()函数简介
feof()
函数是 C 语言标准库中的一个函数,用于检查文件流是否已到达文件末尾(end-of-file,EOF)。当从文件中读取数据时,如果已经读取到文件的最后,feof()
函数可以用来确定是否还有更多的数据可以读取。函数原型如下:
int feof(FILE *stream);
- 参数:
stream
是指向FILE
结构的指针,该结构代表了要检查的文件流。 - 函数返回值:如果文件流已经到达文件末尾,返回非零值(通常是 1),如果文件流还没有到达文件末尾,返回 0。
2.2 示例程序
下面的代码实现了检测文件的读写位置是否移动到了文件末尾,并逐个字符打印。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *readFile, *writeFile;
char buffer[256];
const char *filename = "example.txt"; // 临时文件名
// 打开文件以写入
writeFile = fopen(filename, "w"); // 以文本写入模式打开文件
if (writeFile == NULL) {
perror("Error opening file for writing");
return EXIT_FAILURE;
}
// 提示用户输入文本
printf("Enter your text (max 1024 characters): ");
fgets(buffer, sizeof(buffer), stdin); // 从标准输入读取一行文本
// 写入文本到文件
fputs(buffer, writeFile);
// 关闭写入文件
fclose(writeFile);
// 打开同一个文件以读取
readFile = fopen(filename, "r"); // 以文本读取模式打开文件
if (readFile == NULL) {
perror("Error opening file for reading");
return EXIT_FAILURE;
}
// 循环读取文件,直到到达文件末尾
while (!feof(readFile)) {
int ch = fgetc(readFile); // 逐个字符读取
if (ch != EOF) {
printf("%c\n", ch); // 打印读取的字符
} else {
break; // 如果到达文件末尾或读取失败,退出循环
}
}
// 检查是否有错误发生
if (ferror(readFile) != 0) {
perror("Error reading file");
}
// 关闭读取文件
fclose(readFile);
return EXIT_SUCCESS;
}
首先以文本写入模式打开(或创建)一个名为 "example.txt" 的文件,并将用户输入的文本存储到该文件中。接着,程序使用 feof()
函数检测是否到达文件末尾,并使用 fgetc()
函数逐个字符地读取文件内容,每个字符后跟一个换行符打印到标准输出。最后通过ferror()
函数来检查错误状态并关闭读取的文件。程序运行的结果如下:
3 ferror()函数
上面的示例程序中提到了库函数 ferror(),ferror()函数用于测试参数 stream 所指文件的错误标志,如果错误标志被设置了,则调用 ferror()函数将返回一个非零值,如果错误标志没有被设置,则返回 0。其函数原型如下所示:
#include <stdio.h>
int ferror(FILE *stream);
4 clearerr()函数
4.1 clearerr()函数简介
库函数 clearerr()用于清除 end-of-file 标志和错误标志,当调用 feof()或 ferror()校验这些标志后,通常需要清除这些标志,避免下次校验时使用到的是上一次设置的值,此时可以手动调用 clearerr()函数清除标志。函数原型如下:
void clearerr(FILE *stream);
使用场景:当你检测到文件流有错误(通过 ferror(stream)
)或到达文件末尾(通过 feof(stream)
)后,如果还想继续从该流中读取或写入数据,你可以使用 clearerr()
来清除这些标志。这通常在你解决或忽略了错误,并希望继续处理文件时使用。
4.2 示例程序
下面的代码实现了利用clearerr()
函数清除文件流 fileStream
的 EOF 标志和错误标志。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fileStream = NULL; // 更具描述性的变量名
const char *filename = "example.txt"; // 临时文件名
char buffer[20] = {0}; // 使用 buffer 替代 buf,更清晰地表达用途
/* 打开文件 */
if (NULL == (fileStream = fopen(filename, "w"))) {
perror("Error opening file");
exit(EXIT_FAILURE); // 使用 EXIT_FAILURE 宏替代 -1
}
printf("File opened successfully!\n");
/* 移动读写位置到文件末尾 */
if (0 > fseek(fileStream, 0, SEEK_END)) {
perror("Error seeking to end of file");
fclose(fileStream);
exit(EXIT_FAILURE);
}
/* 读取文件 */
if (fread(buffer, 1, 10, fileStream) < 10) { // 检查是否成功读取 10 个字符
if (feof(fileStream)) {
printf("End-of-file flag is set, reached the end of file!\n");
} else {
perror("Error reading file");
}
clearerr(fileStream); // 清除 EOF 或错误标志
}
/* 关闭文件 */
fclose(fileStream);
exit(EXIT_SUCCESS); // 使用 EXIT_SUCCESS 宏替代 0
}
首先尝试以写入模式打开一个文件,然后将文件指针移动到文件末尾。接着读取文件,如果读取的字节少于预期,它将检查是否到达文件末尾或发生错误。clearerr(fileStream);
这行代码用于清除文件流 fileStream
的 EOF 标志和错误标志,使得后续操作可以继续在文件流上进行,而不受之前错误或 EOF 状态的影响。最后,代码关闭文件并正常退出。运行的结果如下: