众所周知,在考场上写完一道题的“正解”,不和暴力对拍一下,谁也不敢说自己可以 (AC)。
然而,(Windows)批处理文件的循环经常写出 (bug) (起码我是这样)。
怎么办呢?这时候就轮到我们的 (C++) 上场了。
用 (C++) 写对拍器需要用到系统操作,全代码主要分为以下几个部分:
- 利用数据生成器(
随机数大法好)、自己的程序、(std) 或者暴力,进行文件的读入读写。 - 读入两个文件并比较。
- 获得反馈。
假设如今我们有如下这些东西:
(get.cpp/exe): 数据生成器
(T2.cpp/exe): 我们自己的程序
(std.cpp/exe): 我们可以保证答案正确的程序
(check.cpp/exe): 我们要编写的对拍器
Step 1 读写文件
首先看文件的读写部分。在重复生成多组数据并跑出答案时,直接用我们常用 (freopen) 特别不方便,在这里我们使用 (Sprinf)。
(Sprintf) 函数可以大致看作 (Printf) 函数的升级版,但是其功能强大的多。这里不做过多介绍。
创建一个 (char) 变量,作为对系统进行操作的"工具人"。 这里我命名为 (buf)。然后,利用 (sprintf) 与 (Windows) 的 (bat) 文件语言融合版,我们可以这么写:
sprintf(buf, "get.exe > 1.in"); system(buf);
后面的 (system) 表示对系统进行操作,双引号内这句话为 (Windows)批处理文件语法,表示 (get.exe) 向 (1.in) 这个文件输入,箭头指向右边代表输入,指向左边代表读入。
于是,对于我们自己的程序和 (std), 我们可以这样写:
sprintf(buf, "T2.exe < 1.in > 1.out");
system(buf);
sprintf(buf, "std.exe < 1.in > 2.out");
system(buf);
(1.out) 和 (2.out) 即为我们得到的两个程序的输出结果。
Step 2 记录答案
定义一个 (check) 函数,同时用数组记录下两个文件中的所有数字,若为字符串等较长类型,更换成 (char) 记录即可。
这里直接使用简单的 (freopen) 完成。
freopen("1.out", "r", stdin);
while(scanf("%d", &a[++cnt1]) != EOF) ;
fclose;
freopen("2.out", "r", stdin);
while(scanf("%d", &b[++cnt2]) != EOF) ;
fclose;
一个十分简单的操作我们便将两个答案存在了 (a) 数组和 (b) 数组中。
Step 3 答案比较
这一步十分简单,直接 (for) 循环比较即可。当然也可以先比较一下 (cnt1)和 (cnt2) 是否相等。
for(int i = 1; i <= cnt1; i++){
if(b[i] != a[i]){
wrong_and_pause();
return 0;
}
}
其中的 (wrong) _ (and) _ (pause) 函数主要是我们用来在遇到错误时及时得到反馈并暂停程序,以防止 (hack) 数据被覆盖,方便我们及时查看。
实现同样很 (easy):
void wrong_and_pause(){
printf("Wrong!
");
system("pause");
return ; `
}
Step 4 个性化操作
(C++) 对比 (bat) 的简易对拍器,最大的优势就在于我们可以很大程度的自定义自己的对拍器,比如输出两边答案等等。 自己优化即可。
奉上完整对拍器代码:
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
int a[N], cnt1 = 0;
int b[N], cnt2 = 0;
char buf[1024];
void wrong_and_pause(){
printf("Wrong!
");
system("pause");
return ;
}
bool check(int x){
cnt1 = 0, cnt2 = 0;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
freopen("1.out", "r", stdin);
while(scanf("%d", &a[++cnt1]) != EOF) ;
fclose;
freopen("2.out", "r", stdin);
while(scanf("%d", &b[++cnt2]) != EOF) ;
fclose;
printf("%d %d
", a[1], b[1]);
if(cnt1 != cnt2){
wrong_and_pause();
return 0;
}
for(int i = 1; i <= cnt1; i++){
if(b[i] != a[i]){
wrong_and_pause();
return 0;
}
}
return 1;
}
int main(){
for(int i = 1; i <= 1000; i++){
sprintf(buf, "get.exe > 1.in");
system(buf);
sprintf(buf, "T2.exe < 1.in > 1.out");
system(buf);
sprintf(buf, "std.exe < 1.in > 2.out");
system(buf);
if(check(1)){
printf("Right Answer!
");
}
Sleep(700);
}
return 0;
}
(rendered) (by) (Latex)