ACM在线评判系统核心代码

本文详细解析了ACM在线评判系统的实现原理及关键代码,包括输入输出重定向、异常处理、测试函数等核心组件,适用于竞赛编程和系统开发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ACM在线评判系统核心代码:

转载自:http://hi.baidu.com/%CA%A5%D5%BD%CA%BF1991/blog/item/4e59731406142b1c4b90a739.html

#include <windows.h>
#include <process.h>//for _endthread and _beginthread
#include <string>
#include <fstream>
#include <iostream>
#include "psapi.h"//for getting information like memory statistics
#include "Do_File.h"//for jni

using namespace std;
/// <summary>
/// run 进行在线测试
/// Builder:唐彦 2009 1 20
/// V1.0 2009 1 20
/// </summary>

/*实现输入输出重定向相关参数*/
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<s1_len)
   return false;

for(i=0,j=0;i<s1_len;i++,j++){
   if(s1[i]=='\n'){
    if(s2_len-j<s1_len-i)
     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<<"test function is called!"<<endl;
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<<"bytesRead1:"<<bytesRead1<<endl;
   // test_out<<"buffer1:"<<buffer1<<endl;
    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;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值