数据对拍是一种通过找到错误输出数据寻找bug的方法;

首先,我们可以跟据题意通过bfs,暴力等方法写出一份正确的代码,然后写个随机生成数据和验证输入输出的代码

我们可以拿一道题来熟悉这个流程:

路径规划(route)

题意很好理解,就是给出起点,和终点,求出起点到终点的所需的步数,其中上下左右,斜着走八个方向都算一步;

大致思路就是,优先斜着走,因为斜着走即在水平方向有位移,在竖直方向也有位移;

这里有一份根据该思路的错误代码:

//01.cpp
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
int main()
{
	
	int a,b,c,d;
	scanf("%d %d %d %d",&a,&b,&c,&d);
	int dx = abs(c - b);
	int dy = abs(d - b);
	printf("%d\n",max(dx,dy));
	return 0;
}

1.这时候如果我们想用数据对拍来找bug的话我们可以写一个用bfs思路的正确代码,以下是bfs的正确代码;

//02.cpp
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue> 
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{
	int x,y,step;
	node ()
	{
	}
	node(int p_x,int p_y,int p_step)
	{
		x = p_x;
		y = p_y;
		step = p_step;
	}
};
int dir[9][2] = {1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,-1,-1,1};
int n,m;
int mark[305][305];
int main()
{
	int a,b,c,d;
	scanf("%d %d %d %d",&a,&b,&c,&d);
	queue <node> que;
	que.push(node(a,b,0));
	int res = 0;
	while(!que.empty())
	{
		node fro = que.front();
		if(fro.x == c && fro.y == d)
		{
			res = fro.step;
			break;
		}
		que.pop();
		for(int i = 0; i < 8; i++)
		{
			int tx = fro.x + dir[i][0];
			int ty = fro.y + dir[i][1];
			if(tx >= -100 && tx <= 100 && ty >= -100 && ty <= 100 && mark[tx+105][ty+105] == 0)
			{
				mark[tx + 105][ty + 105] = 1;
				que.push(node(tx,ty,fro.step + 1));
			}
		}
	}
	printf("%d\n",res);
	
	
	
	
	
	
	return 0;
} 

2.如果我们想通过验证输入数据来找出错误数据的话,我们需要讲以上两份代码的输入输出重定向到文件流。

也就是把输入的数据通过文件输入,并将输出的数据输出到文件;

以下:

//01.cpp
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
int main()
{
	freopen("input0.in","r",stdin);
    freopen("ouput1.out","w",stdout);
	int a,b,c,d;
	scanf("%d %d %d %d",&a,&b,&c,&d);
	int dx = abs(c - b);
	int dy = abs(d - b);
	printf("%d\n",max(dx,dy));
	fclose(stdin);
    fclose(stdout);
	return 0;
}
//02.cpp
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue> 
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{
	int x,y,step;
	node ()
	{
	}
	node(int p_x,int p_y,int p_step)
	{
		x = p_x;
		y = p_y;
		step = p_step;
	}
};
int dir[9][2] = {1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,-1,-1,1};
int n,m;
int mark[305][305];
template <typename T>
T RandomData(T a, T b,T c)
{
	if(c <= b )
	{
			return rand() % (b - a + 1) +  a;
	}
	else 
	{
		T temp;
		while(true)
		{
			temp = rand()  % (b - a + 1) + a;
			if(temp != c)
			{
				return temp;
			}
		}
		
		
	}
}
int main()
{
	freopen("input0.in","r",stdin);
    freopen("output2.out","w",stdout);
	int a,b,c,d;
	scanf("%d %d %d %d",&a,&b,&c,&d);
	queue <node> que;
	que.push(node(a,b,0));
	int res = 0;
	while(!que.empty())
	{
		node fro = que.front();
		if(fro.x == c && fro.y == d)
		{
			res = fro.step;
			break;
		}
		que.pop();
		for(int i = 0; i < 8; i++)
		{
			int tx = fro.x + dir[i][0];
			int ty = fro.y + dir[i][1];
			if(tx >= -100 && tx <= 100 && ty >= -100 && ty <= 100 && mark[tx+105][ty+105] == 0)
			{
				mark[tx + 105][ty + 105] = 1;
				que.push(node(tx,ty,fro.step + 1));
			}
		}
	}
	printf("%d\n",res);
	fclose(stdin);
    fclose(stdout);
	
	
	
	
	
	
	return 0;
} 

