最近无聊看了看gty的Gena感觉非常 的高大上。
其实我非常早的就想自己弄一个自动评测软件了,于是学习了以下开始动手。
然后发现有非常多的问题,大部分问题都是用黑科技解决,比如fork之后堆栈不再共用没办法互相传递信息,那么我们就开一个文件来传递信息。
不过还是不少地方借鉴了以下,比如得到内存信息,和时间记录的方式(clock函数会出现一些奇怪的问题)
//coder : davidwang #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <sys/types.h> #include <unistd.h> #include <sys/timeb.h> #include <ctime> #include <sys/stat.h> #include <sys/wait.h> #include <vector> #include "My_checker.hpp" using namespace std; /* this program is to check a OI program with specific testcases ./checker [-t Time_limit(ms)]{default : 1000} [-T Time_limit(s)] [-m memory_limit(b)]{default:256Mb} [-M memory_limit(mb)] [-f path of programm and testcases]{default: current path} [-F initial file] [-I input files]{default: a.in} [-O output files] {default: a.out} */ void init_file(char *s1); void show_help(); void work(); vector<string>list; int init(int argv,char *argc[]){ for (int i=1;i<argv;i+=2){ if (!strcmp(argc[i],"--help")){ show_help(); return -1; } if (!strcmp(argc[i],"-t")) sscanf(argc[i+1],"%d",&Time_limit); else if (!strcmp(argc[i],"-T")) sscanf(argc[i+1],"%d",&Time_limit),Time_limit*=1000; else if (!strcmp(argc[i],"-m")) sscanf(argc[i+1],"%d",&Memory_limit); else if (!strcmp(argc[i],"-M")) sscanf(argc[i+1],"%d",&Memory_limit),Memory_limit*=1024*1024; else if (!strcmp(argc[i],"-f")){ sscanf(argc[i+1],"%s",path); used_path=1; }else if (!strcmp(argc[i],"-F")){ init_file(argc[i+1]); return 1; }else if (!strcmp(argc[i],"-I") || !strcmp(argc[i],"-i")){ Infile=1; sscanf(argc[i+1],"%s",input_file); }else if (!strcmp(argc[i],"-O") || !strcmp(argc[i],"-o")){ Outfile=1; sscanf(argc[i+1],"%s",output_file); } } return 0; } int type=-1; int make_file(){ sprintf(cmd,"ls %s >cur_files_list.ckr",path); system(cmd); f1=fopen("cur_files_list.ckr","r"); while (fscanf(f1,"%s",cur)!=EOF){ list.push_back(string(cur)); } fclose(f1); system("rm -r cur_files_list.ckr"); sort(list.begin(),list.end()); //0 for cpp 1 for c 2 for pas char tmp[110]; for (int i=0;i<list.size();i++){ int pos=-1; if (list[i]==string("cur_files_list.ckr")){ list.erase(list.begin()+i); i--; continue; } if (list[i]==string("My_checker.cpp")){ list.erase(list.begin()+i); i--; continue; } if (list[i]==string("My_checker")){ list.erase(list.begin()+i); i--; continue; } for (int j=0;j<list[i].length();j++){ if (list[i][j]=='.'){ pos=j; memset(tmp,0,sizeof(tmp)); for (int k=pos+1;k<list[i].length();k++){ tmp[k-pos-1]=list[i][k]; } if (!strcmp(tmp,"cpp")){ if (type!=-1){ printf("Error : multiple program included\nautochecker failed,please use file style"); return -1; } printf("%d\n",pos); for (int k=0;k<pos;k++) program_name[k]=list[i][k]; type=0; list.erase(list.begin()+i); i--; }else if (!strcmp(tmp,"pas")){ if (type!=-1){ printf("Error : multiple program included\nautochecker failed,please use file style"); return -1; } for (int k=0;k<pos;k++) program_name[k]=list[i][k]; type=1; list.erase(list.begin()+i); i--; }else if (!strcmp(tmp,"c")){ if (type!=-1){ printf("Error : multiple program included\nautochecker failed,please use file style"); return -1; } for (int k=0;k<pos;k++) program_name[k]=list[i][k]; type=2; list.erase(list.begin()+i); i--; }else if (strcmp(tmp,"in") && strcmp(tmp,"out")){ list.erase(list.begin()+i); i--; } break; } } if (pos==-1){ list.erase(list.begin()+i); i--; } } #ifdef DEBUG printf("list begin! with %d\n",list.size()); for (int i=0;i<list.size();i++){ cout<<list[i]<<endl; } puts("list end"); #endif if (type==-1){ printf("Error: No program found!\n checker failed"); return -1; } } int Result,Running; inline int testcase(string input,string output,string program_name){ #ifdef DEBUG printf("check(%s,%s)\n",input.c_str(),output.c_str()); #endif if (used_path) sprintf(cmd,"cat %s/%s > %s",path,input.c_str(),input_file); else sprintf(cmd,"cat %s > %s",input.c_str(),input_file); #ifdef DEBUGcmd puts(cmd); #endif system(cmd); timeb times,timet; ftime(×); int stat; int pid=fork(); if (pid<0){ printf("checker failed!\n"); return 5; } if (pid==0){ char In[22],Out[22]; // if (!Infile) sprintf(In," <%s.in",program_name.c_str()); // if (!Outfile) sprintf(Out," >%s.out",program_name.c_str()); if (used_path) sprintf(cmd,"cd %s && ./%s",path,program_name.c_str()); else sprintf(cmd,"./%s",program_name.c_str()); #ifdef DEBUGcmd puts(cmd); #endif int id=system(cmd); f2=fopen("finished_running_time.ckr","w"); fprintf(f2,"finished!"); fclose(f2); #ifdef DEBUG printf("son progress return ed normally"); #endif while (1); return id; }else{ mem=0; Rtime=0; while (1){ ftime(&timet); mem=max(mem,getmemory(pid)); Rtime=(timet.time - times.time) * 1000 + (timet.millitm - times.millitm); if (Rtime>Time_limit){ Result=2; kill_judge(pid); Running=0; #ifdef DEBUG printf("parent progress return ed TLE"); #endif return 0; }else if (mem>Memory_limit){ // Result=3; // kill_judge(pid); // Running=0; #ifdef DEBUG printf("parent progress return ed MLE"); #endif // return 0; } f1=fopen("finished_running_time.ckr","r"); if (f1==NULL) continue; kill_judge(pid); Running=0; system("rm -r finished_running_time.ckr"); break; } #ifdef DEBUG printf("parent progress return ed nomally"); #endif wait(&stat); int i=WEXITSTATUS(stat); // printf("son program returned %d\n",i); if (i){ Running=0; Result=4; return 0; } Running=0; Result=check(output); return 0; } } inline void sleep_with_limit(int T){ timeb s,t; ftime(&s); while (1){ if (Running==0) return; ftime(&t); if (t.time-s.time>T+1 || t.time-s.time) return; } } int work_auto() { int tmp=make_file(); if (tmp==-1){ return -1; } int Compile_id; if (type==0){ if (used_path) sprintf(cmd,"g++ -o2 %s/%s.cpp -o %s/%s",path,program_name.c_str(),path,program_name.c_str()); else sprintf(cmd,"g++ -o2 %s.cpp -o %s",program_name.c_str(),program_name.c_str()); Compile_id=system(cmd); }else if (type==1){ if (used_path) sprintf(cmd,"fpc -o2 %s/%s.pas",path,program_name.c_str()); else sprintf(cmd,"fpc -o2 %s.pas",program_name.c_str()); Compile_id=system(cmd); }else if (type==2){ if (used_path) sprintf(cmd,"gcc -o2 %s/%s.c -o %s/%s",path,program_name.c_str(),path,program_name.c_str()); else sprintf(cmd,"gcc -o2 %s.c -o %s",program_name.c_str(),program_name.c_str()); Compile_id=system(cmd); } if (Compile_id){ puts(result[5]); return 5; } int Id=0,now; if (!Infile){ if (used_path) sprintf(input_file,"%s/%s.in",path,program_name.c_str()); else sprintf(input_file,"%s.in",program_name.c_str()); } if (!Outfile){ if (used_path) sprintf(output_file,"%s/%s.out",path,program_name.c_str()); sprintf(output_file,"%s.out",program_name.c_str()); } int ip; int pre; for (ip=0;ip<list.size();ip=pre+2){ pre=ip; Running=1; testcase(list[ip],list[ip+1],program_name); sleep_with_limit(Time_limit/1000); if (!Id) Id=Result; printf("%s time:%d memory:%d\n",result[Result],Rtime,mem); sprintf(cmd,"rm -r %s",input_file); system(cmd); if (used_path) sprintf(cmd,"rm -r %s/%s",path,output_file); else sprintf(cmd,"rm -r %s",output_file); system(cmd); } return Id; } int main(int argv,char *argc[]) { int tmp=init(argv,argc); if (tmp==-1) return 0; else if (tmp==1){ printf("Error!\n"),show_help(); return 0; }else if (tmp==2){ work(); }else{ int ret=work_auto(); } return 0; }
//coder : davidwang #include <string> using namespace std; const int DefaultTime_limit=1000; const int DefaultMemory_limit=256*2048*2048; int Time_limit=DefaultTime_limit,Memory_limit=DefaultMemory_limit; char cmd[1000],cur[110]; char input_file[1000],output_file[1000]; string program_name; int Infile,Outfile; FILE *a1,*f1,*f2; int mem,Rtime; char path[2500]; int used_path; char result[100][100]={"Accepted","Wrong Answer","Time Limit Exceeded","Memory Limit Exceeded","Runtime Error","Compile Error"}; // 0: Accepted 1: Wrong Answer 2: TLE 3: MLE 4: RE 5: CE inline int getmemory(int pid) { sprintf(cmd, "ps -eo pid,rss | grep %d", pid); FILE *f = popen(cmd, "r"); int a; fscanf(f, "%d%d", &a, &a); pclose(f); return a; } void kill_judge(int pid) { sprintf(cmd, "kill -s 9 %d", pid); system(cmd); } void init_file(char *s1){ } void show_help(){ printf("this program is to check a OI program with specific testcases\n./checker [-t Time_limit(ms)]{default : 1000} [-T Time_limit(s)] [-m memory_limit(b)]{default:256Mb} [-M memory_limit(mb)] [-f path of programm and testcases]{default: current path} [-F initial file] [-I input files]{default: (s).in} [-O output files] {default: (s).out}\n"); return; } void work() { } char s1[1000010],s2[1000010]; char o1[1000],o2[1000]; inline int check(string output,string checker=string("cmp")) { FILE *fout,*fstd; // printf("checker runned!"); if (used_path) sprintf(o1,"%s/%s",path,output.c_str()); else sprintf(o1,"%s",output.c_str()); if (used_path) sprintf(o2,"%s/%s",path,output_file); else sprintf(o2,"%s",output_file); fstd=fopen(o1,"r"); fout=fopen(o2,"r"); // puts(output_file); // puts(output.c_str()); int t=0; while (fscanf(fstd,"%s",s1)!=EOF){ if (fscanf(fout,"%s",s2)==EOF){ printf("checker log: your output is shorter than standard output\n"); return 1; } t++; // puts(s1); // puts(s2); if (strcmp(s1,s2)){ printf("checker log: Wrong with the %d segment!\n",t); printf("%s %s\n",s1,s2); return 1; } } if (fscanf(fout,"%s",s2)!=EOF){ printf("checker log: Your output is longer than standard output!\n"); return 1; } return 0; }
放在一个目录下编译就可以用了,暂时只支持linux……
2015年6月22日 16:08
是厉害!
2015年6月23日 16:37
跪跪跪