前言
想必不少人在刷ACM题目或者平时写一些小程序时,多多少少都会遇到一些Bug
咦?为什么我的程序RE了……我思路绝对没问题,可这不是我想要的输出结果……等等
其中Bug是缺陷(defect)的一种表现形式,而一个缺陷是可以引起多种Bug的,通常debug是指发现缺陷并改正的过程,如果代码中存在缺陷,我们首先要识别造成缺陷的根本原因(root cause),这个过程就称作调试(debugging)
然后很多人就只好在各种地方printf(),或者assert()等等,来看看这个地方的数据有没有错或者程序能否执行到某个地方,有的时候还好,就一行,但当你想看某个循环里面的变量,或者看一个二维数组中变量时候,就会很不方便/麻烦
而Visual Studio提供了非常齐全使用的调试工具,虽然很多功能相对复杂,但其实想解决一般ACM题目中的问题,还是非常非常简单的,更可以在平时给你节省很多的时间,特别是在网赛冲个前几名时间很宝贵的
以下就拿题目bzoj 3477的AC代码举例,这是一道只需要用到二分的简单题目,当然也调用了函数
一、设置断点
断点用于通知调试器在什么地方暂停程序执行,点击当前行最左侧就可以当前行添加断点
如下图,while循环那一行左侧有个断点,那么F5之后,程序在执行到while循环之前就会停止执行
而此时最下方就会显示目前所有变量的值,把鼠标移到某个变量上也可以
例如图中鼠标移动到a数组上,点击'+'号,就可以列出这个数组中每个下标对应的值,从而不需要printf()操作了
这个时候只要再按一次F5,就会从断点处开始继续执行,直到遇到下一个断点
而断点设在While循环这一行也就意味着:你每按一次F5,程序都会刚好多进行一次while循环!
下面就是若干次循环之后的结果,r的值为625.9375
二、逐过程与逐语句
就是一条一条的执行代码,程序在断点停下后,每按一次逐过程,程序就会多执行一个语句
也就是图中的31→33→34→35→36→37→31(一趟循环结束回到31)
是的没错,逐过程遇到执行函数(方法调用)时,并不会跳进函数里,而是一口气将函数执行完
而逐语句和逐过程一样,唯一的区别就是逐语句会跳入函数中
对于下图逐语句执行到16行时,会直接跳入库函数里
当你在一个函数(方法)内部调试时跳出,调试器会完成此方法的执行,并在调用此方法的语句的下一条语句处暂停。
三、设置下一语句
顾名思义,你可以任选一行设置下一语句,这样你的程序下一步就会直接从那一行开始执行,相当于改变了程序原先的逻辑
如下图,假设你现在你已经执行到while循环里面了,如果你在第27行"右键→设置下一语句",那么程序下一句就会从第27行开始执行,这也意味着你又要输入一次数据
这是一个很有意思的特性,在某些时候可以帮你跳过一下break或者return
四、条件断点
程序中的while循环可能会循环个几万次甚至千万次,如果我想看最后几次循环时的数据怎么办呢?
如果不停的F5,说不准能按上一个月……
那当然是有方法的,右键断点并选择条件,在条件里面输入一个表达式
对于下面的两张图,当且仅当l+0.01≥r(二分快结束)时,这个断点才会生效
五、即时窗口
即时窗口是个很强大的功能,它可以在不改变当前调试步骤的情况下修改变量值或者执行一些语句
例如下面的程序刚执行到第33行(第一次进入循环,m还是垃圾值)
但是我可以在右下角的即时窗口给m赋值为666,并且修改r=100000
因为是入门,就暂时讲到这了,还有很多很强的功能比如调用堆栈等以后有机会再看吧