当前位置: 首页 > news >正文

C++ 古法调试:使用 assert 宏

沃尔特·萨维奇的书 《Problem Solving with C++ 》第五章在介绍函数的抽象原则时,提到:函数的注释中应该包括了这个函数被调用的“前提”和“结果”,正确的前提将保证得到正确的结果,否则则是错误的调用。

在写完程序进行调试(确定程序编写无误)的时候,除了调用编译器的调试组件随时查看变量值,还可以检查一个函数的调用前提是否被满足。这时可以使用一个类似于函数的工具:“宏”,来完成判断,这个宏就被称为 assert 宏,翻译过来就是“断言”宏,用来判断它附加的前提表达式(是个布尔逻辑表达式)是否成立。

也就是写作 assert(前提-布尔表达式 is true); 。如果断言宏附加的布尔表达式不满足,则程序会以非0值退出。

下面是一段应用了 assert 宏的程序,其中为了求一个给定的正数的平方根,用了牛顿的“递归公式法”,这时要求“给定的数和递归的次数都为正数”;断言宏断言这个前提是满足的。


#include <iostream>
//  这是一个用 “牛顿法”公式 迭代求解某个正数的平方根的程序#define NDEBUG
#include <cassert>  // 使用 assert 宏 需要引入的头文件void getInput(double& num, int& i);
//  pre: 键盘输入 num - 需要求平方根的数  i - 公式计算迭代的次数
//  post:num 和 i 分别被设定为输入值void introduction();
//  pre: 无
//  post: 介绍一下程序功能double newtonSqroot(double n, int num_iterations);
//  pre: n是正数 num_iterations是正整数
//  post: 返回 n 的平方根 (通过牛顿公式的 num_iterations 次迭代来估算)void giveOutput(double num, int i, double sq_root);
//  pre: num - 需要求平方根的数  i - 计算迭代的次数  sq_root - 求得的平方根
//  post:屏幕输出 num  i sq_root 的值int main()
{double num, ans;int i; // ans 是 num 的平方根 (经过了i次迭代求得的近似解)introduction();getInput(num, i);ans = newtonSqroot(num, i);giveOutput(num, i, ans);return 0;
}void getInput(double& num, int& i)
{using namespace std;cout << "请输入您要求平方根的数(需要大于0):";cin >> num;cout << "为了求这个平方根,您希望经过几轮计算?(算得越多越接近真实值)\n";cin >> i;
}void introduction()
{using namespace std;cout << "依据牛顿法,每将整数N上一次求出的近似平方根x带入公式 (1/2)(x + N/x) \n" << "求得的值会都比x更接近N的平方根。 本程序可以求一个整数的平方根的近似值: \n";
}double newtonSqroot(double n, int num_iterations)
{double answer = 1;  // 既是n=1时的答案,也是第0次迭代时的初始值int i = 0;assert((n > 0) && (num_iterations > 0));    // 如果调用函数的前提不满足,这行语句将使程序因断言失败而退出while (i < num_iterations){answer = 0.5 * (answer + n / answer);i++;}return answer;
}void giveOutput(double num, int i, double sq_root)
{using namespace std;cout.setf(ios::fixed);cout.setf(ios::showpoint);cout.precision(4);cout << "经过 " << i << " 次计算,"; cout << num << " 的平方根估计值为 " << sq_root << endl;cout << "感谢使用! \n";
}

递归的公式在代码中给出了,就是 \(sqrt_{i+1} = \frac{1}{2} \{ sqrt_i + \frac{n}{sqrt_i} \}\).

需要注意的除了 为了使用 assert,要引入库文件还有只要在代码中定义了“宏” NDEBUG (在代码开头有一行 #define NDEBUG),就可以让代码中的所有 assert 宏失效,也就是即使 assert宏 假设的前提不成立,程序也不会终止,而是就像调用assert宏的语句不存在一样继续运行。所以,要让文中的代码里的assert起到检查前提是否满足的调试功能,需要删掉开头 #define NDEBUG 这一句。

大概就是这样。

http://www.sczhlp.com/news/6303/

相关文章:

  • 美团
  • ubuntu扩盘,根目录/为例。 - try
  • 指针练习试题
  • 【从零开始实现stm32无刷电机FOC】尝试代码阅读
  • 暑假周总结3
  • 【自学嵌入式:51单片机】AD模数转换/DA数模转换(含SPI通信)
  • 2025.8.5 -「图论」
  • 暑假周总结2
  • 20250805-40
  • 1768. 交替合并字符串
  • 浏览器插件过度分享隐私问题剖析
  • 混合递归架构实现推理速度翻倍的技术解析
  • C++ RAII详解
  • RabbitMQ 网络分区
  • 深入解析:java设计模式 -【策略模式】
  • 20250805
  • OI 笑传 #6
  • 搜索旋转排序数组
  • 若依框架创建表结构异常
  • Koala 开源项目常见问题解决方案
  • 记得保存
  • 408-OS之多处理机
  • 百度Comate的AI编程工具小试
  • windows防火墙配置以及网络服务开放排查
  • 八股DAY1--MySQL面试题总结 - Charon
  • P9814 题解
  • 基础字符串算法及其运用
  • AUTO TECH 2025广州汽车内外饰展:解锁行业密码,展望未来出行美学 - 详解
  • 通过文件IO进行文件复制
  • SYZOJ ranklist 溢出修复