与ACM校内赛和省赛的日期越来越接近了,我也开始做一些算法题来练一练手了~最近在做王晓东的《算法设计与实验题解》。因为它全部分好了类,而且有配套光盘给出些测试数据。
但是写好程序好要逐个逐个数据文件地测试、核对答案是一件非常痛苦的事,而且如果中途发现有错的话又要从头来过。这样吃力不讨好的事精明的我自然是不会做的啦~

,于是便萌生了DIY一个简单的“Offline Judge”(相对于acm网站上的“Online Judge”)的念头

。
这是一个使用相当简单的命令行程序,调用格式为:
judge [C++文件路径][测试文件目录][标准答案文件目录]其中C++文件路径是必需的,如果就在当前目录下,直接给出文件名即可。记得带上cpp后缀名。测试文件目录是可选的,默认值是".\test"。标准答案文件目录也是可选的,默认值是".\answer"。
使用时要求你要自己准备一个g++编译器,如果没有的话,可以到
这里下载一个Dev-C。然后在环境变量path里加一项“[dev-c安装目录]\bin\”。当然,如果你不喜欢修改你的环境变量的话,也可以将源文件98行的“g++....”改为“[dev-c安装目录]\bin\g++”(不过笔者还是建议你采用第一种方案,因为将g++设为环境变量会带来很多方便)
使用时你可以把该程序放到C:\windows\system32或其它在path可以找得到的地方,然后用Dos进入你要测试的文件的目录下,然后输入judge xx.cpp就可以自动测试了。返回结果如下:

示例
E:\ftp\upload\acumon\wxd\ch3 动态规划\prog37>judge p37.cpp
Offline Judge 1.0beta
Powered by Acumon(踏雪赤兔).

Compiling
p37.cpp:35:1: warning: no newline at end of file

Testing file:mult0.in
Time used: 0.079000 second(s)
Result: Accepted

Testing file:mult1.in
Time used: 0.047000 second(s)
Result: Accepted

Testing file:mult2.in
Time used: 0.047000 second(s)
Result: Accepted

Testing file:mult3.in
Time used: 0.062000 second(s)
Result: Accepted

Testing file:mult4.in
Time used: 0.047000 second(s)
Result: Accepted

Testing file:mult5.in
Time used: 0.047000 second(s)
Result: Accepted

Testing file:mult6.in
Time used: 0.063000 second(s)
Result: Accepted

Testing file:mult7.in
Time used: 0.062000 second(s)
Result: Accepted

Testing file:mult8.in
Time used: 0.062000 second(s)
Result: Accepted

Testing file:mult9.in
Time used: 0.063000 second(s)
Result: Accepted

Nice performance! ^_^是不是很好玩呢?
总结一下,该Judge有以下功能:

功能一览
1
自动编译cpp文件
2
自动在.\test或指定目录中查找所有.in文件作为测试文件,并与.\answer或指定目录中的同名.out文件核对。
3
为每一个测试文件给出AC、PE、WA、TLE、CE等结果(该beta版尚不能处理RTE和MLE的情况,望高手不吝赐教orz) 和我的其它小作品一样,该Judge是完全开源的,源代码如下:

