当前课程知识点:C语言程序设计 > 第22讲 编程训练 > 编程训练 > 程序调试
写完的程序可能有编译错误和运行错误
我们在前面讲过常见的编译错误
以及排除运行错误的常规方法
这一讲介绍程序调试
是解决程序运行错误的最有力的方法
必须在学习过程中逐渐熟练掌握
C语言程序调试方法也同样适用于其他语言
我们看一下调试的基本概况
首先看下调试的目的
在排除了编译错误后
程序就可以运行
如果程序运行的结果与预期的结果不一致
就可以使用调试的方法找出错误所在
调试的内容包括调试过程中
可以观察变量变化 内存状况等
看看和你预期的是否一致
调试的手段包括单步追踪 设置断点 运行到光标处等
单步跟踪是程序调试最常用的方式
是让程序每运行一条语句后就暂停
以便我们观察刚才运行语句产生的结果
可在“变量窗口”观察和分析变量的变化
我们看一下一个程序调试的例子
这个例子是计算1+2+3+…+100.
我们编译运行这个程序
那么我们看到 得到的答案是5058
我们知道1+2+3+…+100正确答案应该是5050
那这个显然是运行错误
那我们用调试的办法来分析一下错误到底出在了哪里
在这个Debug这儿
然后点Step into
注意这个地方它也可以用快捷键Shift+F7
这样第一步运行了以后就到了程序的真正的语句
因为前面定义变量这个不能完全算是真实的开始语句
我们现在可以看到这边有一个变量窗口
现在有两个变量
我们可以观察到它的值i是33,sum是8
这是在系统给变量分配内存以后
里面随机或者说可以理解成是原本系统当中这个位置
是什么值现在这个值就仍然是多少
那你现在再往下调试的时候可以按这个Next line
也可以按Shift+F7或者直接按F7
那么这个在不同的调试器里面这个快捷键不太一样
但是基本功能都一样
我们按下F7
然后for就执行了一次
我们观察了一下这个是让i给了一个起始值
然后这就是1
是正确的
然后我们再执行一下这个
然后就刚刚sum这一句执行了
那执行了以后我们观察到sum的值是9
这个显然跟我们预想的不一样
因为我们在这个地方只是把1加进去了
那么这个时候正确的答案是sum的值是1才对
那这一遍算下来是9
那么这一步能观察到这就出错了
那我们稍微琢磨一下
我们发现这个问题的根源在哪儿呢
是在最初定义sum变量的时候没有给它赋0
然后就直接在这加i
这样我们就发现了问题所在
调试过程当中如果你发现了错误所在的话
就可以Stop debugger,让调试停止
停止了以后你可以把这个错误消除掉
我们把这个改了以后我们再编译运行一下
我们看到得到了正确的答案
程序比较长或循环次数很多时
单步调试太慢
这时我们可以设置断点
程序直接运行到断点处会暂停
我们可以观察当前的运行结果
在调试时
断点和单步执行可以结合进行
断点可以设置多个
可以随时取消某个断点
我们看一下这个程序调试的示例2
这个要求是输入一个3~10之间的整数n
求1!+2!+…+n
我们在这儿就用设置断点的方式在这设置一个断点
在Code Block里面点一下
然后有一个红点
这个就是断点
然后我们点这个Dbug
这个地方这样运行就会运行到断点处停止
我们输入一个3
然后我们看到这个黄色的三角
就是说程序现在是在这个位置
这个位置然后我们用单步执行
按这个F7
它执行到这一步
那么刚才是这几个运行完了以后变量的变化
我们来看一下刚才i加了以后值是2
然后n是我们前面输入的那个值3
s是刚刚加了k的值
这个地方实际上就是相当是把1!加了进去
然后现在加了以后s变为3
i再增加
i现在变为3
然后现在k等于6
因为这个地方i的值现在是3
那么它已经等于n了
就是不满足小于n的条件
所以这个循环跳出来了
这个循环跳出来了
那么我们其实已经发现了问题所在是什么
刚才本身是要+1!+2!+3!
但是刚才很明显的看到3!没有加进去
那么这个时候s的值等于3
就是没有把这个3!=6加进去
就是问题所在
我们发现了问题的所在了以后
我们就知道了这个地方
应该是循环最后的那个值没有加进去
那么我们可以改成这样
就是小于等于n
然后我们再这样编译运行一下
我们输一个3
它得到的结果是9.我们再验证一下
就是再执行一个
比如说我们输入的是4
那么这个结果是33
我们可以大概算一下
刚才3!的是9
4!的是24
24+9就是33
所以这个答案是正确的
当然这个断点可以设置多个
这个程序比较短
好像也没有必要设多个断点
那么前面也说了
设断点可以和单步执行同时来
设断点是能让程序一下就运行到断点处
然后再单步执行观察这个变量的结果
调试时 还可以运行到光标处(Run to cursor)
另外单步执行有两种情况
step into 与next line
这是Code Block里面的说法
有的编译器把这个next line叫step over
这两种方式在遇到函数时是有区别的
就是第一种方式step into会跟踪进函数体内
而next line遇到调用函数的那条语句以后
它直接把那个执行而过
不跟踪进入函数体
另外调试除了可以查看变量的值以外
也可以查看内存的值
我们看这个调试的示例
求2两个数的最小公倍数和最大公约数
我们编译运行一下这个程序
比如我们输入4、6
那我们看到它输出的结果就是4和6
它得到的结果是最小公倍数是4
最大公约数是6
这个显然是错误的
那我们来看看程序当中到底出了什么问题
那么这个呢
当然你也可以使用单步跟踪
这样我们用一个刚才说过的办法run to cursor
就是运行到光标处
那么它就运行到刚才光标指的地方
就到这一行
那么到这我们看到这个m和n的值
就是刚才输的这两个值已经准确的赋值给这两个变量了
那么现在跟踪的时候想进入这个函数体内跟踪
我们就选择Step into
注意这个黄色三角到这
就是运行到这了
然后 这儿你是点这个地方也行或者按F7也行
然后我们看到t的值是4,然后7
注意这个地方这个条件就是这么写了以后
完了以后就直接跳出循环了
那么说明问题就出在这个地方
像这个例子当中的话
它这个地方它不应该返回这个7不应该返回这个4
而应该在这个地方多处理几次
那么这样我们就知道问题出在这块
我们停止调试
停止调试然后仔细观察一下或者想一下
会发现这个地方写错了
不应该是除
而是求余
我们再运行一下
那么我们看到这次得到的答案是最小公倍数是12
最大公约数是2
这是一个正确的答案
当然程序调试我演示的时候大家看起来好像比较简单
实际上要想很准确的熟练的使用
还是需要多加练习的
而且前面也说过
调试是程序员最有力的排除错误的武器
那么必须要掌握这种方法
否则出了错误以后
如果你不懂调试这种方法
你可能对着代码看上一天甚至几天
也发现不了错误到底在哪里
而用调试的方法
你会很快的缩小错误所在的位置
然后因为只要发现错误所在
那修改这个错误相对来说还是比较容易的
-作业
-作业
-作业
-作业
-作业
-作业
-作业
-作业
-循环类型
-作业
-程序结构
-函数基础
-作业
-数组基础
-作业
-作业
-作业
-作业
-程序调试
- 文件(上)
- 编程训练