在写完代码的时候,测一下样例,很多时候样例过了,但交到OJ上却挂了,始终找不到错误原因。有时候连样例都过不了。因此,我总结了三种方法教给大家,让大家有方向地去查错,而不是看着程序发呆。希望大家可以把三种方法熟练掌握,并懂得去运用。
目测法并不是简单的目测。
此方法用于数据小且少的题目。
用例子来说话:
FZU-1889 龟兔赛跑
原题 vjudge
这题其实很简单。
直接给代码。
#include
#include
#include
#include
#include
#define R register int
#define re(i,a,b) for(R i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
int main() {
int X;
scanf("%d",&X);
while(X--) {
int t,k,u,v;
scanf("%d%d%d%d",&t,&k,&u,&v);
int a=(t-k)*u;
int b=t*v;
if(a>b) printf("0\n");
else if(a<b) printf("1\n");
else printf("-1\n");
}
return 0;
}
这题固然简单,但万一你在测样例的时候错了。
目测法应该是比较好的方法。
那到底怎么目测呢?
比如t=6,k=3,u=6,v=3
读入:
scanf("%d%d%d%d",&t,&k,&u,&v);
计算:
int a=(t-k)*u;
int b=t*v;
把此时的计算结果牢牢记在脑子里。
判断输出:
if(a>b) printf("0\n");
else if(a<b) printf("1\n");
else printf("-1\n");
这有点想NOIP初赛里的看程序写结果。
Dev-cpp这个软件自带调试功能,但我建议大家不要用。
我希望大家手动调试。
原因:
1 Linux环境下没有Dev-cpp这个软件
2 许多大神用的都是Linux,他们没有用这种调试功能
3 手动调试可以提高你对代码的熟悉程度和熟练程度
4 某些比赛不提供Dev-cpp这个软件
5 当程序复杂的时候,用自动调试很困难
6 用手动调试可以加快打字速度,以免在比赛的时候来不及
好,废话不说,直接开始讲。
完。
比如说很多初学者会犯这样的错误:
int main() {
int i=0;
int a[20];
while(i++) {
scanf("%d",&a[i]);
if(i==10) break;
}
return 0;
}
运行一下发现没有读入。
你可以这样:
int main() {
int i=0;
int a[20];
while(i++) {
scanf("%d",&a[i]);
cout << "###" << endl;
if(i==10) break;
}
return 0;
}
这是看while()循环有没有执行
也可以这样:
int main() {
int i=0;
int a[20];
while(i++) {
scanf("%d",&a[i]);
cout << a[i] << endl;
if(i==10) break;
}
return 0;
}
看一下a[i]有没有被读入。
其实把i++改成++i就可以了。
注意:调试完了一定要删除调试的语句,或这样:
//cout << a[i] << endl;
不然很可惜,你就WA了。
对拍,又称“对答案”。
这种方法相对来讲就比较高级了。
在OI/ACM比赛中,这种方法是很常见的。
比如说我要检查一段高精度加法有没有写错。
对拍是最好不过的选择。
它比手动造数据强多了。
(C++高精度模板:点击这里)
make.cpp 用于自动制造数据
my.cpp 中放入你要检查的程序(高精度加法程序)
std.cpp 中放入标程(低精度加法程序)
//std.cpp
#include
using namespace std;
int a,b;
int main() {
cin >> a >> b;
cout << a+b << endl;
return 0;
}
//make.cpp
#include
using namespace std;
int main() {
srand(time(0));
int a=rand()%1000+1;
int b=rand()%1000+1;
cout << a << endl << b << endl;
return 0;
}
下面开始解释:
srand(time(0));
上者是播放随机种子,为制造随机数埋下伏笔。
int a=rand()%1000+1;
int b=rand()%1000+1;
上着是产生随机数。
r a n d ( ) rand() rand() 可以产生 0 ~ 215-1 这个范围内的随机数。
r a n d ( ) rand() rand()%1000+1 就是产生1 ~ 1000 这个范围的随机数。
如果你想更数据更大,可以尝试这样写:
long long a=1LL*rand()*rand()*rand();
long long b=1LL*rand()*rand()*rand();
cout << a << endl << b << endl;
上者是输出 输入数据。
其目的是为了生成exe文件
千万不要双击打开
@echo off
:loop
make > std.in
echo %time%
std < std.in > std.out
echo %time%
my < std.in > my.out
echo %time%
fc std.out my.out
if errorlevel=1 pause
goto loop
这段话的分析:
make > std.in
用make.exe制造输入文件std.in
echo %time%
输出时间t1,得到程序开始的时间
std < std.in > std.out
运行std.exe得到标准输出文件
echo %time%
输出时间t2, t 1 − t 2 t1-t2 t1−t2就是std.exe运行所用的时间
my < std.in > my.out
运行my.exe得到my.cpp的输出文件
echo %time%
输出时间t3, t 3 − t 2 t3-t2 t3−t2就是my.exe运行的时间,这可以检查你的my.cpp是否超时
fc std.out my.out
比较std.oout和my.out是否相同,结果返回到errorlevel
if errorlevel=1 pause
如果errorlevel=1(比较结果不相同),那么pause(暂停)
@echo off
:loop
goto loop
无限循环
如果你的程序有错,就会出现这样的情况:
出现不同。
这个意思就是你的程序错了。
此时关闭run.bat
在文件夹中,你会找到std.in这个文件
这就是使你程序错的输入数据。
把你的程序改正之后,再次运行run.bat 看是否有错。