信息学竞赛中调试方法的建议(对拍程序怎么写?)

http://www.360doc.com/content/18/0308/23/5315_735520558.shtml

 

信息学之于其他竞赛学科的不同,就在于需要通过写程序来表达自己的思维和想法。如何尽可能又快又好地调试程序,成了我们必须要思考的问题。相信很多同学都有过这样的经历:思考一个算法只花了半个小时,但是把这个算法写对却花了一天。。思考与实现的时间往往不成正比。

下面是我结合自己的经验给出的一些小建议,仅供大家参考,如果有不太好的地方,也欢迎指正~

关于调试有一个大前提,就是思考的方向一定得严谨正确,因为思考决定实现,如果思考的时候有漏洞,那么实现的程序肯定也不强健。在想出算法之后不要急着实现,一定要认真反复地论证:我的算法每一步的定义是否严谨,是不是哪里还有漏洞,我的算法所得到的东西是否就是题目需要求解的。确认了自己的想法后再开始实现。

假设我们现在写完了一个程序:

第一步:静态查错(俗称裸眼观察^_^),即不测试数据,而是通过反复地看代码来检查。静态查错首先要检查是否有变量名打错,语法是否正确,你打的代码和你的想法是否相符。然后要分析代码的逻辑性是否严谨正确,是否能在所有情况下都能正确运行。最后还要验证是否在所有边界情况都能得到正确的解,包括数组是否开够,会不会有n=0的情况等等。静态查错是最有效的查错方法,为什么有的大牛能够一遍写对很复杂的代码,因为他们静态查错的能力非常之强,并且在敲程序的过程中就已经在静态查错了。在实践中,我建议大家尽量让自己的程序模块化(即一个函数做一件事情),然后检查的时候边看边打上注释,这样能让自己更清醒地判断,也方便以后能轻松阅读自己的程序。

第二步:动态查错,用数据来验证代码的正确性。人眼往往不可靠,我们需要用更安全的数据来判定。一般而言在普通的OI竞赛中,时间是比较充裕的,我们有时间来对拍。对拍需要三个程序,一个是你需要提交的标准程序(std),一个是能够通过部分数据的暴力程序(plain),一个是用来生成数据的程序(mk_data)。

关于plain程序,一般会比较好写,所以一定要认真检查,不要写错!

关于mk_data,一般需要得到一个随机的整数,c++语言写法如下:

我们可以运行一次mk_data,得到一组数据,然后分别用std和plain跑一遍,看结果是否一样。当然这样手动是比较麻烦的,我们可以用脚本来自动对拍,下面是windows下用bat脚本对拍的普通写法:

(约定plain的输出文件是1.out,std的输出文件是2.out)

将这一段话写在一个文本文件中,将其重命名为ck.bat,然后和上述三个程序放在同一文件夹下,双击ck.bat,就能够实现对拍了。对拍的优势在于能够近似模拟出出题人的数据来检验你的程序,一般在考场上通过了对拍的程序很难写挂。当然有的时候随机数据不一定能够满足我们的需求,这时候需要我们从出题人的角度出发,去构造一些最坏情况下的数据,来检验我们程序的强健性。

第三步:提交之前,检查文件名,再次编译程序,运行一遍样例,以防手抽。

静态差错大大降低了程序出错的概率,减少了动态调试的时间,动态查错给程序上了双保险,最后的检查防止了意外情况的出现。这样的程序的正确性能够大大提高。

在调试中,最关键的一点,是站在逻辑的高度去思考程序,而不是从某个数据的角度去查看变量,这样才能避免陷于调试的泥潭不能自拔。

 

 

 

对拍程序

 分享| 2012-08-14 12:22cao199338 | 浏览 5418 次

 编程语言

ACM的程序怎么设置对拍程序??有没有那个好心人给我和例子吧,
基本思路是对于一道题目来讲,写出高效算法后,时间充裕的情况下再写一个纯暴力的算法,写一个数据生成器,对你的程序和暴力程序的结果进行比对,出现错误后就人工检查。一般来讲数据范围一开始可以小一点,小数据过了以后再慢慢扩大,为保证正确性你在写下一题的时候可以让对拍程序一直跑着。
这是别人说的,可是那个数据生成器和高效程序和暴力程序都是什么啊?不明白。
有完整例子可以加分。。

