在本教程中,您将学习 C 语言提供的一些附加功能来实现错误处理,尽管 C 语言本身并不直接支持。
错误处理和调试是编程的重要组成部分。错误处理是指检测和解决中断正常运行的不良压力的过程。基本上,错误处理涉及两个不同的活动:
在大多数现代语言中,程序员会提前预见到错误的发生,并在程序中加入了异常代码来处理错误,一次性解决检测和恢复问题。不幸的是,在 C 语言例程中,这个功能不可用,因此我们需要额外的函数来支持错误处理。
C 语言提供的用于处理错误的一个附加功能是**错误编号**,简称**errno**。如果任何函数调用失败,这个预定义的全局变量 `errno` 会返回像 ‘-1’ 或 ‘NULL’ 这样的值来通知程序员错误状态。它的所有内容都写在头文件 `error.h` 中。为了快速识别,始终建议将变量初始化为 ‘0’。因此,在程序启动时,errno 的值为零。编译结束后,程序员可以注意返回值并采取必要的步骤。
下表列出了 errno 及其对应的错误类型。
| errno 值 | 错误 |
|---|---|
| 1 | 操作不允许 |
| 2 | 没有这样的文件或目录 |
| 3 | 没有这样的进程 |
| 4 | 系统调用被中断 |
| 5 | I/O 错误 |
| 6 | 没有这样的设备或地址 |
| 7 | 参数列表太长 |
| 8 | 执行格式错误 |
| 9 | 无效文件描述符 |
| 10 | 没有子进程 |
| 11 | 再试一次 |
| 12 | 内存不足 |
| 13 | 拒绝访问 |
以下两个函数用于显示与 `errno` 相关的错误消息:
此函数显示传递的字符串,后跟冒号和空格,然后是 errno 中存储的错误代码的描述。
当我们编写打开或读取文件的代码时,编译器会指示操作系统执行此操作。但有时可能会因为文件不存在或已损坏而失败。然后库文件 `error.h` 会将错误代码保存在 `errno` 中。使用 `perror`,我们可以显示所需的文本消息,而不是一个简单的代码。请看下面的程序。
#include <stdlib.h>
int main()
{
FILE *fp;
fp = fopen("my_file.txt", "r");
if (fp == NULL)
{
printf("Value of errno: %d\n ", errno);
perror("Message from perror");
}
}
在这里,编译器会查找文件 'my_file.txt'。如果找不到,文件指针将返回一个空值,`perror` 将显示消息“没有这样的文件或目录”。在屏幕上,我们将看到 `perror` 传递的字符串,然后是冒号和空格,后面跟着这个消息。
输出
Value of errno: 2 Message from perror: No such file or directory
这是 `string.h` 头文件中定义的另一个函数,它返回一个指向与 errno 关联的系统生成错误消息的指针。请检查以下示例以理解这两个函数之间的核心区别。
#include <stdio.h>
#include <error.h>
#include <string.h>
#include<stdlib.h>
int main()
{
FILE *fp;
fp = fopen("my_file.txt", "r");
if (fp == NULL)
{
printf("Value of errno: %d\n ", errno);
perror("Message from perror");
printf("The error message by strerror is : %s\n", strerror(errno));
}
else{
fclose(fp);
}
}
在这里,`perror` 和 `strerror` 这两个函数都将打印相同的消息“没有这样的文件或目录”。区别在于,前者表示 errno 的文本格式,而后者通过将错误编号作为函数的参数来执行此操作。
Value of errno: 2 Message from perror:No such file or directory The error message by strerror is : No such file or directory
我们经常会遇到这种错误,尤其是在涉及复杂数学计算时。在编写计算器或银行软件的代码时,我们可能会忘记用户可能输入零作为除数。我们知道任何数除以零都会得到无穷大,所以如果发生这种情况,程序会报错。
因此,最佳做法是将所有除数为零的情况路由到单独的代码块中。这将标志一个适当的错误消息,用户将很容易理解哪里出错了。在下面的程序中,我们将尝试将 1 除以 0 并使用 `strerror` 函数标记错误。
#include <stdio.h>
#include <stdlib.h>
main()
{
int a = 1;
int b = 0;
int c;
if( b == 0)
{
fprintf(stderr, " Zero can not be a divisor...\n");
exit(-1);
}
c = a / b;
fprintf(stderr, "The result of the division is %d\n", c );
exit(0);
}
输出
Zero cannot be a divisor…
通常,程序有两种可能的结局:成功或失败。程序员们通常会将成功运行的程序退出时返回 ‘0’,否则返回 ‘-1’ 作为负结果的表示。当输入数据不正确时,其余代码的执行就没有意义了。因此,最好带有消息退出程序。
这是一个除法程序
#include <stdio.h>
#include <stdlib.h>
main()
{
int a, b, c;
printf(" Enter the dividend");
scanf("%d",&a);
printf ("\n Enter the divisor");
scanf("%d",&b);
if( b== 0)
{
fprintf(stderr, "\nZero cannot be a divisor! ");
exit(EXIT_FAILURE);
}
c=a/b;
fprintf(stderr, " \nTHE RESULT IS : %d", c );
exit(EXIT_SUCCESS);
}
如果输入零作为除数,程序将退出并显示定义的错误消息“零不能作为除数!”。否则,它将显示正确的商。
输出
Enter the dividend 40
Enter the divisor 2
THE RESULT IS : 20
OR
Enter the dividend 4
Enter the divisor 0
Zero cannot be a divisor!