自制蓝桥杯题库单机评测系统

使用说明书

       百度网盘下载: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); 
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值