C 教程

C 教程 C 语言简介 C 下载安装和环境配置 C 快速入门 C 语法 C 输出 C 注释 C 变量 C 数据类型 C 常量 C 运算符 C 布尔值 C If...Else 语句 C Switch 语句 C While 循环 C For 循环 C Break/Continue 语句 C 数组 C 字符串 C 用户输入 C 内存地址 C 指针

C 函数

C 函数 C 函数参数 C 作用域 C 函数声明 C 递归 C 数学函数

C 文件

C 创建文件 C 写入文件 C 读取文件

C 结构体

C 结构体 C 嵌套结构体 C 结构体和指针 C 联合体 C typedef

C 枚举

C 枚举

C 内存

C 内存管理

C 错误

C 错误 C 调试 C 空值 C 错误处理 C 输入验证

C 更多

C 日期 C 随机数 C 宏 C 代码组织 C 存储类 C 位运算符 C 固定宽度整数

C 项目

C 项目

C 参考资料

C 参考资料 C 关键词 C <stdio.h> C <stdlib.h> C <string.h> C <math.h> C <ctype.h> C <time.h>

C 标准库参考

C 标准库 - 参考手册 C 标准库 - <assert.h> C 标准库 - <ctype.h> C 标准库 - <errno.h> C 标准库 - <float.h> C 标准库 - <limits.h> C 标准库 - <locale.h> C 标准库 - <math.h> C 标准库 - <setjmp.h> C 标准库 - <signal.h> C 标准库 - <stdarg.h> C 标准库 - <stddef.h> C 标准库 - <stdio.h> C 标准库 - <stdlib.h> C 标准库 - <string.h> C 标准库 - <time.h>

C 实例

C 语言实例 C 经典100例 C 编译器 C 测验


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;
}

结果:

打开文件时出错。

获取更多详情

如果您想了解更多错误详情,可以使用 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;
}

结果:

打开文件时出错:没有该文件或目录

使用 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
", strerror(errno));
    return 1;
  }

  fclose(f);
  return 0;
}

结果:

错误:没有该文件或目录

常见错误代码

错误常量定义在 <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.
");
    } else {
      printf("Some other file error occurred.
");
    }
    return 1;
  }

  fclose(f);
  return 0;
}

结果:

文件未找到。

使用 exit() 停止程序

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

退出码有助于指示程序是成功结束还是出错,例如:

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

示例:使用 exit() 函数处理错误


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

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

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

  fclose(f);
  return 0;
}

Result:

Failed to open file.

常用退出状态码

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

提示: 您可以使用 EXIT_SUCCESS 和 EXIT_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;
}

结果:

无法打开 nothing.txt:没有该文件或目录

总结

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

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