使用说明书
百度网盘下载:http://pan.baidu.com/s/1dDci8cp
如果你是蓝桥杯选手,无法在蓝桥杯的练习系统刷题(如图1),或者不是VIP用户而不能做VIP题,可以在这个网站找到题目和测试数据下载:http://www.coolnote.cn/。由于无法在官方的OJ测试自己代码的正误,所以我开发了一款单机版的测评系统,由于兼容性问题(程序以C++为框架,调用命令行实现),可能win7及以上版本操作系统才可以使用。
图1 蓝桥杯练习系统界面
评测系统功能非常简洁,事实上我只写了200多行代码,所以只是作为应急之需,不可能代替正规的测评系统。测试时,只要你的源代码生成的可执行文件放在与“测试软件.exe”同目录即可,注意放入的可执行文件名称必须与所做题目相同,如我做了“带分数”这题,操作如图2所示。
图2 软件使用介绍
然后双击“测试软件.exe”即可,效果如图3所示。
图3 软件效果截图
如果有错误,你可以打开“2--当前题数据”文件夹,查看里面的文件,保存着最近一次测试的题目数据。其中"input"和"output"是从“1--测试数据”拷贝过来的官方版标准输入输出,"ans"是你的程序生成的答案。效果如图4所示。
图4 “2--当前题数据”文件夹
最后,读者在使用若干次,掌握了程序的原理后,可以自行添加新的题目数据进行测试。这里不在说明,留读者自己探索发现。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
“测试软件”源代码
#include <cstdio>
#include <string>
#include <string.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <cctype>
#include <iomanip>
#include <ctime>
using namespace std;
// 定义常量
const string File1 = "1--测试数据";
const string File2 = "2--当前题数据";
const string softName = "测试软件.exe";
string ProName;
int testNum;
int main()
{
// 函数声明
string get_ProName();
int get_testNum();
void Check();
// 初始化
time_t t = clock();
ProName = get_ProName();
testNum = get_testNum();
cout << "初始化用时:" << clock()-t << "ms\n\n";
// 判断
Check();
system("pause");
return 0;
}
string get_ProName()
{
void guide();
ifstream fin;
// Step 1
system(("dir "+File1+" > tmp.txt").c_str()); // 用时50~77ms
fin.open("tmp.txt");
vector<string> Pro;
string s, name;
while (fin >> s)
{
if (s.find(".txt") != string::npos) // 后缀为.txt
{
name = s.substr(0, s.find('-'));
if (Pro.empty() || name!=*Pro.rbegin()) Pro.push_back(name);
}
}
fin.close();
/* Debug:输出Pro列表
for (int i = 0; i < Pro.size(); i++)
{
cout << i+1 << " :" + Pro[i] << endl;
}
//*/
// Step 2
int ok, i;
string pro;
system("dir > tmp.txt");
fin.open("tmp.txt");
while (fin >> s)
{
if (s.find(".exe") != string::npos && s != softName)
{
// Step 3
pro = s.substr(0, s.find(".exe"));
for (ok = i = 0; i < Pro.size(); i++)
{
if (Pro[i] == pro)
{
ok = 1;
break;
}
}
if (ok) break;
}
}
fin.close();
system("del tmp.txt");
if (ok) return pro;
else guide();
}
int get_testNum()
{
void clear(string F);
// Step 1
clear(File2);
// Step 2
system(("copy "+File1+"\\"+ProName+"*.txt "+File2+" > tmp.txt").c_str());
// Step 3
ifstream fin("tmp.txt");
string s;
int n;
while (fin >> s)
{
if (s == "已复制")
{
fin >> n;
break;
}
}
fin.close();
return n/2;
}
void Check()
{
// 输出表头
cout << "完全正确:是指官方的output文件和您生成的ans文件完全匹配,没有任何差异\n";
cout << "基本正确:是指在忽略空格和回车符等空白字符影响下,两个文件内容相同\n";
cout << " 用 时:包含生成ans文件的时间,加上性能不稳定等原因,这里统计的值只能作为参考\n\n";
cout << "测试编号 " << "完全正确 " << "基本正确 " << "用时(单位ms)" << endl;
time_t t, useTime;
char num[5];
string s, s2;
ifstream fin, fin2;
char ch;
for (int i = 1; i <=testNum; i++)
{
// Step 1
cout << setw(5) << i;
// Step 2
// 下面先用s存储好命令文本,减小计时额外消耗
sprintf(num, "%d", i); // 把整数i变成字符串形式
s = ProName; // 调用exe
// 找到输入文件
s = s + " <" + File2 + "\\" + ProName + "-input-" + num + ".txt";
// 找到输出文件
s = s + " >" + File2 + "\\" + ProName + "-ans-" + num + ".txt";
// 运行
t = clock(); system(s.c_str()); useTime = clock() - t;
// Step 3
s = "fc " + File2 + "\\" + ProName + "-output-" + num + ".txt";
s = s + File2 + "\\" + ProName + "-ans-" + num + ".txt > tmp.txt";
fin.open("tmp.txt");
fin >> t;
if (t) cout << setw(12) << "No";
else cout << setw(12) << "Yes";
fin.close();
// Step 4
bool same = 1;
fin.open((File2 + "\\" + ProName + "-output-" + num + ".txt").c_str());
fin2.open((File2 + "\\" + ProName + "-ans-" + num + ".txt").c_str());
while (fin >> s && fin2 >> s2) if (s != s2) break; // 先去掉前面两份均相同的部分
//这里的尾部判断方法,一直觉得有点不太好
// 如果fin在此基础上,还能再读入s(s会变成不等于s2),则答案错误
do
{
if (s != s2)
{
same = 0;
break;
}
} while (fin >> s);
// 如果fin2还可以读入改变s2的字符,则答案错误
while (fin2 >> s2)
{
if (s != s2)
{
same = 0;
break;
}
}
if (same) cout << setw(12) << "Yes";
else cout << setw(12) << "No";
fin.close();
fin2.close();
cout << setw(12) << useTime << endl;
}
system("del tmp.txt");
}
// 清空某个文件夹
void clear(string F)
{
system(("rmdir/s/q "+F).c_str());// 删除文件夹
system(("mkdir "+F).c_str()); // 再重新创建
}
void guide()
{
cout << "(初次使用请忽略本句话)未在当前目录找到有效测试程序,请确认是否存在可执行文件或文件名正确性!\n\n";
int i, len;
string star(80, '*');
for (i = 1; i < 80; i+=2) star[i] = ' ';
cout << star << endl;
string title("蓝桥杯测试软件 v0.5 By coder4101\n");
len = title.size();
cout << setw((80-len)/2+len) << title << endl; // 居中输出
cout << "使用指南\n\n";
cout << "1、只需把您编译出的exe可执行程序放在当前目录(与该\"测试软件.exe\"所在位置同级),";
cout << "并把名称改为对应的题目名。完成后,直接点击该\"测试软件.exe\"即可进行测试。\n\n";
cout << "2、若程序未AC,您可以在\""+File2+"\"目录下查看刚才的测试数据及结果,方便Debug。";
cout << "input和output标记的是标准的输入与输出,ans标记的是您的程序跑出的结果。\n\n";
cout << "3、本软件结果仅供参考,最终结论以官网为准。\n\n";
cout << "注:请勿修改以下三个名称:"+File1+","+File2+",测试软件.exe。";
cout << endl << star << endl;
system("pause");
exit(0);
}