OfflineJudge源代码一览
1
/**//*
2
AppName: OfflineJudge 1.0beta(离线评测系统)
3
Author: Acumon(踏雪赤兔)
4
Usage:
5
@param 1: cpp文件名(必需)
6
@param 2: .in文件所在目录(可选,默认为.\test)
7
@param 3: .out文件所在目录(可选,默认为.\answer)
8
@return: 见namespace Error
9
Compiler: G++, VC6.0
10
Last Update: 07-03-25
11
Contact:
12
QQ: 38136419
13
Blog: http://www.cnitblog.com/cockerel/
14
*/
15
#include<ctime>
16
#include<cstdlib>
17
#include<cstdio>
18
#include<iostream>
19
#include<io.h>
20
using namespace std;
21
//----- BEGIN Configration
22
//common settings
23
namespace Settings
{
24
const static char* Title="Offline Judge 1.0beta\n\tPowered by Acumon(踏雪赤兔).\n";
25
const static char* DefaultInPath=".\\test"; //默认测试数据路径
26
const static char* DefaultStdPath=".\\answer"; //默认标准输出数据路径
27
const static char* DefaultInExt=".in"; //默认测试数据扩展名
28
const static char* DefaultStdExt=".out"; //默认标准输出数据扩展名
29
const static double TimeLimit= 1.0; //限时
30
const static int bufLen= 1024; //缓冲区大小
31
const static char* GppParam="-o _judge -ansi -fno-asm -O2 -Wall -lm --static -DONLINE_JUDGE";//g++编译器参数
32
}
33
//return value and return string
34
namespace Error
{
35
//return value
36
const static int NoError=0;
37
const static int TooFewParam=1;
38
const static int TooManyParam=2;
39
const static int NoCppFile=3;
40
const static int NoInputFile=4;
41
const static int NoStandardFile=5;
42
43
//output string
44
const static char* TooFewParamMsg="Error: Too few parameters\nUsage: judge [cppfilename] [.in path] [.out path]";
45
const static char* TooManyParamMsg="Error: Too many parameters\nUsage: judge [cppfilename] [.in path] [.out path]";
46
const static char* NoCppFileMsg="Error: No such .CPP file";
47
const static char* NoInputFileMsg="Error: No .IN file";
48
const static char* NoStandardFileMsg="Error: No .OUT file";
49
}
50
// judge output string
51
namespace Result
{
52
const static char* CE="Result: Compile Error";
53
const static char* RTE="Result: Runtime Error";
54
const static char* TLE="Result: Time Limit Exceeded";
55
const static char* WA="Result: Wrong Answer";
56
const static char* PE="Result: Presentation Error";
57
const static char* AC="Result: Accepted";
58
}
59
//----- END Configration
60
61
class Timer
{ //封装clock()函数
62
public:
63
void reset()
{
64
beginClock=clock();
65
}
66
double get()
{
67
return double(clock()-beginClock)/CLOCKS_PER_SEC;
68
}
69
Timer()
{
70
reset();
71
}
72
private:
73
time_t beginClock;
74
};
75
76
int main(int argc, char** argv)
{
77
//参数检查
78
if(argc<2)
{
79
puts(Error::TooFewParamMsg);
80
return Error::TooFewParam;
81
}
82
if(argc>4)
{
83
puts(Error::TooManyParamMsg);
84
return Error::TooManyParam;
85
}
86
puts(Settings::Title);
87
//参数设定
88
const char* cpp_name=argv[1]; //待测cpp文件名
89
const char* in_path= argc>=3 ? argv[2] : Settings::DefaultInPath;
90
const char* std_path= argc>=4 ? argv[3] : Settings::DefaultStdPath;
91
const char* in_ext=Settings::DefaultInExt;
92
const char* std_ext=Settings::DefaultStdExt;
93
94
char buf[Settings::bufLen];
95
int cmdReturn;
96
//编译CPP
97
puts("Compiling
");
98
sprintf(buf, "g++ \"%s\" %s",cpp_name, Settings::GppParam);
99
cmdReturn=system(buf);
100
// CE
101
if(cmdReturn==1)
{
102
puts(Result::CE);
103
return Error::NoError;
104
}
105
putchar('\n');
106
107
// run
108
bool fail=false;
109
_finddata_t test_in,tmp; //保存找到文件的结构,有name属性,见io.h
110
int hFile;
111
sprintf(buf, "%s\\*%s", in_path,in_ext);
112
hFile = _findfirst(buf,&test_in);
113
if(hFile==-1)
{
114
puts(Error::NoInputFileMsg);
115
return Error::NoInputFile;
116
}
117
do
{
118
printf("Testing file:%s\n", test_in.name);
119
Timer timer;
120
sprintf(buf,"_judge < %s\\%s > _judge.out", in_path, test_in.name);
121
cmdReturn=system(buf);
122
double duration=timer.get();
123
printf("Time used: %lf second(s)\n", duration);
124
if(duration>Settings::TimeLimit)
{
125
printf("%s\n\n", Result::TLE);
126
fail=true;
127
}else
{
128
//比较输出文件
129
char std_out[Settings::bufLen]; //std文件名
130
sprintf(std_out,"%s\\%s ", std_path, test_in.name);
131
memcpy(strstr(std_out,in_ext),std_ext,strlen(std_ext)); //更改后缀名:.in→.out
132
if(_findfirst(std_out,&tmp)==-1)
{
133
puts(Error::NoStandardFileMsg);
134
system("del _judge.out");
135
system("del _judge.exe");
136
return Error::NoStandardFile;
137
}
138
sprintf(buf,"fc %s _judge.out >fc.out",std_out);
139
cmdReturn=system(buf);
140
if(cmdReturn==1)
{ //不相等
141
//删除空白再比较文件
142
sprintf(buf,"fc/w %s _judge.out >fc.out",std_out);
143
cmdReturn=system(buf);
144
if(cmdReturn==0)
{
145
printf("%s\n\n",Result::PE);
146
fail=true;
147
}else
{
148
printf("%s\n\n",Result::WA);
149
fail=true;
150
}
151
}else
{
152
printf("%s\n\n",Result::AC);
153
}
154
system("del _judge.out");
155
system("del fc.out");
156
}
157
}while(_findnext(hFile,&test_in)!=-1);
158
system("del _judge.exe");
159
puts(fail ? "Wrong on some case(s). >_<" : "Nice performance! ^_^");
160
return Error::NoError;
161
} 今天是我的好朋友酒精的生日

,这份小作品特别献给同为ACMer且刚刚获得学校校内赛“最佳女生奖”的她,希望她喜欢啦~

有什么意见或者建议欢迎用QQ或回贴的方式告诉我,先多谢大家支持啦~
附:
C++源文件及程序下载。
posted on 2007-03-29 20:48
踏雪赤兔 阅读(1044)
评论(11) 编辑 收藏 引用 所属分类:
玩转编程