可以看到,两份代码都是通过input0.in输入数据的,这里的input0.in的数据我们可以通过第3步的随机数据来获得。然后错误

代码的数据输出到output1.out里面,正确代码的数据输出到output2.out里面。

3.我们需要造出随机数据来作为正确代码和错误代码的输入,然后对别两份代码的输出文件进行寻找错误数据

如下:

//03.cpp
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<random> 
#include<algorithm>
#include <chrono>
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
using namespace chrono;
const int INF = 0x3f3f3f3f; 
mt19937 rng;  //声明一个随机生成器 

template <typename T>
T RandomData(T a, T b,T c)
{
    uniform_int_distribution<T> dist6(a, b); //指定范围 
	if(c > b)
	{
			return dist6(rng);
	}
	else 
	{
		T temp;
		while(true)
		{
			temp = dist6(rng);
			if(temp != c)
			{
				return temp;
			}
		}
	}

}

void makeData()
{

	FILE* fp=fopen("input0.in","w");
	int a = RandomData(-100,100,INF);
	int b = RandomData(-100,100,INF);
	int c = RandomData(-100,100,INF);
	int d = RandomData(-100,100,INF);
	fprintf(fp,"%d %d %d %d\n",a,b,c,d);
    printf("%d %d %d %d\n",a,b,c,d);	
	fclose(fp);
} 
int main()
{
	rng.seed(time(0));     //将时间作为随机生成器随机种子 
	for(int i = 1; i < 500; i++)
	{
		makeData();
		system("01.exe");
		system("02.exe");
		printf("Number:%d\n",i);
		if(system("fc output1.out output2.out"))
        {
            printf("Wrong Asnwer\n");
            while(1);     //使程序暂停1毫秒 
        } 
	}
	
	return 0;
} 

该代码会造出499组数据用来通过验证两个输出文件的差异来寻找bug;

当有差异的话该程序会自动停下并输出有差异的数据

请注意03.cpp中的53行代码和63行代码,47行是为了给随机函数通过当前时间设置一个随机种子,57行是通过使程序“休眠”

1毫秒使得随机种子起作用。

 

 

注意,在运行03.cpp之前,必须保证

1.三个cpp文件必须在同一文件夹下

2.01.cpp和02.cpp必须通过编译

如果想要生成小数的话,随机函数应该这样写

//03.cpp
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<random> 
#include<algorithm>
#include <chrono>
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
using namespace chrono;
const double INF = 0x3f3f3f3f; 
std::mt19937 rng;  //声明一个随机生成器 

template <typename T>
T RandomData(T a, T b,T c)
{
    uniform_real_distribution<T> dist6(a, b); //指定范围 
	if(c <= b)
	{
			return dist6(rng);
	}
	else 
	{
		T temp;
		while(true)
		{
			temp = dist6(rng);
			if(temp != c)
			{
				return temp;
			}
		}
	}

}

int main()
{
	
	rng.seed(time(0));
	while(true)
	{
		printf("%lf\n",RandomData(-10.0,25.0,INF));
	}
	return 0;
}

如果想生成随机字符应该这样写

//03.cpp
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<random> 
#include<algorithm>
#include <chrono>
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
using namespace chrono;
const double INF = 0x3f3f3f3f; 
std::mt19937 rng;  //声明一个随机生成器 

template <typename T>
T RandomData(T a, T b,T c)
{
    uniform_int_distribution<T> dist6(a, b); //指定范围 
	if(c <= b)
	{
			return dist6(rng);
	}
	else 
	{
		T temp;
		while(true)
		{
			temp = dist6(rng);
			if(temp != c)
			{
				return temp;
			}
		}
	}

}

int main()
{
	
	rng.seed(time(0));
	while(true)
	{
		printf("%c",RandomData('a','y','c'));
	}
	return 0;
}