如何在考场上快速用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!\n");
	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!\n");
	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\n", 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!\n"); 
		}
		Sleep(700); 
	}
	return 0;
}




\(rendered\) \(by\) \(Latex\)

posted @ 2020-10-17 10:06  雪之下,树之旁  阅读(537)  评论(2编辑  收藏  举报