错误代码的修改方法


大前提:先自己算一遍样例,搞清楚正确答案是怎么来的

这步最容易被跳过,但其实最重要。很多同学一上来就盯着代码看,看半天也不知道哪里错,因为你还不知道什么叫“正确”,自然不知道哪里错了。

比如做切绳子那道题,先拿样例自己算一遍:

  • 4条绳子,要切11条一样长的
  • 8.02能切4条2.00的,7.43能切3条,4.57能切2条,5.39能切2条,加起来正好11条
  • 此时如果代入测试2.01,你会发现总共只能切出10条
  • 所以最大长度是2.00
    自己手动跑通样例,把每一步怎么算的记下来,后面看代码的时候,就有个“标准答案”去比对,哪里不一样一眼就能看出来。

方法1:读代码(适合简单逻辑,或者你已经大概锁定目标了)

如果代码不长,或者你刚才算样例的时候,感觉某一步可能有问题,就直接读代码。

读的时候不是通读,是对照你刚才的手动流程读,比如你算获奖人数是 p * w / 100,就看代码里是不是这么写的,算式是否一致;你模拟冒泡是从后往前换,就看代码里循环的方向对不对。这一步能解决一些低级错误,比如变量名写错、符号写反、循环边界写错。建议别花太多时间干读,读不出来就用其他办法。


方法3:添加输出(粗定位错误)

如果读代码没看出来,或者代码逻辑比较复杂,就加输出语句看看中间结果。这是获取“代码里到底发生了什么”的方法。

具体操作:

  • 对照你的手动流程,把关键变量每一步的值都打出来。典型就是统计类的变量:sum总和、cnt计数器、flag标志量、函数调用的返回值之类的,都是典型的中间结果。
  • 运行代码,把输出的结果和你手动算的结果逐行比对
  • 比如你手动算中间结果是5,代码输出是3,那就是这一步的计算写错了
  • 又比如说,你代码无限循环了,不知道哪个循环的问题,就给循环里写个测试输出,比如输出!,如果真无限输出了,就是这个循环的问题。如果有多个循环,就挨个往里放输出语法测试。
  • 知道哪个循环无限循环了,要想进一步知道原因,可以再输出和你循环条件相关的变量,看到底怎么变的,为什么没触发失败(退出)

方法3:debug调试

如果加输出找到了大概的错误位置,但还是不知道具体为什么错,就用IDE的debug功能,但能精准看到每一步的变化。具体说就是让程序一句一句运行,且能看到执行中的实际状态和数据值,相当于另类的阅读程序。

大前提永远不变:先手动算一遍样例

在碰调试之前,先拿样例在草稿纸上完完整整手动跑一遍

  • 你要知道正确的执行流程是怎样的
  • 你要知道每一步变量应该变成什么值
  • 你要知道程序大概在哪几步会做什么操作

没有这个“标准答案”,就算调试时看着变量跳,你也不知道它跳得对不对,看也白看。


设置方面:Dev-C++ 编译模式调为 64bit - debug,默认都是64bit - release

另外注意:你的代码文件必须放在全英文路径里,不能有中文文件夹名,不然断点可能会失效。此时要么新建个项目调试,要么把CPP文件干脆放D盘根目录下。
另外每次调试前必须先点一下编译


Dev-C++ 调试功能介绍

1. 下断点

断点是让程序停下的位置,大概估计一下哪里会出错,然后在对应行标数字上点一下,整行会变红色。

2. 开始调试

点底部的「调试[D]」按钮,或者按快捷键 F5,程序就会进入调试模式,弹出运行窗口。
一般我们的断点都下在输入语句的后面,所以点调试后会先弹出运行窗口并让你输入,正常输入并回车就行。
程序会自动运行到第一个断点处停下,此时断点行会变为蓝色,蓝色就是当前执行到哪一行了的标志,注意是即将执行的一行,所以比如这一行是a=0,你添加查看会看到a不一定等于0,点了下一步执行了才会变0。

3. 下一步

  • 执行一句代码,但注意如果遇到函数调用不会钻进去,会直接把整个函数执行完,停在函数调用的下一行。

4. 单步进入

  • 也是执行一句,但如果当前行是函数调用,会直接钻到函数的第一行代码里,这里说的是自己写的函数类似check,C++库函数不行。
  • 什么时候用:你怀疑就是这个函数内部算错了,想进去细调。

5. 跳过

  • 跳到下一次断点位置,比如你在一个循环里,你已知第10次循环输出的值不对,你想快速来到第十次循环,直接给循环里下断点,然后点九次跳过,就能不断跳到下一次循环,快速定位到某一次。
  • 又比如你有个程序,有三个循环,你调试到某一步了,想先看看接下来这个循环的结果对不对,不想直接进去一句一句走,就可以给循环结束后的行下个断点,然后点跳过,直接跳过去。如果发现结果是错的,说明就在上面这个循环里有问题,再停止调试,重新给循环里下个断点,类似于先粗调,再细调。

6. 添加查看[A]

  • 添加你要监视的变量,实时看它的值变化,临时想看一眼的直接鼠标挪到变量名上就会显示。注意数组也可以查看,字符串也行,但结构体之类的不行。
  • 注意:只有程序运行到变量的作用域里,才能看到值,比如在循环外面看循环里的i,就会显示红色。

7. 停止执行

  • 找到错误了,不想继续跑了;或者调试错了想重来,就点停止执行。注意直接关闭运行窗口调试不会结束。另外没有上一步功能,如果点快了没看清到底哪一句开始错的,就得停止执行再来一遍。

调试的核心策略:先粗调,再细调,从第一行开始调没意义。

第一步:粗调——用断点快速缩小错误范围

  1. 先给代码的关键节点下断点,这里的关键节点其实就是上面添加输出中说到的那些变量,比如总和、个数之类的。
  2. 按F5开始调试,程序会在第一个断点停下,你看一下关键变量的值对不对:不对的话,就说明错误就在上一个断点和当前断点之间的代码里
    当然这一步也可以用添加输出的方式完成。

第二步:细调——在小范围里逐句预判找错

锁定了错误范围后,就在这个范围的开头下一个断点,重新调试跑到这里停下,然后开始逐句走。
逐句走的核心:预判!
不是光看着变量变,在你按下一步之前,必须先在心里算一遍:

  • 这行是if判断,根据现在的变量值,条件应该是真还是假?程序应该进哪个分支?
  • 这行是计算,a = b + c,现在b是2,c是3,a应该变成多少?
  • 这行是循环,这次循环应该执行几次?变量i应该变成多少?

算完预判结果,再按下一步,看实际结果和你预判的一不一样。


标签: none

评论已关闭