c++编写评测机(3)

目录

前言

完善

完整代码

后续透露


前言

评测机终于更新第三版了。这次更新有较大的改动,我也就写了两个晚上吧(真是太肝了),不过这次改动后评测及也就比较完善了。

v1.0.1版本中有以下几个可以改动的地方:

  1. 由于功能越来越多,评测机文件夹里的东西也越来越多,很杂乱。
  2. 每次评测完成后光标就会出现(我也不知道为什么)。

完善

1.针对第一个问题,我们可以把输入数据和测试点数据(sample.in和textpoint.in)放在一个名为data的文件夹中。这就需要在读取数据时加入目录操作。

首先就是获得测试点数据,我们只要对getpoint()函数进行改动就ok了。原本我们读取测试点数据用的是FILE。用法如下:

FILE *p;
p = fopen(filename, "r");

但此函数只能打开本文件夹的文件,所以需要换掉。我们换成fstream,具体用法如下:

fstream(文件地址+名称) filename;
filename.open;

其中filename是自己定义的一个变量。

这样我们就可以把getpoint()函数换成以下代码:

void getpoint(string str_filename){
	string tool = "\\data\\";
	string t1 = buf + tool + str_filename;
	const char* filename = t1.c_str();
	fstream myfile;
	myfile.open(filename);
	string s;
	char textpoint[1005];
	int _cnt = 0;
	while(getline(myfile, s)){
		for(int i = 0; i < s.length(); i++){
			textpoint[++_cnt] = s[i];
		}
		textpoint[++_cnt] = '\n';
	}
    int f;
	for(int i = 0; i < strlen(textpoint); i++){//获得测试点个数
		if(textpoint[i] == '#'){
			f = i;
			break;
		}
		if(textpoint[i] >= '0' && textpoint[i] <= '9')
			cnt = cnt * 10 + textpoint[i] - '0';
	}
	int now = 0;
	for(int i = f; i <= strlen(textpoint); i++){//获取测试点时间限制及分数
        if(textpoint[i] == '#'){
        	now++;
		}
		else if(textpoint[i] == ':'){
			int nowlimit = 0;
			for(int j = i; j <= strlen(textpoint); j++){
				if(textpoint[j] == ','){
					int nowpoint = 0;
                    for(int k = j; k <= strlen(textpoint); k++){
                    	if(textpoint[k] == '#'){
                    		break;
						}
						if(textpoint[k] <= '9' && textpoint[k] >= '0'){
							nowpoint = nowpoint * 10 + textpoint[k] - '0';
						}
					}
					sample[now].point = nowpoint;
					break;
				}
				if(textpoint[j] >= '0' && textpoint[j] <= '9') nowlimit = nowlimit * 10 + textpoint[j] - '0';
			}
			sample[now].time_limit = nowlimit;
		}
	}
}

这样就可以在data文件夹里读取测试点数据了。其中buf是data文件的地址,我们可以通过一个函数获取评测机的地址,由于data和评测机放在一起,所以也就获得了data的地址:

GetCurrentDirectory(1000, buf);

第一个问题解决啦。

2.前面我们加入了一个函数,使控制台光标小时,但我i们会发现,每次评测完或者改变了控制台的大小都会让光标再次出现。原因作者上网查找了许久,都没有找到原因。下面贴出让光标隐藏的代码,评论区有大神知道原因欢迎告知。

我们可以手动隐藏光标,在主页加入一个选项,每次选中就可以隐藏光标。

printf("1:评测 2:设置 3:隐藏光标\n");
		char choose = getch();
		if(choose == '1'){
			system("cls");
			if(!initialize()){
				printf("0:返回\n");
				Mypause('0');
				continue;
			}
			start_judge();
			system("del ans.out");
			system("del std.out");
			system("del ans.exe");
			system("del std.exe");
			printf("0:返回\n");
			Mypause('0');
			continue;
		}
		else if(choose == '2'){
			while(1){
				system("cls");
				printf("0:返回\n1:评测方式\n2:比较方式\n");
				char choosea = getch();
				if(choosea == '1'){
					system("cls");
                    printf("暂不支持\n0:返回\n");
                    Mypause('0');
				}else if(choosea == '2'){
					while(1){
						system("cls");
						printf("0:返回\n1:忽略空格");
						if(ifblank){
							printf("-\n");
						}else{
							printf("√\n");
						}
						printf("2:忽略换行");
						if(ifenter){
							printf("-\n");
						}else{
							printf("√\n");
						}
						char choose2 = getch();
						if(choose2 == '1') ifblank = !ifblank;
						else if(choose2 == '2') ifenter = !ifenter;
						else if(choose2 == '0'){
							system("cls");
							break;
						}
					}
				}else if(choosea == '0'){
					system("cls");
					break;
				}
			}
		}else if(choose == '3'){
			hide();
		}

