Bootstrap

【C语言】处理文件错误:详解 strerror, perror, 和 fopen

🦄个人主页:小米里的大麦-CSDN博客

🎏所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html

⚙️操作环境:Visual Studio 2022

目录

一、引言

二、fopen 函数

解释:

1. 函数原型

2. 参数

3. 代码示例

三、strerror 函数

1. 函数原型

2. 参数

3. 代码示例

四、perror 函数

1. 函数原型

2. 参数

3. 代码示例

五、总的来说(可直接跳转至此处开始)

1. 错误处理的基础

errno 变量

strerror 函数

注意事项

2. 这里数据太多,所以我整理了常见的错误码及其描述:

3. 代码示例

3.1 示例一 

3.2 示例二 

4. 日常使用示例

六、总结

综合使用的重要性

七、共勉


一、引言

在 C 语言编程中,处理错误是非常重要的,尤其是当涉及到文件操作时。本文将详细介绍三个常用的错误处理函数:strerror, perror, 和 fopen 的使用方法。这些函数可以帮助开发者更好地理解和处理程序中发生的错误。

错误处理是编程中不可或缺的一部分。当程序遇到问题时,如文件无法打开或内存分配失败,程序需要能够捕捉这些错误并给出适当的反馈。C 语言提供了多种机制来处理这类错误,其中包括 strerrorperror 函数,它们可以提供详细的错误信息。

此外,我们还将讨论 fopen 函数,这是 C 语言中用于打开文件的标准函数。fopen 函数无法成功打开文件时,我们需要能够正确地处理这种失败,并向用户或开发者提供清晰的错误信息。

二、fopen 函数

解释:

  • fopen 是一个用于打开文件的标准库函数。它可以读取、写入或同时读写文件。如果文件不存在,fopen 可以创建新文件;如果文件存在,fopen 可以打开并重用它。
  • 即:fopen 是一个用于打开文件的函数,它可以在不同的模式下打开文件。如果我们尝试打开一个不存在的文件,或者因为权限问题无法打开文件,fopen 会返回 NULL。因此,我们通常会检查 fopen 的返回值是否为 NULL 来判断文件是否成功打开。

还是先来看看fopen - C++ Reference上的介绍:

1. 函数原型

#include <stdio.h>
FILE *fopen(const char *filename, const char *mode);

2. 参数

  • filename: 要打开的文件的路径和名称。
  • mode: 指定了打开文件的方式,常见的模式有 "r"(只读)、"w"(清空并写入新的数据)、"a"(追加到文件末尾)和 "r+"(读写)等。

3. 代码示例

#include <stdio.h>

int main() {
    FILE* fp = fopen("test.txt", "r");
    if (fp == NULL) {
        // 处理打开失败的情况
        return 1;
    }

    // 文件成功打开后的操作...

    fclose(fp);//关闭文件
    return 0;
}

三、strerror 函数

strerror 函数是用来获取错误描述字符串的。当 fopen 或者其他函数失败时,它们通常会设置全局变量 errno 来表示错误的原因。strerror 可以将 errno 的值转换成一个描述性的字符串,从而帮助我们了解具体的错误信息。

strerror - C++ Reference 的介绍:

1. 函数原型

#include <string.h>
const char *strerror(int errnum);

2. 参数

errnum: 错误码,通常直接使用 errno

3. 代码示例

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main() {
    FILE* fp = fopen("test.txt", "r");
    if (fp == NULL) {
        fprintf(stderr, "Failed to open file: %s\n", strerror(errno));
        return 1;
    }

    // 文件成功打开后的操作...

    fclose(fp);
    return 0;
}

四、perror 函数

perror 函数与 strerror 类似,但它会自动将错误描述打印到标准错误流(stderr)。此外,perror 还会在错误描述前加上一个自定义的消息,通常用来指定出错的函数名称。

perror - C++ Reference的介绍:

1. 函数原型

#include <stdio.h>
void perror(const char *msg);

2. 参数

msg: 一个字符串,通常表示出错的函数名称或其他相关信息。

3. 代码示例

#include <stdio.h>
#include <errno.h>

int main() {
    FILE* fp = fopen("test.txt", "r");
    if (fp == NULL) {
        perror("fopen");
        return 1;
    }

    // 文件成功打开后的操作...

    fclose(fp);
    return 0;
}

五、总的来说(可直接跳转至此处开始)

1. 错误处理的基础

  • 在编程时,我们经常会遇到一些错误或异常情况。例如,打开文件失败、内存分配不足等。当这些错误发生时,程序通常会返回一个错误码,以便开发者能够识别出发生了什么问题。
  • 在 C 语言中,错误码通常是通过全局变量 errno 来传递的。errno 是一个整数变量,它会在系统调用或者库函数失败时被设置为特定的值来表示不同的错误类型。

