C 语言中的错误处理


2021年8月23日, Learn eTutorial
2572

在本教程中,您将学习 C 语言提供的一些附加功能来实现错误处理,尽管 C 语言本身并不直接支持。

什么是错误处理?

错误处理和调试是编程的重要组成部分。错误处理是指检测和解决中断正常运行的不良压力的过程。基本上,错误处理涉及两个不同的活动:

  1. 错误检测:发现已发生错误的的过程
  2. 错误恢复:采取措施纠正错误的的过程

在大多数现代语言中,程序员会提前预见到错误的发生,并在程序中加入了异常代码来处理错误,一次性解决检测和恢复问题。不幸的是,在 C 语言例程中,这个功能不可用,因此我们需要额外的函数来支持错误处理。

什么是 errno?

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 拒绝访问

perror() 和 strerror() 与 errno 有何关联

以下两个函数用于显示与 `errno` 相关的错误消息:

1. perror()

此函数显示传递的字符串,后跟冒号和空格,然后是 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

2. strerror()

这是 `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!