这样就可以暂时解决这个问题了。(有点投机取巧)

完整代码

最后,贴上完整代码

评测机.cpp

//v1.0.2
#include"tools.h"
int main(){
	system("title 评测机");
	color(7);
	GetCurrentDirectory(1000, buf);
	Clear_Qiuckedit();
	while(1){
		hide();
		gotoxy(1, 1);
		printf("1:评测 2:设置 3:隐藏光标\n");
		char choose = getch();
		if(choose == '1'){
			system("cls");
			if(!initialize()){
				printf("0:返回\n");
				Mypause('0');
				continue;
			}
			start_judge();
			system("del ans.out");
			system("del std.out");
			system("del ans.exe");
			system("del std.exe");
			printf("0:返回\n");
			Mypause('0');
			continue;
		}
		else if(choose == '2'){
			while(1){
				system("cls");
				printf("0:返回\n1:评测方式\n2:比较方式\n");
				char choosea = getch();
				if(choosea == '1'){
					system("cls");
                    printf("暂不支持\n0:返回\n");
                    Mypause('0');
				}else if(choosea == '2'){
					while(1){
						system("cls");
						printf("0:返回\n1:忽略空格");
						if(ifblank){
							printf("-\n");
						}else{
							printf("√\n");
						}
						printf("2:忽略换行");
						if(ifenter){
							printf("-\n");
						}else{
							printf("√\n");
						}
						char choose2 = getch();
						if(choose2 == '1') ifblank = !ifblank;
						else if(choose2 == '2') ifenter = !ifenter;
						else if(choose2 == '0'){
							system("cls");
							break;
						}
					}
				}else if(choosea == '0'){
					system("cls");
					break;
				}
			}
		}else if(choose == '3'){
			hide();
		}
	}
	return 0;
}

tools.h

#ifndef TOOLS_H
#define TOOLS_H
#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
#define WEXITSTATUS(status)   (((status) & 0xff00) >> 8)
#define WIFEXITED(status) ((status & 0x7f) == 0)
using namespace std;
namespace mname{
	char textpoint[10000];
	char buf[10000];
	struct node{
		int time_limit, point;
	}sample[1005];
	int cnt, mysco, totlesco;
	int outcheck_std, outcheck_ans;
	const int maxn = 100005;
	char ANS[maxn], STD[maxn] = "";
	clock_t start, end;
	double elapsed_secs;
	const char *name1 = "test.in";
	string samplename = "sample";
	bool ifblank = 1, ifenter = 1;
}
using namespace mname;
void Clear_Qiuckedit(){
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);
}
void hide(int hide_type = 0){
	CONSOLE_CURSOR_INFO cursor_info = {1, hide_type};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}
