c++编写评测机(4)

目录

前言

完善

完整代码

后续透露


前言

第三版已经很完善了,本版本主要是完善细节以及把上次代码里的剧透完善。完善后评测机就基本上可以完成日常的评测了。不过以后肯定还会有后续,而且后续的评测机会越来越趋近完善,最终目标是做成一个评测软件。看着评测机一点点完善,我觉得最终目标也不远了。

好了,废话不多说进入今天正题吧。

首先,v1.0.2版本中可以优化的有以下几个地方

  1. 只能与std.cpp输出的答案进行比较,若没有std.cpp就无法进行比较。
  2. 到现在评测机都没有一个名字~(现在看起来不是个问题,但到了以后做软件肯定得有个名字吧)。
  3. 加点有意思的东西。

完善

1.我们想想,怎么才能直接和文件进行比较呢?其实实现非常简单,我们只需要增加一个“与cpp比较”的选项,选中后就与cpp比较,否则就与目标文件中存放的答案进行比较。与答案进行比较时,就把编译std.cpp的过程跳过,依旧将答案存入std.out文件中。由于原来就是将ans.out和std.out进行比较,所以将答案存入std.out后可以直接用后面的代码进行比较。

while(1){
	system("cls");
    printf("0:返回\n1:与cpp比较");
	if(std_judge){
	    printf("√\n");
	}else{
        printf("-\n");
	}
    char std_choose = getch();
	if(std_choose == '1') std_judge = !std_judge;
	else if(std_choose == '0'){
	    system("cls");
	    break;
	}
}

其中std_judge是爬满断是否与std.cpp进行比较,否则就直接与答案进行比较。

知道了是否与答案直接进行比较,那么如何与答案进行直接比较呢?

if(!std_judge){
			string std_toname = samplename + temp + ".out";
			const char *std_name2 = std_toname.c_str();
			if(!findfile(std_name2, 0)){
				cout << "未找到" << std_name2 << "!\n";
				continue;
			}
			printsample(std_name2, stdname);
			start = clock();
			outcheck_ans = system("ans.exe");
			end = clock();
			elapsed_secs = static_cast<double>(end - start);
			if(outcheck_ans == -1 || WIFEXITED(outcheck_ans) == false || 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(!ifcontinue) continue;
			enter_deal("ans.out", ifblank, ifenter);
			enter_deal("std.out", ifblank, ifenter);
			int count_ans = 0;
			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";
			}
		}

可以发现,相较于和std.cpp进行比较,直接与答案进行比较只不过是把编译std.cpp的代码去掉了,并且把sample.out中的答案存入std.out中,后面依旧是将ans.out和std.out进行比较。

2.评测及到现在还没有个名字呢,我们取个什么名字呢?还是让你们投票决定吧!(个人认为叫水滴比较好)。

3.我们给评测及加点有意思的东西吧,不然太单调了。加点什么呢?比方说打卡。我们可以统计连续打卡天数,并规定有一天段开就从零开始重新计数(太残忍了qwq)。

void daka(){
    FILE *fp = fopen("daka.sdsys", "r+");
    if (fp == NULL) {
        createFile("daka.sdsys");
    }
    time_t now = time(NULL);
    struct tm *tm_now = localtime(&now);
    int today = tm_now->tm_yday;
    int last_day = 0, streak = 1;
    fscanf(fp, "%d%d", &last_day, &streak);
    if (last_day == today) {
        printf("今天已经打卡了!连续打卡%d天!\n", streak);
    }else{
        fseek(fp, 0, SEEK_SET);
        fprintf(fp, "%d", today);
        fflush(fp);
        if(last_day == today - 1) {
            streak++;
        }else{
        	streak = 1;
		}
        printf("打卡成功!连续打卡 %d 天!\n", streak);
        fprintf(fp, " %d", streak);
    }
    fclose(fp);
}

把打卡天数存入daka.sddays文件中,文件的后缀名其实是我自己编的,为的是不让用户自己改动打卡天数。这样就能实现打卡了! 

我们的v1.0.3版本就完善好了。

完整代码

tools.h