———————对拍程序介绍,来自百度—————————————–
在信息学竞赛中,尤其是考试的时候,经常会出现把水题写水的情况,而题目那一两个单薄的测试数据常常不足以让我们发现自己程序中的BUG。在竞赛时,水题悲剧了的话下场一定会很惨。在这种情况下,我们可以采用写一个对拍程序的方法来大大降低出错的可能。
基本思路是对于一道题目来讲,写出高效算法后,时间充裕的情况下再写一个纯暴力的算法,写一个数据生成器,对你的程序和暴力程序的结果进行比对,出现错误后就人工检查。一般来讲数据范围一开始可以小一点,小数据过了以后再慢慢扩大,为保证正确性你在写下一题的时候可以让对拍程序一直跑着。
这里的关键是要写一个批处理让Windows不停地反复执行这一操作,代码如下。
我会不停的加分。直到200分、

2012-08-20 18:11

提问者采纳

 

对拍程序的写法如下
@echo off  
:loop  
    datamaker   #数据生成器 rand.exe > data.in  
这里的大于符号,小于符号为重定向符号
    std      #标准程序  std.exe < data.in > std.out
    myprogram   #my.exe < data.in > my.out   我的程序
    fc ans.out std.out    //比较两个程序的输出是否一致,一致则返回0
if not errorlevel 1 goto loop  
pause  
goto loop

#最后上边的内容保存为.bat文件
#rand.exe  std.exe  my.exe 以及windows下的这个 .bat文件放在同一个目录下
***************************************************************************************************
这里数据生成器:就是你自己编写一个应用程序 rand.exe,这个应用程序就是随机的生成一组符合题意的输入数据并存放到上边提到的输入数据文件中data.in
高效程序:就是上边提到的高效算法写的程序,即 my.exe
暴力程序:就是指能够保证所有输入数据都能输出正确结果的程序,即这里的std.exe
上边的.bat文件的功能就是循环判断高效程序和暴力程序在同样的输入数据情况下,输出数据是否相同,从而实现了对拍程序的功能

追问:

厉害,不过可不可以提供一个现实程序的例子。发邮箱也行。。主要是不知道该怎么写数据生成器,高效程序和暴力程序、谢谢。
406182143@qq.com

追答:

比如举一个简单的例子:求 1+2+3+……+n = ?
数据生成器:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
 int n;
 srand((int)time(0));  //调用srand()函数,以系统时间为随机种子
 n = 1 + rand()%10000;  //随机生成一个1到10000的自然数
 printf(“%d\n”,n); // 输出随机生成的自然数
 return 0;
}
 
//编译运行后,生成rand.exe可执行文件 然后在批处理文件中直接调用 rand.exe>data.in即将上边的输出结果重定向到data.in文件中
 
暴力程序:算法是直接从1加到n,执行n次循环时间复杂度为 O(n)
#include<stdio.h>
#include<stdlib.h>
int main()
{
 int i,n;
 long int sum = 0;
 scanf(“%d”,&n);
 for(i=1;i<=n;i++)
 {
  sum += i;
 }
 printf(“%d\n”,sum);
 return 0;
}
 
//编译运行后,生成std.exe可执行文件 然后在批处理文件中直接调用 std.exe<data.in>std.out即将从data.in中获取输入,然后将输出结果重定向到std.out文件中
 
高效算法:算法为 1+2+……+n = n*(n+1)/2,   时间复杂度为O(1)
#include<stdio.h>
#include<stdlib.h>
int main()
{
 int n;
 long int sum = 0;
 scanf(“%d”,&n);
 sum = n*(n+1)/2; 
 printf(“%d\n”,sum);
 return 0;
}
 
//编译运行后,生成my.exe可执行文件 然后在批处理文件中直接调用 my.exe<data.in>std.out即将从data.in中获取输入,然后将输出结果重定向到my.out文件中
批处理文件 test.bat内容如下
@echo off  
:loop  
    rand.exe>data.in  
    std.exe<data.in>std.out
    my.exe<data.in>my.out  
    fc my.out std.out  
if not errorlevel 1 goto loop  
pause  
goto loop
最后将这三个.exe文件和批处理文件放到同一个目录下运行批处理文件即可

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值