C++ 以及普及组选手多使用静态查错法与输出调试法
提高组选手可以适当使用对拍调试法
[https://www.bilibili.com/video/BV1sQ4y1K7T4/ 初级调试指南视频版]
[https://www.bilibili.com/video/BV1he411p74Y/ 高级调试指南视频版]
= 调试指南 =
1:在草稿纸上模拟程序的运行,写下一些关键变量的中间结果
2:利用打印调试法打印出这些中间变量的值
3:对比观察
下面介绍利用数据去查错的几种查错方法
== 静态查错法 ==
静态查错法的意思是说,写完程序,先整体浏览一遍代码,把一些肉眼可见的,明显发现是错的地方修改掉
根据以往的经验,我们发现,一个选手功力越深,静态查错的时候能发现的问题越多,往往大多数错误不需要下面的方法就已经查出来了。
== 输出调试法 ==
首先,我们运行了一组数据,发现结果不对,然后静态查错也没看出什么来,这个时候我们采用输出调试法。
1:先 分段 打印一些变量,观察变量的值跟预想的对不对,找到最先不对的地方,然后检查,这个时候下面的代码就不用看了
2:不停的重复 1 的行为,不断的缩小定位错误区域,直到所有的错误修复完毕
举个例子
比如下面这个程序,题库链接:https://517coding.com/p/1100
#include<bits/stdc++.h>
using namespace std;
int a[10010];
int b[10010];
int main(void){
int n,m;
int k=-1e9;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(a[i]+b[j]>k) {
//下面这行代码是用来打印调试的语句
printf("i=%d j=%d sum=%d\n", i, j, a[i]+b[j]);
k=a[i]+b[j];
}
}
}
printf("%d",k);
return 0;
}
/*
错误数据:
2 3
1 2
1 2 3
*/
我们可以在循环里面加一句 printf 语句打印关键信息,然后运行代码下方的错误数据,我们发现会输出如下信息
2 3
1 2
1 2 3
i=1 j=1 sum=2
i=1 j=2 sum=3
i=2 j=2 sum=4
4
可以发现,答案明明是 5,但是却输出了 4,而且中间过程也并没有产生 5,而答案 5 是来自于第一个数组中的 2 与第二个数组中的 3 相加得到的,此时我们通过调试信息的输出并没有发现这两个数被同时枚举到,于是我们检查两个 for 循环,这个时候发现了两个 for 循环枚举的都是 1 到 n,而实际上,第二个循环应该枚举 1 到 m,修改之后,这个程序就可以正常通过了
== 对拍调试法 ==
=== duipai.sh ===
#!/bin/bash | |
t=0; | |
while true; do | |
let "t = $t + 1" | |
printf $t | |
printf ":\n" | |
./rand > rand.txt | |
./AC < rand.txt > AC.out | |
./WA < rand.txt > WA.out | |
if diff AC.out WA.out; then | |
printf "\n" | |
else | |
printf "WA\n" | |
cat rand.txt | |
break | |
fi | |
done |
=== run.bat ===
:loop
@echo off
gen.exe > in.txt
my.exe < in.txt > myout.txt
std.exe < in.txt > stdout.txt
fc myout.txt stdout.txt
if not errorlevel 1 goto loop
pause
=== std.cpp ===
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
cout << a + b << endl;
return 0;
}
=== my.cpp ===
#include <bits/stdc++.h>
using namespace std;
//这是一个错误程序
int main() {
int a, b;
cin >> a >>b;
if (a > 130 && b > 130) {
cout << a - b << endl;
} else {
cout << a + b << endl;
}
return 0;
}
=== gen.cpp ===
#include <bits/stdc++.h>
using namespace std;
// 返回0到x-1之间的随机数
// rand()函数返回 0-32767之间的一个随机数
int get_rand(int x) {
return rand() * rand() % x + 1;
}
//返回L 到 R之间的整数
int get_rand(int L, int R) {
return rand() * rand() % (R-L+1) + L;
}
int main() {
//初始化随机种子
srand(time(0));
int a, b;
//生成一组随机数据
a = get_rand(1, 200);
b = get_rand(1, 200);
cout << a << " " << b <<endl;
return 0;
}