C语言之错误处理
在C语言中,错误处理是一种重要的编程技术,用于处理程序运行过程中可能出现的错误情况。C语言提供了几种处理错误的机制,包括返回错误码、使用全局变量、异常处理等。
1、返回错误码: 在函数执行过程中,如果发生错误,可以通过返回一个特定的错误码来表示错误的类型。通常情况下,函数的返回值为0表示成功,非零值表示错误。这种方式需要在函数声明时明确指定返回类型为错误码,并在函数体内根据错误情况返回相应的错误码。
例如:
int divide(int a, int b, int* result) {if (b == 0) {return -1; // 表示除数为0的错误}*result = a / b;return 0; // 表示成功
}
调用方可以通过检查函数的返回值来确定函数是否执行成功,并根据返回的错误码进行相应的处理。
2、使用全局变量: 另一种处理错误的方式是使用全局变量来记录错误信息。在函数执行过程中,如果发生错误,将错误信息保存到全局变量中,调用方可以通过读取该全局变量来获取错误信息。
例如:
#include <stdio.h>int error_code = 0;
char error_msg[100];void divide(int a, int b, int* result) {if (b == 0) {error_code = -1;sprintf(error_msg, "除数为0");return;}*result = a / b;
}
调用方可以在调用函数后检查全局变量的值,以确定是否发生了错误,并获取相应的错误信息。
3、异常处理: C语言本身并没有内置的异常处理机制,但可以使用一些库或自定义的方法来实现类似的功能。例如,可以使用setjmp和longjmp函数来进行异常处理。setjmp函数设置一个跳转点,longjmp函数用于从跳转点直接跳转到指定位置,从而实现异常的捕获和处理。
例如:
#include <stdio.h>
#include <setjmp.h>jmp_buf jump_buffer;void divide(int a, int b, int* result) {if (b == 0) {longjmp(jump_buffer, -1);}*result = a / b;
}int main() {int result;if (setjmp(jump_buffer) != 0) {printf("除数为0\n");return -1;}divide(10, 0, &result);printf("结果:%d\n", result);return 0;
}
在上述示例中,如果除数为0,则调用longjmp函数跳转到setjmp函数处,并返回指定的错误码。
4、断言: 断言是一种在程序中检查某个条件是否成立的方法。如果条件不成立,则会触发一个断言错误,并终止程序的执行。断言通常用于调试过程中,帮助开发者快速定位问题所在。
例如:
#include <stdio.h>
#include <assert.h>void divide(int a, int b, int* result) {assert(b != 0); // 断言除数不为0*result = a / b;
}int main() {int result;divide(10, 0, &result);printf("结果:%d\n", result);return 0;
}
在上述示例中,如果除数为0,则会触发一个断言错误,并终止程序的执行。
5、日志记录: 日志记录是一种记录程序运行过程中信息的方法,包括错误信息、警告信息、调试信息等。通过记录日志,可以帮助开发者追踪程序的执行过程,定位问题所在。在C语言中,可以使用一些日志库来实现日志记录功能,如log4c、syslog等。
例如:
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>void divide(int a, int b, int* result) {if (b == 0) {syslog(LOG_ERR, "除数为0"); // 记录错误日志exit(1); // 终止程序的执行}*result = a / b;
}int main() {int result;openlog("myapp", LOG_PID, LOG_USER); // 打开日志divide(10, 0, &result);printf("结果:%d\n", result);closelog(); // 关闭日志return 0;
}
6、处理错误信息:在C语言中,errno、perror()和strerror()是用于处理错误信息的重要函数。
- errno: errno是一个全局变量,用于表示最近发生的错误代码。在C标准库中的很多函数在发生错误时会将相应的错误代码存储在errno中。通过检查errno的值,可以确定函数是否成功执行,以及具体的错误类型。
- perror(): perror()函数用于打印与errno相关的错误消息。它接受一个字符串作为参数,并在该字符串后面输出当前的errno值对应的错误消息。通常,这个字符串是用来描述出错的上下文信息,以便更好地理解错误的原因。
- strerror(): strerror()函数返回一个指针,指向当前errno值对应的错误消息的字符串表示形式。它接受一个整数参数,该参数通常是errno的值。通过调用strerror(errno),可以获取到与errno相关的错误消息,然后可以根据需要进行处理或输出。
下面是一个示例代码,演示了如何使用errno、perror()和strerror()来处理错误信息:
#include <stdio.h>
#include <errno.h>
#include <string.h>int main() {FILE* file = fopen("nonexistent.txt", "r");if (file == NULL) {int errnum = errno;fprintf(stderr, "错误号: %d\n", errno);perror("通过 perror 输出错误");fprintf(stderr, "打开文件错误: %s\n", strerror(errnum));} else {// 执行文件操作fclose(file);}return 0;
}
在这个示例中,我们尝试以只读方式打开一个不存在的文件"nonexistent.txt"。由于文件不存在,fopen()函数将返回NULL,并且errno被设置为对应的错误代码。
接下来,我们将errno的值存储在errnum变量中,然后使用fprintf()函数将errno的值输出到标准错误流stderr。接着,使用perror()函数输出与errno相关的错误消息,它会在我们提供的字符串后面输出当前errno值的文本表示形式。
最后,我们使用strerror()函数将errnum的值转换为相应的错误消息字符串,并通过fprintf()函数输出到标准错误流stderr。
当我们运行这段代码时,输出将类似于以下内容:
错误号: 2
通过 perror 输出错误: No such file or directory
打开文件错误: No such file or directory
这个示例展示了如何利用errno、perror()和strerror()函数来获取和输出与错误相关的信息,有助于更好地理解和处理错误情况,,使得调试和错误修复变得更加方便和有效。
相关文章:

