我们今天来看下异常处理,在看 C++ 的异常处理之前,先来看看 C 语言中的异常处理。那么什么是异常呢?在程序运行过程中可能会产生异常,异常(Exception)与 Bug 的区别是:异常是程序运行时可预料的执行分支,而 Bug 是程序中的错误,是不被预期的运行方式。

下来我们来看看异常和 Bug 的对比:a> 异常比如运行时产生除 0 的情况,需要打开的外部文件不存在,数组访问时越界;b> Bug 是使用野指针,堆数组使用结束后未释放,选择排序无法处理长度为 0 的数组。在 C 语言中的经典处理方式为:if ... else ... 。if 语句中处理的是正常情况代码逻辑,else 语句中处理的是异常情况代码逻辑。

我们还是以代码为例来看看除法操作异常的处理

#include <iostream>
#include <string>using namespace std;double divide(double a, double b)
{const double delta = 0.000000000000001;double ret = 0;if( !((-delta < b) && (b < delta)) ){ret = a / b;}else{ret = 0;}return ret;
}int main()
{cout << divide(1, 1) << endl;cout << divide(1, 0) << endl;return 0;
}

我们看看编译结果

执行的结果是正确的,但是如果我们打印的是 0/1 的结果呢?我们就不知道执行的到底是正确的情况还是异常的情况。那么我们在上面程序中的 divide 函数中添加一个参数,用来表示执行结果的正确与否,根据这个参数的值来判断执行是否正常。程序如下

#include <iostream>
#include <string>using namespace std;double divide(double a, double b, int* valid)
{const double delta = 0.000000000000001;double ret = 0;if( !((-delta < b) && (b < delta)) ){ret = a / b;*valid = 1;}else{*valid = 0;}return ret;
}int main()
{int valid = 0;double r = divide(1, 0, &valid);if( valid ){cout << "r = " << r << endl;}else{cout << "Divided by zero..." << endl;}return 0;
}

我们来看看编译结果

再来试试 0/1 呢

我们看到结果已经正确的执行了。但是这个程序有个缺陷,便是 divide 函数需要 3 个参数,难以理解它的用法,而且 divide 函数调用后必须判断 valid 代表的结果,当 valid 为 true 时,运算结果正常;当 valid 为false 时,运算结果出现异常。在 C 语言还有一种异常处理的方式,通过 setjmp() 和 longjmp() 进行判断。下来我们来讲讲这两个函数的原型及其意思:a> int setjmp(jmp_buf env) 是将当前上下文保存在 jmp_buf 结构体中;b> void longjmp(jmp_buf env, int val) 从 jmp_buf 结构体中恢复 setjmp() 保存的上下文,最终从 setjmp 函数调用点返回,返回值为 val;下来我们通过示例代码来进行分析

#include <iostream>
#include <string>
#include <csetjmp>using namespace std;static jmp_buf env;double divide(double a, double b)
{const double delta = 0.000000000000001;double ret = 0;if( !((-delta < b) && (b < delta)) ){ret = a / b;}else{longjmp(env, 1);}return ret;
}int main()
{if( setjmp(env) == 0 ){double r = divide(1, 0);cout << "r = " << r << endl;}else{cout << "Divided by zero..." << endl;}return 0;
}

在它进入 main 函数的 if 语句后,会将 0 保存在当前的 env 中,然后 setjmp 函数会保存当前的上下文信息。然后执行 divide 函数,进入到 divide 函数中,会进入到 else 分支。longjmp 函数则会将 1 保存到 env 中并将程序的执行流跳转到 setjmp 处,此时 env 为 1,因此条件不成立,所以会打印出 Divided by zero...,我们来看看编译结果

我们再来看看 1/1 呢,进入到 divide 函数中,它会执行 if 语句进行正常的计算之后直接便会返回 ret,便会输出结果

虽然这是两个参数,但是它有一定的缺陷。setjmp() 和 longjmp() 的引入就必然涉及到使用全局变量,暴力跳转导致代码的可读性降低,其本质还是 if ... else ... 异常处理方式。它的暴力跳转会破坏 C 语言的结构化特性(顺序执行、选择执行、循环执行)。C 语言中的经典异常处理方式会使得程序中逻辑混入大量的处理异常的代码。正常逻辑代码和异常处理代码混合在一起,导致代码迅速膨胀,难以维护。那么在 C++ 中肯定便会有更好的异常处理方式,我们后面会继续学习。通过对 C 语言中异常处理的学习,总结如下:1、程序中不可避免的会发生异常;2、异常是在开发阶段就可以预见的运行时问题;3、C 语言中通过经典的 if ... else ... 方式处理异常,在 C++ 中存在更好的异常处理方式。

欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。

转载于:https://blog.51cto.com/12810168/2124290