void color(int x, bool intensity = true){
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
    x | (intensity << 3));
}
void gotoxy(int x, int y){
	COORD pos = {y - 1, x - 1};
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void print(string s, int n){
	gotoxy(1, 1);
	cout << "状态:";
	color(n);
	cout << s << "          " << endl;
	color(7);
}
bool findfile(string str_find_filename, bool data = true){
	const char* find_filename;
	if(data){
		find_filename = str_find_filename.c_str();
		FILE *fp;
		fp = fopen(find_filename, "r");
		fclose(fp);
		return fp;
	}else{
		string tool = "\\data\\";
		string t1 = buf + tool + str_find_filename;
		find_filename = t1.c_str();
		fstream file(find_filename);
		return file;
	}
}
void enter_deal(const char* filename, bool ifblank = 1, bool ifenter = 1){
	int i, j = 0;
	char s[10000];
	FILE *p;
    p = fopen(filename, "r");
    fscanf(p, "%[^$]", s);
    fclose(p);
    for(int i = 0; i < strlen(s); i++){
        if((!ifblank && s[i] == ' ') || (!ifenter && s[i] == '\n'))
			continue;
        s[j++] = s[i];
    }
    s[j] = 0;
	p = fopen(filename, "w");
    fprintf(p, "%s", s);
    fclose(p);
    return;
}
bool compare(const char* filename1, const char* filename2){
	int i, j = 0;
	char s1[10000];
	FILE *p1;
    p1 = fopen(filename1, "r");
    fscanf(p1, "%[^$]", s1);
    fclose(p1);
	char s2[10000];
	FILE *p2;
    p2 = fopen(filename2, "r");
    fscanf(p2, "%[^$]", s2);
    fclose(p2);
    if(strlen(s1) != strlen(s2)) return false;
    for(int i = 0; i < strlen(s1); i++){
    	s1[j++] = s1[i];
    }
    j = 0;
    for(int i = 0; i < strlen(s1); i++){
    	s2[j++] = s2[i];
    }
    for(int i = 0; i < strlen(s1); i++){
        if(s1[i] != s2[i]) return false;
    }
    return true;
}
void getpoint(string str_filename){
	string tool = "\\data\\";
	string t1 = buf + tool + str_filename;
	const char* filename = t1.c_str();
	fstream myfile;
	myfile.open(filename);
	string s;
	char textpoint[1005];
	int _cnt = 0;
	while(getline(myfile, s)){
		for(int i = 0; i < s.length(); i++){
			textpoint[++_cnt] = s[i];
		}
		textpoint[++_cnt] = '\n';
	}
    int f;
	for(int i = 0; i < strlen(textpoint); i++){//获得测试点个数
		if(textpoint[i] == '#'){
			f = i;
			break;
		}
		if(textpoint[i] >= '0' && textpoint[i] <= '9')
			cnt = cnt * 10 + textpoint[i] - '0';
	}
	int now = 0;
	for(int i = f; i <= strlen(textpoint); i++){//获取测试点时间限制及分数
        if(textpoint[i] == '#'){
        	now++;
		}
		else if(textpoint[i] == ':'){
			int nowlimit = 0;
			for(int j = i; j <= strlen(textpoint); j++){
				if(textpoint[j] == ','){
					int nowpoint = 0;
                    for(int k = j; k <= strlen(textpoint); k++){
                    	if(textpoint[k] == '#'){
                    		break;
						}
						if(textpoint[k] <= '9' && textpoint[k] >= '0'){
							nowpoint = nowpoint * 10 + textpoint[k] - '0';
						}
					}
					sample[now].point = nowpoint;
					break;
				}
				if(textpoint[j] >= '0' && textpoint[j] <= '9') nowlimit = nowlimit * 10 + textpoint[j] - '0';
			}
			sample[now].time_limit = nowlimit;
		}
	}
}
void printsample(string str_filename, string str_filename2){
	string tool = "\\data\\";
	string t1 = buf + tool + str_filename;
	const char* filename = t1.c_str();
	const char* filename2 = str_filename2.c_str();
	fstream myfile;
	myfile.open(filename);
	string s;
	char ch[1005];
	int cnt = 0;
	while(getline(myfile, s)){
		for(int i = 0; i < s.length(); i++){
			ch[++cnt] = s[i];
		}
		ch[++cnt] = '\n';
	}
	FILE *p;
	p = fopen(filename2, "w");
    fprintf(p, "%s", ch + 1);
    fclose(p);
    return;
}
void judge(){
	for(int i = 1; i <= cnt; i++){
		totlesco += sample[i].point;
		cout << "#" << i << ": ";
	    char temp[10000];
	    sprintf(temp, "%d", i);
		string toname = samplename + temp + ".in";
		const char *name2 = toname.c_str();
		if(!findfile(name2, 0)){
			cout << "未找到" << name2 << "!\n";
			continue;
		}
		printsample(name2, name1);
		outcheck_std = system("std.exe");
		start = clock();//
		outcheck_ans = system("ans.exe");
		end = clock();//
		elapsed_secs = static_cast<double>(end - start);//
		if(outcheck_std == -1 || outcheck_ans == -1 || WIFEXITED(outcheck_std) == false || WIFEXITED(outcheck_ans) == false || 0 != WEXITSTATUS(outcheck_std) || 0 != WEXITSTATUS(outcheck_ans)){
			color(5);
			cout << "RE";
			color(7);
			cout << "(" << elapsed_secs << "ms)\n";
			continue;
		}
		if(elapsed_secs > sample[i].time_limit){
			color(3);
			cout << "TLE";
			color(7);
			cout << "(" << elapsed_secs << "ms)\n";
			continue;
		}
		bool ifcontinue = 1;
		if(!findfile("ans.out")){
			cout << "未找到输出!\n";
			ifcontinue = 0;
		}
		if(!findfile("std.out")){
			cout << "未找到输出!\n";
			ifcontinue = 0;
		}
		if(!ifcontinue) continue;
		enter_deal("ans.out", ifblank, ifenter);
		enter_deal("std.out", ifblank, ifenter);
		int count_ans = 0, count_std = 0;
		freopen("std.out", "r", stdin);
			scanf("%s", STD);
		freopen("ans.out", "r", stdin);
			scanf("%s", ANS);
		fclose(stdin);
		if(compare("ans.out", "std.out")){
			color(2);
			cout << "AC";
			color(7);
			cout << "(" << elapsed_secs << "ms)\n";
			mysco += sample[i].point;
		}
		else{
			color(4);
			cout << "WA";
			color(7);
			cout << "(" << elapsed_secs << "ms)\n";
		}
	//	printf("Your answer:\n%s\nCorrect answer:\n%s\n", ANS, STD);//输出用户答案以及正确答案
	}
}
void start_judge(){
	getpoint("textpoint.txt");
	print("提交中", 7);
	int i = 0, j = 0;
    gotoxy(1, 1);
    print("编译中", 7);
	if(sizeof(char*) == 4){
		int status_std32 = 0, status_ans32 = 0;
		status_std32 = system("g++ -o std.exe -m32 std.cpp");
		status_ans32 = system("g++ -o ans.exe -m32 ans.cpp");
		if(status_ans32 == -1 || status_std32 == -1 || WIFEXITED(status_ans32) == false || WIFEXITED(status_std32) == false || 0 != WEXITSTATUS(status_ans32) || 0 != WEXITSTATUS(status_std32)){
			print("CE", 6);
			return ;
		}
	}
	if(sizeof(char*) == 8){
		int status_std = 0, status_ans = 0;
		status_std = system("g++ -o std.exe std.cpp");
		status_ans = system("g++ -o ans.exe ans.cpp");
		if(status_ans == -1 || status_std == -1 || WIFEXITED(status_ans) == false || WIFEXITED(status_std) == false || 0 != WEXITSTATUS(status_ans) || 0 != WEXITSTATUS(status_std)){
			print("CE", 6);
			return ;
		}
	}
	print("评测中", 7);
	judge();
	print("评测结束", 7);
	gotoxy(cnt + 2, 1);
	cout << "分数:" << mysco << "(/" << totlesco << ")" << endl;
	printf("结果:");
	if(totlesco == mysco){
		color(2);
		printf("Accept\n");
		color(7);
	}
	else{
		color(4);
		printf("Unaccept\n");
		color(7);
	}
}
//void deletefile(){
//	system("del ans.exe");
//	system("del std.exe");
//	system("del ans.out");
//	system("del std.out");
//	system("del test.in");
//}
bool initialize(){
	bool back = 1;;
	if(!findfile("std.cpp")){
		printf("未找到std.cpp!\n");
		back = 0;
	}
	if(!findfile("ans.cpp")){
		printf("未找到源程序!\n");
		back = 0;
	}
	if(!findfile("textpoint.txt", 0)){
		printf("请创建textpoin.txt并将测试点数据存入\n");
		back = 0;
	}
	cnt = 0;
	totlesco = 0;
	mysco = 0;
	return back;
}
void Mypause(char to){
	while(1){
		if(kbhit()){
			char ch = getch();
			if(ch == to){
				system("cls");
				break;
			}
		}
	}
}
void setup(){//1评测方式2对拍方式
	
}
#endif

用法嘛,其他都一样,参考c++编写评测机(1)。不同的就是要在评测及所在的文件夹里新建一个文件夹,命名为data,将输入数据(sample.in)和测试点数据(textpoint.txt)放入,就可以了。

后续透露

现在的评测机只能和std.cpp生成的答案进行比较,如果没有标程就无法评测。所以我们要加一种对拍方式。就透露这么多了~


ps:代码里有剧透。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值