C语言之错误处理
在C语言中,错误处理是一种重要的编程技术,用于处理程序运行过程中可能出现的错误情况。C语言提供了几种处理错误的机制,包括返回错误码、使用全局变量、异常处理等。 1、返回错误码: 在函数执行过程中,如果发生错误&a…...

IO流框架,缓冲流
一.缓冲流有什么优点 Java中的缓冲流(Buffered Stream)具有以下优势: 提高效率:缓冲流通过在内存中缓存一部分数据,减少了直接从内存到磁盘或从磁盘到内存的频繁IO操作,从而提高了读写效率。缓冲区大小调整…...

数字音频工作站软件 Ableton Live 11 mac中文软件特点与功能
Ableton Live 11 mac是一款数字音频工作站软件,用于音乐制作、录音、混音和现场演出。它由Ableton公司开发,是一款极其流行的音乐制作软件之一。 Ableton Live 11 mac软件特点和功能 Comping功能:Live 11增加了Comping功能,允许用…...

【PyQt】调整子控件的层级以调整绘制的先后顺序
简述 qt中貌似没有直接设置z序的函数,但对应的有其他调整z序的方法: QWidget.raise_():置顶 QWidget.lower():置底 QWidget.stackUnder(wid):置于指定控件之下 其中关键函数是QWidget.stackUnder(wid),利…...

js中数组的相关方法
引言: 数组(Array)是有序的元素序列。 [1]若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量 方法: push()…...

深入浅出排序算法之直接插入排序(拓展:折半插入排序)
目录 1. 图示解析 2. 原理解析 3. 代码实现 4. 性能分析 5. 折半插入排序(拓展) 直接插入排序和选择排序的第一趟就是第一个关键字 ! 1. 图示解析 2. 原理解析 整个区间被分为:① 有序区间;② 无序区间 每次选…...

皮卡丘RCE靶场通关攻略
皮卡丘RCE靶场通关攻略 文章目录 皮卡丘RCE靶场通关攻略RCE(remote command/code execute)概述远程系统命令执行启动环境漏洞练习第一关exec "ping"第二关 exec "eval" RCE(remote command/code execute)概述 RCE漏洞,可以让攻击者直接向后台服…...