C 语言异常处理(五十二)相关推荐

  1. C语言试题五十二之学生的记录由学号和成绩组称个,n名大学生得数据已在主函数中放入结构体数组a中,请编写函数fun,它的功能时:按分数的高低排列学生的记录,高分在前。

    1. 题目 请编写一个函数void function(Student a[], int n),其功能时:学生的记录由学号和成绩组称个,n名大学生得数据已在主函数中放入结构体数组a中,请编写函数fun, ...

  2. C语言/C++常见习题问答集锦(五十二) 之职工信息管理系统

    C语言/C++常见习题问答集锦(五十二) 之职工信息管理系统 程序之美 用C语言,职工信息管理系统具体要求 1.基本信息:如工号.姓名.性别.年龄.学历.住址.电话号码.工资等. 2.各职工信息用结构 ...

  3. c语言压缩文本文件北京理工大学,北京理工大学C语言程序设计第十二章文件.ppt...

    北京理工大学C语言程序设计第十二章文件 2000年1月25日 北京理工大学 / 第十二章 文件 第一节 文件概述 第二节 文件的处理 第三节 文件的顺序读写操作 第四节 文件的随机读写操作 第五节 文 ...

  4. C++语言学习(十二)——C++语言常见函数调用约定

    C++语言学习(十二)--C++语言常见函数调用约定 一.C++语言函数调用约定简介 C /C++开发中,程序编译没有问题,但链接的时候报告函数不存在,或程序编译和链接都没有错误,但只要调用库中的函数 ...

  5. JavaWeb学习总结(五十二)——使用JavaMail创建邮件和发送邮件

    JavaWeb学习总结(五十二)--使用JavaMail创建邮件和发送邮件 一.RFC882文档简单说明 RFC882文档规定了如何编写一封简单的邮件(纯文本邮件),一封简单的邮件包含邮件头和邮件体两 ...

  6. OpenCV学习笔记(五十一)——imge stitching图像拼接stitching OpenCV学习笔记(五十二)——号外:OpenCV 2.4.1 又出来了。。。。。 OpenCV学习笔记(五

    OpenCV学习笔记(五十一)--imge stitching图像拼接stitching stitching是OpenCV2.4.0一个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitch ...

  7. 《当程序员的那些狗日日子》(五十二)同学情与差距

    (五十二)同学情与差距 临近春节放假前,我收到了高中一同学志的结婚请柬.想想也快到春节放假了,于是我干脆请了几天假,跟春节假期连在一起,这样就可以提先回家过一个春节长假了. 说起来很巧,志是我到广州后 ...

  8. JavaScript学习(五十二)—继承、call方法和apply方法

    JavaScript学习(五十二)-继承.call方法和apply方法 学习内容 一.继承 二.call方法 三.apply方法 一.继承 所谓继承就是两个构造方法建立起来的某种联系,通过某种联系,可 ...

  9. 硬盘底座linux,微客智品 篇五十二:机械硬盘如何安放?用奥睿科单盘位移动硬盘底座助力新玩法...

    微客智品 篇五十二:机械硬盘如何安放?用奥睿科单盘位移动硬盘底座助力新玩法 2020-01-07 15:36:58 1点赞 10收藏 30评论 随着新一代M.2硬盘的流行与普及,3.5寸机械硬盘愈发变 ...

  10. (五十二):多模态情感分析研究综述_张亚洲

    (五十二):多模态情感分析研究综述_张亚洲 Abstract 1 叙述式多模态情感分析 1. 1 静态多模态情感分析(文本与图像划分为静态文档) 1. 1. 1 基于机器学习的方法 1. 1. 2 基 ...

最新文章

  1. SQL Relay开源的数据库池连接代理服务器
  2. 借助C/C++进行Android开发:NDK的配置与使用
  3. 多维DP UVA 11552 Fewest Flop
  4. 51单片机学习笔记(郭天祥版)(3)——引脚讲解、数码管静态显示、中断系统(外部中断,定时器中断)...
  5. vs 2015查看动态库
  6. EOS的trace_api_plugin插件测试
  7. 游戏程序员的核心竞争力是什么?
  8. Spring Boot项目自定义启动Banner
  9. Glib学习笔记(1)
  10. 小米设备跨版本降级后相机打不开陀螺仪无法工作解决办法
  11. 页面显示LCD液晶字体,特殊字体,@font-face属性详细用法,配图
  12. iCal及iCalendar说明
  13. [499]openstack swift 的UI客户端
  14. clickhouse 数据TTL使用
  15. 专利申请流程所需时间是怎样的?
  16. php reactphp wss_浅谈WebSocket协议、WS协议和WSS协议原理及关系
  17. 土地利用覆盖数据免费下载
  18. python3制作捧腹网段子页爬虫
  19. people05-1——中国人、北京人和美国人
  20. 重庆计算机软件类工作在哪找,重庆计算机办公应用有哪些

热门文章

  1. Django--ORM基本操作
  2. Hadoop和Spark的异同
  3. MySQL - ODBC安装错误问题!
  4. 使用抓包工具fiddler和apipost进行接口测试
  5. selenium windows 下面环境搭建(Eclipse)
  6. graphics | 基础绘图系统(一)——主函数plot及其参数
  7. 显示2位小数 python3_自动化常用语言python,版本3和2有何变化?
  8. python dataframe索引转成列_Pandas之DataFrame对象的列和索引之间的转化
  9. 服务器x不会下载mysql_MySQL_解决MySQL数据库死掉以及拒绝服务的方法,从Mysql 5.x的某个版本之后,MySQ - phpStudy...
  10. 记者“卧底”程序猿的故事