代码调试技巧【OI缩水版】
1 小黄鸭调试法
来自维基:小黄鸭调试法是软件工程中使用的调试代码方法之一。
就是在程序的调试、纠错或测试过程中,耐心地向小黄鸭解释每一行程序的作用,以此来激发灵感。
2 输出中间值
在关键位置输出值
适用于以下一些:
数据输入,输出
死循环,盏溢出
过程值,语义分析(较痛苦
much more :
适用于细节手误没看到。
操作函数化,分块测试,能独立测试的算法部分先验证其正确性。
对照神犇代码,用一样的部分替换掉自己代码,并测试答案。
3 断点、单步
GDB调试技巧
我也不会啊,我也很无奈啊。
4 对拍
大量随机数据测试,正确性判断
步骤
- 写好程序和暴力
- 写好数据生成器
- 写好对拍文件
关于对拍脚本
”Windows 环境下对拍文件.bat
“用重定向的方式代替代码内的文件输入输出
@echo off "关掉屏幕显示
:loop "循环
rand.exe %random% > input.txt “随机生成数据
test.exe < input.txt > test.out ”运行错解
std.exe < input.txt > std.out “运行标程
fc test.out std.out “比较输出
if errorlevel 1 pause ”如果不同就停下来
goto loop “重复循环
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
#Linux 环境下对拍文件.sh
#!/bin/bash
while true; do
./rand > input.txt
./test < input.txt > test.out
./std < input.txt > std.out
if diff std.out test.out; then
printf "AC\n"
else
printf "Wa\n"
exit 0
fi
done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
关于数据生成器
#include<cstdlib>
#include<ctime>
int random(int n){//返回一个[0,n-1]的随机整数。
return (long long)rand()*rand()%n;
}
int main(){
srand((unsigned)time(0));
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
1.随机生成整数序列
int n = random(100000)+1;
int m = 1000000000;
for(int i = 1; i <= n; i++)
a[i] = random(2*m+1)-m;
- 1
- 2
- 3
- 4
2.随机生成区间列
for(int i = 1; i <= m; i++){
int l = random(n)+1;
int r = random(n)+1;
if(l > r)swap(l,r);
cout<<l<<" "<<r<<"\n";
}
- 1
- 2
- 3
- 4
- 5
- 6
3.如何生成一棵树?
for(int i = 2; i <= n; i++){
//从2~n之间的每个点i向1~i-1之间的点随机连一条边
int fa = random(i-1)+1;
int val = random(1000000000)+1;
cout<<fa<<" "<<i<<" "<<val<<"\n";
}
- 1
- 2
- 3
- 4
- 5
- 6
4.如何生成一张图?
pair<int, int>e[1000005];//保存数据
map<pair<int,int>,bool>h;//防止重边
//先生成一棵树,保证联通
for(int i = 1; i < n; i++){
int fa = random(i)+1;
e[i] = make_pair(fa,i+1);
h[e[i]] = h[make_pair(i+1,fa)] = 1;
}
//再生成剩余的m-n+1条边
for(int i = n; i <= m; i++){
int x, y;
do{
x = random(n)+1, y = random(n)+1;
}while(x==y || h[make_pair(x,y)]);
e[i] = make_pair(x, y);
h[e[i]] = h[make_pair(y,x)] = 1;
}
//随机打乱,输出
cout<<n<<" "<<m<<"\n";
random_shuffle(e+1,e+m+1);
for(int i = 1; i <= m; i++)
cout<<e[i].first<<" "<<e[i].second<<"\n";
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
5 静态查错
程序按照思路编完之后,查编译错误。
编译全部修正后,千万不要测样例。
1、经验证明,第一次就把样例过了的几率很低,即使过了,在测自己的特殊数据的时候也会出错。所以,编译完后一定要静态查错。
2、经验表明,静态查错是很有效果的。基本上每次静态查错都可以找到变量代错的错误。特别是快排的I,J是否带错,DEC,INC是否搞错,SWAP是不是加了VAR等等。
3、试想:如果没有静态查错,就去测样例,如果程序有错,样例不过,影响心情;即使样例过了,因为程序有错,特殊数据也不一定能过;即使特殊数据也过了,程序有错,评测的时候绝对会错。发现错了,影响心情了,还是要来静态查,心情不好,肯定效率低。那还不如一开始就静态查,即使发现错误,获得成就感,心情很好。千万不要慌着去测。
4、要保证程序无错,思路清晰,结构清晰了,然后再去测样例,再去测特殊数据。
样例过了不要得意,特殊数据过了不要得意,很有可能还有很多特殊情况你没有想到。
(1)是否写上了using namespace std? (这是C++的,Pascal就不用了)
(2)数组开得是否够大?
(3)变量类型是否正确?
(4)memset时,所填的sizeof(XX)的XX是不是匹配?大小是不是正确? (Pascal 是 fillchar)
(5)外层循环与内层循环的i,j是不是混用了?
(6)循环之前,i,j是否定义了?
(7)输入数据都输入了吗?
(8)这个程序是在执行你想让它执行的步骤吗?
6 其他一些
重写代码(雾
拒绝调试(逃
文章来源: gwj1314.blog.csdn.net,作者:小哈里,版权归原作者所有,如需转载,请联系作者。
原文链接:gwj1314.blog.csdn.net/article/details/79980970
- 点赞
- 收藏
- 关注作者
评论(0)