errno 变量

  • errno 是一个预定义的全局变量,在 <errno.h> 头文件中定义。每次系统调用或库函数失败后,它会被设置成一个表示错误原因的整数值。每个错误码都有一个对应的描述字符串,可以帮助理解错误的具体含义。

strerror 函数

  • strerror 函数的作用是将 errno 的值转换成相应的错误描述字符串。这样你就可以通过打印这个字符串来告诉用户发生了什么错误。

注意事项

  • strerror 返回的字符串可能被其他调用覆盖,因此如果需要保留错误消息,应该复制到另一个字符串中。
  • 不同的操作系统可能有不同的错误码和错误消息。

2. 这里数据太多,所以我整理了常见的错误码及其描述:

 strerror 函数返回与给定错误码 (errno) 相对应的错误描述字符串。每个错误码都有一个特定的意义,并且与之对应有一个描述性的字符串。这些错误码及其描述字符串是由操作系统定义的,并且在不同平台上可能会有所不同。然而,大多数常见的错误码和它们的含义在各种 Unix 和类 Unix 系统(包括 Linux)中都是通用的。 

请注意,下面列出的错误码和描述并不是所有可能的错误码,而且具体的错误码数值和描述可能会根据不同的系统和平台有所不同。在实际使用中,你可以查阅你所使用的系统的文档来获取更准确的信息。 

3. 代码示例

3.1 示例一 

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main() {
    int error_number = 2; // 假设这里发生了错误 2: No such file or directory
    const char *error_string = strerror(error_number);
    printf("Error description: %s\n", error_string);

    return 0;
}


运行上述代码会输出:
Error description: No such file or directory

3.2 示例二 

int main() {
    printf("%s\n", strerror(0));   // No error
    printf("%s\n", strerror(1));   // Operation not permitted
    printf("%s\n", strerror(2));   // No such file or directory
    printf("%s\n", strerror(3));   // No such process
    printf("%s\n", strerror(4));   // Interrupted function call
    printf("%s\n", strerror(5));   // Input/output error

    return 0;
}
  • strerror(0):No error (没有错误)
  • strerror(1):Operation not permitted (操作未被允许)
  • strerror(2):No such file or directory (没有这样的文件或目录)
  • strerror(3):No such process (没有这样的进程)
  • strerror(4):Interrupted function call (中断的函数调用)
  • strerror(5):Input/output error (输入/输出错误)

4. 日常使用示例

#include <stdio.h>    // 包含标准输入输出头文件
#include <stdlib.h>   // 包含标准库函数头文件,如 calloc 和 free

int main()
{
    int *p = (int*)calloc(10, sizeof(int));  // 分配足够的内存来存储10个整数,并初始化为0
    if (NULL == p)                           // 如果内存分配失败(p为NULL)
    {
        perror("calloc");                    // 打印错误信息
        return 1;                            // 返回非零值,表示程序异常终止
    }

    // 使用
    int i = 0;                               // 初始化循环变量
    for (i = 0; i < 10; i++)                 // 循环遍历数组中的每个元素
    {
        printf("%d ", *(p + i));             // 输出第i个元素的值
    }

    // 释放内存
    free(p);                                 // 释放之前分配的内存
    p = NULL;                                // 将指针设置为NULL以避免悬挂指针问题

    return 0;                                // 正常退出程序
}
这段代码的主要功能如下:

使用 calloc 函数分配足够空间来存放10个整数,并且将这些整数初始化为0。
检查内存是否成功分配,如果没有分配成功,则打印错误信息并退出程序。
使用一个循环来遍历这个整数数组,并打印每个整数的值。
使用 free 函数释放之前分配的内存。
将指针 p 设置为 NULL 以避免后续使用该指针时产生悬挂指针的问题。
最后返回0表示程序正常结束。

六、总结

综合使用的重要性

  • 错误处理的最佳实践:在文件操作中,结合使用 fopenstrerror, 和 perror 是一种很好的错误处理策略。
  • 提高程序健壮性:通过检查错误条件并提供清晰的错误信息,可以提高程序的稳定性和可靠性。
  • 易于维护:良好的错误处理机制使得代码更容易理解和维护,尤其是在大型项目中。

处理文件错误是一项基本但又复杂的任务。fopen, strerror, 和 perror 这些工具的正确使用能够显著提升程序的质量,使开发者能够更加高效地解决问题。通过掌握这些技巧,开发者可以构建更加健壮、可靠的应用程序。

七、共勉

;