如何在考场上快速用C++写高级对拍器

众所周知,在考场上写完一道题的“正解”,不和暴力对拍一下,谁也不敢说自己可以 (AC)
然而,(Windows)批处理文件的循环经常写出 (bug) (起码我是这样)。

怎么办呢?这时候就轮到我们的 (C++) 上场了。

(C++) 写对拍器需要用到系统操作,全代码主要分为以下几个部分:

  1. 利用数据生成器(随机数大法好)、自己的程序、(std) 或者暴力,进行文件的读入读写。
  2. 读入两个文件并比较。
  3. 获得反馈。

假设如今我们有如下这些东西:
(get.cpp/exe): 数据生成器
(T2.cpp/exe): 我们自己的程序
(std.cpp/exe): 我们可以保证答案正确的程序
(check.cpp/exe): 我们要编写的对拍器
image.png

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)

原文地址:https://www.cnblogs.com/wondering-world/p/13830057.html