//v1.0.3
#ifndef TOOLS_H
#define TOOLS_H
#include<bits/stdc++.h>
#include<dirent.h>
#include<windows.h>
#include<conio.h>
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
#define WIFEXITED(status) ((status & 0x7f) == 0)
using namespace std;
namespace My_Space{
	char textpoint[10005];
	char buf[10000];
	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";
	const char *stdname = "std.out";
	string samplename = "sample";
	bool ifblank = 1, ifenter = 1, std_judge = 1;
	struct SAMPLE{
		int time_limit, point;
	}sample[1005];
}
using namespace My_Space;
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);
}
void createFile(char* fileName) {
    FILE* fp;
    fp = fopen(fileName, "w");
    if(fp == NULL) {
        printf("Error: cannot create file!\n");
    } else {
        printf("File created successfully!\n");
        fclose(fp);
    }
}
void daka(){
    FILE *fp = fopen("daka.sdsys", "r+");
    if (fp == NULL) {
        createFile("daka.sdsys");
    }
    time_t now = time(NULL);
    struct tm *tm_now = localtime(&now);
    int today = tm_now->tm_yday;
    int last_day = 0, streak = 1;
    fscanf(fp, "%d%d", &last_day, &streak);
    if (last_day == today) {
        printf("今天已经打卡了!连续打卡%d天!\n", streak);
    }else{
        fseek(fp, 0, SEEK_SET);
        fprintf(fp, "%d", today);
        fflush(fp);
        if(last_day == today - 1) {
            streak++;
        }else{
        	streak = 1;
		}
        printf("打卡成功!连续打卡 %d 天!\n", streak);
        fprintf(fp, " %d", streak);
    }
    fclose(fp);
}
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){
	const char* filename = str_filename.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(string str_name){
	system("ans.exe");
	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);
		if(std_judge){
			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";
			}
		}else{
			string std_toname = samplename + temp + ".out";
			const char *std_name2 = std_toname.c_str();
			if(!findfile(std_name2, 0)){
				cout << "未找到" << std_name2 << "!\n";
				continue;
			}
			printsample(std_name2, stdname);
			start = clock();
			outcheck_ans = system("ans.exe");
			end = clock();
			elapsed_secs = static_cast<double>(end - start);
			if(outcheck_ans == -1 || WIFEXITED(outcheck_ans) == false || 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(!ifcontinue) continue;
			enter_deal("ans.out", ifblank, ifenter);
			enter_deal("std.out", ifblank, ifenter);
			int count_ans = 0;
			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";
			}
		}
	}
}
void start_judge(){
	string tool = "\\data\\";
	string name = "textpoint.txt";
	string file_name = buf + tool + name;
	getpoint(file_name);
	if(findfile("ans.out")) system("del ans.out");
	if(findfile("std.out")) system("del std.out");
	if(findfile("ans.exe")) system("del ans.exe");
	if(findfile("std.exe")) system("del std.exe");
	if(findfile("test.in")) system("del test.in");
    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("ans.cpp");
	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);
	}
}
bool initialize(){
	bool back = 1;;
	if(std_judge && !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;
			}
		}
	}
}
#endif

评测机.cpp 

//v1.0.3
#include"tools.h"
int main(){
	system("title 水滴评测机");
	color(7);
	GetCurrentDirectory(1000, buf);
	Clear_Qiuckedit();
	while(1){
		hide();
		gotoxy(1, 1);
		printf("1:评测 2:设置 3:刷新 4:打卡\n");
		char choose = getch();
		if(choose == '1'){
			system("cls");
			if(!initialize()){
				printf("0:返回\n");
				Mypause('0');
				continue;
			}
			start_judge();
			if(findfile("ans.out")) system("del ans.out");
			if(findfile("std.out")) system("del std.out");
			if(findfile("ans.exe")) system("del ans.exe");
			if(findfile("std.exe")) system("del std.exe");
			if(findfile("test.in")) system("del test.in");
			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'){
					while(1){
						system("cls");
	                    printf("0:返回\n1:与cpp比较");
	                    if(std_judge){
	                    	printf("√\n");
						}else{
							printf("-\n");
						}
						char std_choose = getch();
						if(std_choose == '1') std_judge = !std_judge;
	                    else if(std_choose == '0'){
	                    	system("cls");
							break;
						}
					}
				}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();
		}else if(choose == '4'){
			bool ifbreak = 0;
			system("cls");
			daka();
			printf("按任意键返回。\n");
			while(1){
				if(kbhit()){
					ifbreak = 1;
					system("cls");
					break;
				}
				if(ifbreak) break;
			}
		}
	}
	return 0;
}

使用方法和v1.0.2相同,参考c++编写评测机(3)

后续透露

下一个版本可以说是最重磅的了,因为自从下一个版本开始,我们就像软件的方向完善了,实用性也更高一个档次。

最后,请给个三连把~期待下一版哦!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值