前言

对拍是帮助我们检验算法正确性(或者帮助我们死了用高级算法的心)的极其有效的方式,最近上网查了查对拍器的写法和检验器的写法,放一个比较花哨的对拍与检验器在这,有改进意见的 DALAO 们也可以提出来~

在开始之前,可能需要了解以下东西:

  1. 整个对拍器并没有使用 freopen ,并且在对拍器头文件(以下有说明)里也不允许使用 freopen,因为对拍程序会频繁的在控制台和文件输入输出流之间切换,所以我采用的是 ifstreamofstream
  2. ifstreamofstream 是对应输入输出流的数据类型,头文件为 include <fstream>,实例化以后可以用类似 cincout 的形式往文件里面输入内容或从文件里面读取内容,写入和读取的机制也和 cincout 相似,例如,往 TEST.txt 写入内容 Hello World!
1
2
3
ofstream ofile;
ofile.open("TEST.txt");
ofile<<"Hello World!";
  1. 由于在随机数生成时不需要用到 ifstream(就是说不用自己写)所以在此不多介绍,那么使用 ofstream 为经典的 A+B Problem 生成一组数据到 input.txt 里面,就是:
1
2
3
4
5
srand(time(0));
ofstream ofile;
ofile.open("input.txt");
ofile<<rand()<<' '<<rand();
ofile.close(); // 关闭文件

组成部分

我写的对拍程序包含以下几个部分:

  1. 随机数头文件 data.h(注意不是CPP!直接将对拍的代码写到一个叫做 makedata 的无参数且为 void 型的函数里面即可,不写 main() 函数),头文件不用编译直接保存即可
  2. 标准程序 std.exe ,注意是编译好的可执行文件不是源代码
  3. 要对拍的程序 my.exe ,注意是编译好的可执行文件不是源代码
  4. 统一的文件输入从 testin.txt 里面输入,输出时,标准程序输出到 r_testout.txt,要对拍的程序输出到 testout.txt (当然也可以进入检验器里面更改文件名)
  5. 以上文件和检验器必须处在同一目录下

操作方法

  1. 在下方复制检验器的源代码,编译后生成一个可执行文件,将上述的所有文件放到同一目录下,运行检验器
  2. 一来会提示你检查需要的程序以及文件(其中输出输出文件可以不用专门创建,但是一定要写在程序的文件输入输出的代码内并编译通过)确定无误后输入 y,随后输入数据组数就可以开始对拍了
  3. 如果要修改文件名,可以进入检验其源代码,修改对应的部分即可

源代码

检验器源代码(Judge.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <windows.h>
#include "data.h" // 随机数头文件
using namespace std;
char op;int n;
char s1[1000001],s2[1000001];
int main(){
srand((unsigned)time(NULL));
ifstream infile1,infile2,rdfile;
printf("欢迎使用对拍器!\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
printf("请确保以下文件与对拍器在同一目录内:\n");
printf("对拍程序:std.exe\n");
printf("测试程序:my.exe\n");
printf("随机数头文件:data.h\n");
printf("对拍输出:r_testout.txt\n");
printf("测试输出:testout.txt\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |
FOREGROUND_GREEN | FOREGROUND_BLUE);
printf("确定开始对拍请输入[y]\n");
cin>>op;if(op!='y') return 0;
system("cls"); int col=0;bool sign=true;
printf("输入数据组数:");scanf("%d",&n);
printf("------------------------------\n");
for(int i=1;i<=n;i++){
makedata();
system("my.exe"); // 在这里修改要对拍的程序名
system("std.exe"); col=0;// 在这里修改标准答案程序名
infile1.open("testout.txt");// 在这里修改对拍程序输出文件的名字
infile2.open("r_testout.txt");// 在这里标准程序输出文件的名字
while(!infile1.eof() && !infile2.eof()){
col++;sign=true;
infile1.getline(s1,1000000);
infile2.getline(s2,1000000);
if(strcmp(s1,s2)){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
printf("#%d: 在第 %d 行,标准输出 %s,测试输出 %s\n",i,col,s2,s1);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |
FOREGROUND_GREEN | FOREGROUND_BLUE);sign=false;
break;
}
}
if(sign){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
printf("#%d: 测试输出与对拍输出一致\n",i);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |
FOREGROUND_GREEN | FOREGROUND_BLUE);
}
infile1.close();
infile2.close();
} printf("------------------------------\n");
printf("%d 组",n);
system("echo 评测完成 & pause>nul");
return 0;
}

随机数源代码样例(data.h)

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <fstream>
using namespace std;
void makedata(){
ofstream ofile;
ofile.open("testin.txt");// 在这里指定输入文件的名字
// 以下内容根据题目需要编写,生成符合题目的数据
int n=rand()%40;
ofile<<n<<' '<<rand()%2000000+2000000<<'\n';
for(int i=1;i<=n;i++) ofile<<rand()%2000000<<' ';
}

最后

欢迎各位 DALAO 提出改进建议或者与我交流!!!

2019 / 07 / 24