关于Debug

关于Debug
一、Debug
(1)如何判断程序有bug:
··········《1》显然,答案错了一定有bug
··········《2》构造特殊数据,使劲考验自己的程序
··········《3》多看几遍,分析逻辑有无错误

(2)怎么找bug:
··········《1》先把-Wall打开,emacs用指令,其他编译器直接在设置里打开就行

指令如下
g++ 123.cpp -o 123 -Wall

不开-Wall某些编译错误是不能被显示的,比如下文里常见bug第一位
··········《2》输出法:
···············【1】输出运行次数:这个很实用,因为很多时候答案错误的原因是因为某些应当运行多次或者进入递归的函数,只运行一次或者根本没运行
···············【2】输出某些关键值&把数组打出来:这个没什么好说的,直接手算小数据,然后和输出对比一下就行
··········《3》各种奇奇怪怪的编译设置:某些编译器里有,而且据说功能很离谱。but比赛里肯定是没有的。

二、我遇到的一些比较常见的bug
类型一:输入输出
(1)输入:比如你打了多个%d,却只有&a,这个时候不开-Wall是不会报错的。
(2)输入2:没打取地址符,这个不开-Wall也不会报错,表现是直接RE
(3)输入3:输入格式
(4)输出:估计不会有出题人无聊到这个程度,但是要看清输出的到底时什么

类型二:预处理类
(1)图论:head数组初始值一定要记得赋成-1!!!(当然习惯从0开始的就不必看这条了)

but记一次灵异事件:我也记不住是哪一道图论题了,反正别人从-1开始都能过,但是我的写法改成从0开始才能过。现在找不到那道题了,有机会补上。
总之能想起来这里也会出现奇怪的错误就好,毕竟有些bug实在过于玄学。

(2)线段树:.....不说了记得建树,不知道忘了多少次了。扫描线记得离散化,不离散化直接升天。

(3)动态规划或者很多其他题型求最小值时,一定要记得把初值赋成inf。
还有有的题解里,会有取min不需要初值的现象,比如下面这个树形dp的节点覆盖

	f[x][0] += min(f[v][2], f[v][1]);
        f[x][1] += min(f[v][2], f[v][1]);
        d = min(d, f[v][2] - min(f[v][2], f[v][1]));
        f[x][2] += min(f[v][2], min(f[v][1], f[v][0]));

这里转移式写的都是+=,因此一定会被更新,故初值为0即可

类型三:杂项,什么都有
(1)关于数组下标为0:比如我们经常会用f[i][0]来存储点i有几个子节点,或者循环迭代处理到第i个数时的情况总数,又或者是f[0]在prim里充当inf的作用(因为初值是inf,而f[0]不会被更新)。
但是有很多情况点的编号是从0开始的,因此如果不假思索直接背板子就会直接WA掉

(2)经典中的经典:循环

for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++i)

然后就死循环了,仔细一看就会发现第二层循环里根本没有处理j。
所以说要好好看看自己的循环都写了写什么

(3)inline:
有返回值的&函数递归的时候尽量不要使用
再说了inline也就是个心理安慰,快不了多少

(4)思路错误:
。。。。。。这个就自己悔改去罢!
记得分析清楚了再写题

三、关于debug的总结
(1)一定要分析清楚题意、仔细思考自己的思路、证明其正确性后再开写,边想边写又慢又容易错
(2)debug不要耗费太长时间,毕竟我就干过在4h的比赛里debug用了1.5h结果还没改对的结果
(3)debug需要耐心:看到程序有问题,经常下意识地觉得是核心部分出错了,但是其实很多情况只是一些无关紧要的预处理或者输入输出的错误。多看几遍总能发现。
(4)debug这个事情还是要靠自己的,总是依靠别人找问题结果就是代码能力差的一批,每天日常就是想出来了结果不会实现。
别问我怎么知道最后一条的....

posted @ 2021-08-31 20:41  Mint-hexagram  阅读(49)  评论(2编辑  收藏  举报