嵌入式Linux系统编程 — 2.2 标准I/O库:检查或复位状态

目录

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 状态的影响。最后,代码关闭文件并正常退出。运行的结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

几度春风里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值