# 对拍是什么

对拍,是一个比较实用的工具。它能够非常方便地对于两个程序的输出文件进行比较,可以帮助我们实现一些自动化的比较输出结果的问题。

众所周知,几乎每一道编程题目,都会有某种正解能拿到满分;当我们想不出正解时,我们往往可以打暴力代码来获取部分分数。

但是,当我们觉得有思路写正解,但又担心自己正解写的不对,而恰好,我们又有一个能够暴力骗分的代码。这个时候就可以用到对拍。 暴力骗分代码必须保证正确性,只是超出时间限制,不能出现答案错误的情况。

这样,我们可以造多组数据,让暴力骗分的程序跑一遍,再让我们自己写的正解跑一遍,二者进行多次对比。如果多组数据都显示二者的输出结果一样,那么这个正解大概率没问题。相反地,如果两组数据不同,我们就找到了一组错误数据,方便调试,找到正解哪里出了问题。

这便是对拍。其作用也在上文提出。

# 对拍的实现

# 准备基本代码

首先,我们要有 2 份代码,一份是这一道题 “你写的正解” 代码wa.cppwa.cpp,另一份是同一道题 “你打的暴力” 代码ac.cppac.cpp

两份代码有了,将它们全部编译。我们把它们放在同一个文件夹里。这样算是做好了对拍的准备。

Alt text

# 制作数据生成器

也就是data.cppdata.cpp

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll Random(ll mod) {
    ll ans = 2147483647;
    return ans = ans * rand() % mod + 1;  // 1 到 mod 之间的数
}
signed main() {
    struct _timeb T;
    _ftime(&T);
    srand(T.millitm);
    // 生成随机数种子,利用 timeb 生成毫秒级别随机数
    ll a, b;
    a = Random(1e12), b = Random(1e12);
    cout << a << ' ' << b;
    // 这样就生成了 2 个随机数
}

rand () 只会生成 0~32767 的数据

# 对拍代码

# 标准输入输出代码

标准输入输出指的是:两份基本代码和数据生成代码里不含文件输入输出操作,如 freopen 等。

在这里,我们需要用到一些文件的读写符号。(需用到 <cstdlib> 库)

system ("data.exe> in.txt") 指的是运行 data.exe,把结果输出(>)到 in.txt 中。

system ("wa.exe < in.txt> wa.txt") 指的是运行 wa.exe,从 in.txt 中读入(<)数据,把结果输出(>)到 wa.txt 中。

system ("fc ac.txt wa.txt") 指的是比较 ac.txt 和 wa.txt ,如果两个文件里的数据相同返回 0,不同返回 1。

那么,我们就可以执行这一操作来实现对拍。

先让数据生成器输出数据。 system ("data.exe> in.txt")
然后用这个数据跑一遍暴力代码,输出结果。 system ("ac.exe < in.txt> ac.txt")
再用这个数据跑一遍你写的正解代码,输出结果。 system ("wa.exe < in.txt> wa.txt")
把两个结果相比较,判断是不是一样的。 system ("fc ac.txt wa.txt")
创建一个源代码,命名为 duipai.cpp:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    while (1) // 一直循环,直到找到不一样的数据
    {
        system("data.exe > in.txt");
        system("baoli.exe < in.txt > baoli.txt");
        system("std.exe < in.txt > std.txt");
        if (system("fc std.txt baoli.txt")) // 当 fc 返回 1 时,说明这时数据不一样
            break;                          // 不一样就跳出循环
    }
    return 0;
}

# 以下是林浩老师的代码

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<windows.h>
int main()
{
	long s, t;
	int num = 1;
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	while (1)
	{
		system("cls");
		do
		{
			system("data.exe > in.txt");  // 数据生成程序
			s = clock();
			system("wa.exe < in.txt > wa.txt");  // 自己程序
			t = clock();
			system("ac.exe < in.txt > ac.txt");  // 答案
			if (system("fc wa.txt  ac.txt > nul"))
			{
				WORD wr2 = FOREGROUND_RED | FOREGROUND_INTENSITY;
				SetConsoleTextAttribute(hOut, wr2);
				printf("P%d  ", num);
				break;
			}
			else
			{
				WORD wr2 = FOREGROUND_GREEN  | FOREGROUND_INTENSITY;
				SetConsoleTextAttribute(hOut, wr2);
				printf("P%d  ", num);
				printf("Accept time: %ldms\n", t - s);
			}
			num++;
			printf("\n\n\n\n");
		}
		while (1);
		WORD wr2 = FOREGROUND_RED | FOREGROUND_INTENSITY;
		SetConsoleTextAttribute(hOut, wr2);
		printf("Wrong Answer time: %ldms\n", t - s);
		wr2 = 0x00000 | FOREGROUND_INTENSITY;
		SetConsoleTextAttribute(hOut, wr2);
		system("fc wa.txt ac.txt");
		system("pause > nul");
	}
}

# 运行 duipai.exe

最后运行

Alt text

得到结果后去看in.txtin.txt 查看是哪组数据出了问题,然后根据数据调试 bug

此文章已被阅读次数:正在加载...更新于