Mysql binlog日志功能使用,简单易懂
一、简单了解binlog MySQL的二进制日志binlog可以说是MySQL最重要的日志,它记录了所有的DDL和DML语句(除了数据查询语句select)。因此binlog日志文件我们用cat等查看文件的命令是打不开的,但是mysql提供了专门看binlog文件的命令…...

计算机视觉-光源的目的和作用
光源的目的 机器视觉系统的核心是图像采集和图像处理,而光源则是影响图像水平的重要因素,通过适当的光源照明,使图像中的目标信息与背景信息得到更好的分离,可大大降低图像识别难度,提高系统的精度和可靠性。 对于机器…...

源码角度分析Java 循环中删除数据为什么会报异常
一、源码角度分析Java 循环中删除数据为什么会报异常 相信大家在之前或多或少都知道 Java 中在增强 for中删除数据会抛出:java.util.ConcurrentModificationException 异常,例如:如下所示程序: public class RmTest {public sta…...

leetCode 229. 多数元素 II + 摩尔投票法 + 进阶 + 优化空间
229. 多数元素 II - 力扣(LeetCode) 给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。 进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题。 (1)哈希表 class …...

5 个编写高效 Makefile 文件的最佳实践
在软件开发过程中,Makefile是一个非常重要的工具,它可以帮助我们自动化构建、编译、测试和部署。然而,编写高效的Makefile文件并不是一件容易的事情。在本文中,我们将讨论如何编写高效的Makefile文件,以提高我们的开发…...

20231028刷题记录
P3381 【模板】最小费用最大流 Portal. sol. 注意 SPFA 找最小费用增广路时不要到终点就返回,因为到终点的路径可能有多条不能确定哪条是费用最小的。 P2740 [USACO4.2] 草地排水Drainage Ditches Portal. 最大流模板。 注意区分 N , M N,M N,M。 CF609D G…...

39 深度学习(三):tensorflow.data模块的使用(基础,可跳)
文章目录 data模块的使用基础api的介绍csv文件tfrecord data模块的使用 在训练的过程中,当数据量一大的时候,我们纯读取一个文件,然后每次训练都调用相同的文件,然后进行处理是很不科学的,或者说,当我们需…...

css四种导入方式
1 行内样式 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <h1 style"color: blue">我是标题</h1> </body> </htm…...

Linux学习第24天:Linux 阻塞和非阻塞 IO 实验(一): 挂起
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 在正式开始今天的笔记之前谈一下工作中遇见的一个问题。 本篇笔记主要学习Linux 阻塞和非阻塞 IO 实验,主要包括阻塞和非阻塞简介、等待队列、轮询、…...

037-第三代软件开发-系统音量设置
第三代软件开发-系统音量设置 文章目录 第三代软件开发-系统音量设置项目介绍系统音量设置QML 实现C 实现 总结一下 关键字: Qt、 Qml、 volume、 声音、 GPT 项目介绍 欢迎来到我们的 QML & C 项目!这个项目结合了 QML(Qt Meta-Obj…...

Python 自动化详解(pyautogui)
文章目录 1 概述1.1 第三方库:pyautogui1.2 坐标说明 2 操作对象2.1 鼠标2.1.1 定位2.1.2 移动2.1.3 拖动2.1.4 滚动2.1.5 点击 2.2 键盘2.2.1 输入2.2.2 按键2.2.3 快捷键 2.3 屏幕2.3.1 截图2.3.2 分辨率 2.4 信息提示2.4.1 提示框2.4.2 选择框2.4.3 密码输入2.4.…...

【Linux】第四站:Linux基本指令(三)
文章目录 一、时间相关的指令1.指令简介2.使用 二、cal指令三、find指令 -name1.介绍2.使用 四、grep指令1.介绍2.使用 五、zip/unzip指令1.介绍2.zip的安装3.使用 六、tar指令:打包解包,不打开它、直接看内容1.介绍2.使用 七、bc指令八、uname -r指令1.…...

SpringBoot内置工具类之断言Assert的使用与部分解析
先例举一个service的demo中用来验证参数对象的封装方法,使用了Assert工具类后是不是比普通的 if(xxx) { throw new RuntimeException(msg) } 看上去要简洁多了? 断言Assert工具类简介 断言是一个判断逻辑,用来检查不该发生的情况ÿ…...

如何检测租用的香港服务器是不是CN2线路呢?
CN2,是中国电信新一代融合承载网络,是为电信自身关键业务和具有QoS保证的SLA业务服务的,可以提供高性能的网络指 标,平均单向时延、最大单向时延、单向丢包率等均属于顶尖水平。简单地说,CN2和普通网络,就像…...

Spring Boot进阶(94):从入门到精通:Spring Boot和Prometheus监控系统的完美结合
📣前言 随着云原生技术的发展,监控和度量也成为了不可或缺的一部分。Prometheus 是一款最近比较流行的开源时间序列数据库,同时也是一种监控方案。它具有极其灵活的查询语言、自身的数据采集和存储机制以及易于集成的特点。而 Spring Boot 是…...

Redis(02)| 数据结构-SDS
一、键值对数据库是怎么实现的? 在开始讲数据结构之前,先给介绍下 Redis 是怎样实现键值对(key-value)数据库的。 Redis 的键值对中的 key 就是字符串对象,而 value 可以是字符串对象,也可以是集合数据类型…...

HackTheBox-Starting Point--Tier 0---Preignition
文章目录 一 题目二 实验过程 一 题目 Tags Web、Custom Applications、Apache、Reconnaissance、Web Site Structure Discovery、Default Credentials译文:Web、定制应用程序、Apache、侦察、网站结构发现、默认凭证Connect To attack the target machine, you …...

售货机相关的电路
一、货道选通矩阵电路,类似扫描电路,驱动哪个电机,就打开相应的行线与列线输出 二、MDB纸币器,虽然现在国内都是手机支付,但如果机器还是外销国外还是有用 三、硬币器电路,投币与退币,脉冲信号…...

软考高项(十四)项目沟通管理 ★重点集萃★
👑 个人主页 👑 :😜😜😜Fish_Vast😜😜😜 🐝 个人格言 🐝 :🧐🧐🧐说到做到,言出必行&am…...

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第五章 高效的多线程日志
“日志(logging)”有两个意思: 1.诊断日志(diagnostic log)。即log4j、logback、slf4j、glog、g2log、log4cxx、log4cpp、log4cplus、Pantheios、ezlogger等常用日志库提供的日志功能。 2.交易日志(trasac…...

利用Pholcus框架提取小红书数据的案例分析
前言 在当今互联网时代,数据的获取和分析变得越来越重要。爬虫技术作为一种数据采集的方法,被广泛涉及各个领域。在本文中,我们将介绍如何使用Python Spark语言和Pholcus框架来实现一本小红书数据爬虫的案例分析。 开发简述 Go语言作为一种…...

超详细Hadoop安装教程(单机版、伪分布式)
超详细Hadoop安装教程(单机版、伪分布式) 1.Hadoop分布式系统基础架构介绍1.1.Hadoop核心 2.Hadoop安装教程2.1.环境准备2.2.配置用户ssh 免密登录2.3.JAVA环境的安装和配置2.4.Hadoop安装2.5.单机版Hadoop配置2.6.伪分布式Hadoop配置2.7Hadoop初始化 1.…...

持续集成部署-k8s-服务发现-Ingress
持续集成部署-k8s-服务发现-Ingress 1. Ingress 是什么2. Ingress 控制器3. 安装 Ingress-Nginx3.1 添加 Helm 仓库3.2 更新 Helm 仓库3.3 下载 Ingress-Nginx 安装包3.4 配置 Ingress-Nginx 配置文件参数3.5 安装 Ingress-Nginx1. Ingress 是什么 Ingress是 Kubernetes 中的一…...