OI调试技巧

1 小黄鸭调试法

来自维基:小黄鸭调试法是软件工程中使用的调试代码方法之一。

就是在程序的调试、纠错或测试过程中,耐心地向小黄鸭解释每一行程序的作用,以此来激发灵感。

2 输出中间值

在关键位置输出值

适用于以下一些:
数据输入,输出
死循环,盏溢出
过程值,语义分析(较痛苦
much more :

适用于细节手误没看到。
操作函数化,分块测试,能独立测试的算法部分先验证其正确性。
对照神犇代码,用一样的部分替换掉自己代码,并测试答案。

3 断点、单步

GDB调试技巧

我也不会啊,我也很无奈啊。

4 对拍

大量随机数据测试,正确性判断

步骤

  1. 写好程序和暴力
  2. 写好数据生成器
  3. 写好对拍文件

关于对拍脚本

”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 “重复循环
#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

关于数据生成器

#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.随机生成整数序列

int n = random(100000)+1;
int m = 1000000000;
for(int i = 1; i <= n; i++)
    a[i] = random(2*m+1)-m;

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";
}

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";
}

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";

5 静态查错

程序按照思路编完之后,查编译错误。

编译全部修正后,千万不要测样例。

1、经验证明,第一次就把样例过了的几率很低,即使过了,在测自己的特殊数据的时候也会出错。所以,编译完后一定要静态查错。

2、经验表明,静态查错是很有效果的。基本上每次静态查错都可以找到变量代错的错误。特别是快排的I,J是否带错,DEC,INC是否搞错,SWAP是不是加了VAR等等。

3、试想:如果没有静态查错,就去测样例,如果程序有错,样例不过,影响心情;即使样例过了,因为程序有错,特殊数据也不一定能过;即使特殊数据也过了,程序有错,评测的时候绝对会错。发现错了,影响心情了,还是要来静态查,心情不好,肯定效率低。那还不如一开始就静态查,即使发现错误,获得成就感,心情很好。千万不要慌着去测。

4、要保证程序无错,思路清晰,结构清晰了,然后再去测样例,再去测特殊数据。
样例过了不要得意,特殊数据过了不要得意,很有可能还有很多特殊情况你没有想到。

6 其他一些

  1. 重写代码(雾

  2. 拒绝调试(逃

猜你喜欢

转载自blog.csdn.net/qq_33957603/article/details/79980970
OI