C 语言 - 错误处理

C 语言中的错误处理

错误处理允许您检测并响应程序中的问题,例如文件无法打开或内存无法分配,从而使您的程序不会崩溃或出现意外行为。

与某些语言不同,C 语言没有内置的异常处理(如 try/catch)。相反,C 语言使用返回值、全局错误代码以及像 perror()strerror() 这样的辅助函数。

使用返回值

在上一章中,您了解到像 fopen() 这样的函数在出现问题时返回 NULL

您可以使用 if 语句检查 NULL,以便在程序崩溃前检测并处理错误。

在下面的示例中,我们尝试打开一个不存在的文件。由于 fopen() 失败,它返回 NULL,我们打印一条错误信息:

实例:fopen() 失败

#include <stdio.h>

int main() {
  FILE *fptr = fopen("nothing.txt", "r");

  if (fptr == NULL) {
    printf("Error opening file.\\n");
    return 1;
  }

  fclose(fptr);
  return 0;
}

结果:

Error opening file.

获取更多详细信息

如果您想了解关于出错的更多详细信息,可以使用 perror() 函数。

它会打印一条自定义错误消息,后跟对上次发生错误的描述:

实例:perror() 与 fopen() 一起使用

#include <stdio.h>

int main() {
  FILE *f = fopen("nothing.txt", "r");

  if (f == NULL) {
    perror("Error opening file");
    return 1;
  }

  fclose(f);
  return 0;
}

结果:

Error opening file: No such file or directory

使用 strerror() 和 errno

errno 是一个全局变量,存储上次失败操作的错误代码。您可以包含 <errno.h> 来访问它,而 strerror(errno) 会将错误代码转换为可读的消息:

实例:strerror()

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

int main() {
  FILE *f = fopen("nothing.txt", "r");

  if (f == NULL) {
    printf("Error: %s\n", strerror(errno));
    return 1;
  }

  fclose(f);
  return 0;
}

结果:

Error: No such file or directory

常见错误代码

错误常量在 <errno.h> 中定义。您可以将 errno 与它们进行比较以检测特定问题:

错误代码 含义
ENOENT 没有此文件或目录
EACCES 权限被拒绝
ENOMEM 内存不足
EINVAL 无效参数

实例:为 ENOENT 自定义消息

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

int main() {
  FILE *f = fopen("nothing.txt", "r");

  if (f == NULL) {
    if (errno == ENOENT) {
      printf("The file was not found.\n");
    } else {
      printf("Some other file error occurred.\n");
    }
    return 1;
  }

  fclose(f);
  return 0;
}

结果:

The file was not found.

使用 exit() 停止程序

如果您想在发生错误时立即停止程序,可以使用 exit()。它允许您向操作系统返回一个状态码。

退出代码有助于表明程序是成功完成还是出现错误,例如:

  • 0 表示成功
  • 非零值(如 1EXIT_FAILURE)表示错误

实例:出错时使用 exit()

#include <stdio.h>
#include <stdlib.h>

int main() {
  FILE *f = fopen("nothing.txt", "r");

  if (f == NULL) {
    printf("Failed to open file.\n");
    exit(1);
  }

  fclose(f);
  return 0;
}

结果:

Failed to open file.

常见退出状态码

代码 含义
0 成功 - 程序正常完成
1 错误 - 出现问题
EXIT_SUCCESS 与 0 相同(在 <stdlib.h> 中定义)
EXIT_FAILURE 与非零错误代码相同(也在 <stdlib.h> 中)

提示:您可以使用 EXIT_SUCCESSEXIT_FAILURE 代替数字,以使代码更具可读性。

实例:使用 EXIT_FAILURE 和 EXIT_SUCCESS

#include <stdio.h>
#include <stdlib.h>

int main() {
  FILE *f = fopen("nothing.txt", "r");

  if (f == NULL) {
    perror("Could not open nothing.txt");
    exit(EXIT_FAILURE); // More readable than exit(1)
  }

  fclose(f);
  return EXIT_SUCCESS;
}

结果:

Could not open nothing.txt: No such file or directory

总结

  • 许多 C 语言函数在出现问题时返回 NULL
  • 使用 perror() 打印关于错误的消息
  • 使用 strerror(errno) 将错误消息作为字符串获取
  • errno 存储上次失败操作的错误代码
  • 您可以将 errno 与诸如 ENOENT(找不到文件)或 ENOMEM(内存不足)等值进行比较
  • 如果出现错误,使用 exit() 提前停止程序

提示:在文件操作、内存分配和系统调用之后,始终检查错误。忽略错误可能导致意外行为或崩溃。