• 代码调试技巧【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
    "
      else
          printf "Wa
    "
          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<<"
    ";
    }

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

    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<<"
    ";
    random_shuffle(e+1,e+m+1);
    for(int i = 1; i <= m; i++)
        cout<<e[i].first<<" "<<e[i].second<<"
    ";

    5 静态查错

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

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

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

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

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

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

    6 其他一些

    1. 重写代码(雾

    2. 拒绝调试(逃

  • 相关阅读:
    iOS中的两种主要架构及其优缺点浅析
    iOS
    iOS开发人员不容错过的10大工具
    安装CocoaPods报错
    把你唱的歌用乐器表达出来

    String.Split函数
    四部和声
    SerializeField和HideInInspector
    十年许嵩雅俗共赏
  • 原文地址:https://www.cnblogs.com/gwj1314/p/9444874.html
Copyright © 2020-2023  润新知