ACM在线评判系统核心代码:
#include
#include //for _endthread and _beginthread
#include
#include
#include
#include "psapi.h"//for getting information like memory statistics
#include "Do_File.h"//for jni
using namespace std;
///
/// run 进行在线测试
/// Builder:唐彦 2009 1 20
/// V1.0 2009 1 20
///
/*实现输入输出重定向相关参数*/
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa,sa2;
HANDLE hInputRead,hInputWrite;
HANDLE hOutputRead,hOutputWrite;
/*初始被验证的源代码为ACCEPTED*/
bool flag=true;
/*测试程序运行的起始和结束时间*/
DWORD begin_time,end_time;
/*定义为全局,以便在test进程不正常退出的情况下能够被关闭*/
FILE *fin;//输入文件指针
HANDLE fout;//输出文件句柄
/*exe文件名、输入文件名、输出文件名、临时输出文件名*/
char APPNAME[256];
char INPUTFILE[256];
char ANSWERFILE[256];
//char TEMPFILE[256];
//ofstream test_out("d:\\test\\test_rs.txt");
bool _strcmp(const char* s1,const char* s2){
int i,j,s1_len=strlen(s1),s2_len=strlen(s2);
if(s2_len
return false;
for(i=0,j=0;i
if(s1[i]=='\n'){
if(s2_len-j
return false;
if(s2[j]=='\r'&&s2[j+1]=='\n')
++j;
else
return false;
}else{
if(s1[i]==s2[j]);
else
return false;
}
}
if(j==s2_len)
return true;
return false;
}
//是否存在异常
BOOL existException(DWORD dw){
switch(dw){
case EXCEPTION_ACCESS_VIOLATION:
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_BREAKPOINT:
case EXCEPTION_SINGLE_STEP:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_INEXACT_RESULT:
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_FLT_UNDERFLOW:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_PRIV_INSTRUCTION:
case EXCEPTION_IN_PAGE_ERROR:
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
case EXCEPTION_STACK_OVERFLOW:
case EXCEPTION_INVALID_DISPOSITION:
case EXCEPTION_GUARD_PAGE:
case EXCEPTION_INVALID_HANDLE:
return TRUE;
default:
return FALSE;
}
}
//测试函数
void test(void *dummy){
//test_out<
DWORD dwWritten;
//strcat(TEMPFILE,".tmp");
//打开测试数据文件
fin = fopen(INPUTFILE, "r" ),
//打开输出文件
fout=::CreateFile(ANSWERFILE,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
begin_time=::GetTickCount();
//写入测试数据
char szInPut[4096];
while(fgets( szInPut, 4096, fin ) != NULL){
WriteFile(hInputWrite, szInPut, strlen(szInPut), &dwWritten, NULL);
}
//判断输出结果是否正确
char buffer1[4096] = {0},buffer2[4096]={0};
DWORD bytesRead1,bytesRead2;
while(ReadFile(fout,buffer1,4095,&bytesRead1,NULL)!=NULL&&bytesRead1){
if(ReadFile(hOutputRead,buffer2,4095,&bytesRead2,NULL) == NULL || !_strcmp(buffer1,buffer2)){
// test_out<
// test_out<
flag=false;
break;
}
}
if(flag)
end_time=::GetTickCount();
_endthread();
}
/*
* Class: Do_File
* Method: exec
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)LExecInfo;
*/
JNIEXPORT jobject JNICALL Java_common_Do_1File_exec
(JNIEnv *env, jobject obj, jstring exe_file_path,
jstring input_file_path, jstring ans_file_path, jlong time_limit){
//以便捕获运行时异常,并屏蔽掉exception对话框的弹出
SetErrorMode(SEM_NOGPFAULTERRORBOX);
//参数类型转换
strcpy(APPNAME, (env)->GetStringUTFChars(exe_file_path, 0 ));
strcpy(INPUTFILE, (env)->GetStringUTFChars(input_file_path, 0 ));
strcpy(ANSWERFILE, (env)->GetStringUTFChars(ans_file_path, 0 ));
//获取Java中的实例类,必须带包名
jclass objectClass = (env)->FindClass("common/ExecInfo");
//获取类中每一个变量的定义
//使用的内存
jfieldID memory = (env)->GetFieldID(objectClass,"_memory","J");
//使用的时间
jfieldID used_time = (env)->GetFieldID(objectClass,"_used_time","J");
//执行的结果
jfieldID rs = (env)->GetFieldID(objectClass,"_rs","I");
//创建管道流,实现输入输出流重定向
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if(!CreatePipe(&hOutputRead,&hOutputWrite,&sa,0))
return NULL;
sa2.nLength = sizeof(SECURITY_ATTRIBUTES);
sa2.lpSecurityDescriptor = NULL;
sa2.bInheritHandle = TRUE;
if(!CreatePipe(&hInputRead,&hInputWrite,&sa2,0))
return NULL;
//设置进程初始化参数,并创建进程
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hOutputWrite;
si.hStdOutput = hOutputWrite;
si.hStdInput = hInputRead;
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//创建测试进程
if(!CreateProcess(APPNAME,NULL,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))
return NULL;
CloseHandle(hInputRead);
CloseHandle(hOutputWrite);
//异步调用,开始测试
_beginthread( test, 0, NULL);
//开始计时
Sleep((DWORD)time_limit);
//关闭流
fclose(fin);
CloseHandle(fout);
CloseHandle(hInputWrite);
CloseHandle(hOutputRead);
/*************************************************************/
if(!flag)//如果flag为false,评判结果优先定为wrong answer
(env)->SetIntField(obj,rs,common_Do_File_RUN_WRONG_ANSWER);
//进程状态值
DWORD dw;
//获取进程状态
GetExitCodeProcess(pi.hProcess, &dw);
if(existException(dw)){//是否在运行中出现"常见"异常,若存在,修正评判结果为Runtime error
(env)->SetIntField(obj,rs,common_Do_File_RUN_TIME_ERROR);
flag=false;
}
else if(dw==STILL_ACTIVE){//超时
TerminateProcess(pi.hProcess, 0);
(env)->SetIntField(obj,rs,common_Do_File_RUN_TIME_LIMIT);
flag=false;
}
if(flag){//accepted!
PROCESS_MEMORY_COUNTERS pmc;
GetProcessMemoryInfo(pi.hProcess,&pmc, sizeof(pmc)) ;
(env)->SetLongField(obj,memory,pmc.PeakWorkingSetSize);
(env)->SetLongField(obj,used_time,end_time-begin_time);
(env)->SetIntField(obj,rs,common_Do_File_RUN_ACCEPT);
}
CloseHandle(pi.hProcess);
//test_out.close();
return obj;
}