抱歉笨拙的英语;这不是我的母语。
我正在开发在线评判,以便在下学期使用。
这将从学生那里收到一个.java文件并进行编译,
并运行.class并由教授用预定义的测试用例进行测试。
但是当我在下面提交一个java文件时,Enter.java,出现了执行错误,并且.java文件被判为ExecutionError。
import java.util.Scanner;
public class Enter {
public static void main(String[] args) {
// TODO Auto-generated method stub
int i=0;
int max=0;
int min=10000000;
while(true)
{
System.out.print("Enter integer :");
Scanner input = new Scanner(System.in);
i = input.nextInt();
if(i==-1)
break;
else if(i>max)
{
max=i;
}
else if(i<min)
{
min=i;
}
}
System.out.printf("Smallest Integer is : %d",min);
System.out.println();
System.out.printf("Largest Integer is : %d", max);
}
}
当然,这不是一个正确的源代码,但是我觉得系统将其判断为ExecutionError(这意味着系统运行.class时会发生异常,以便用testcases对其进行测试)。 并且在Input.nextInt()中也会出现NoSuchElementException; 但它应该被判断为失败(运行和结束,但产生错误的输出)。
这是JudgeModule.java的来源
private Judgement judge() {
// some works before compile & test //
// phase 1. compile //
CompileResult compileResult = tester.doCompile(compiler, fd);
if( !compileResult.isSuccess() ) // compile fail
{
// some works
Judgement judgement = new Judgement(compileResult.getResult());
return judgement;
}
// pahse 2. execute
ExecuteResult executeResult = tester.doTest(compiler, fd, testcases);
if( executeResult.getException() != null )
{
// some works
Judgement judgement = new Judgement(executeResult.getResult());
return judgement;
}
// some works after compile & test//
Judgement judgement = new Judgement(executeResult.getResult());
return judgement;
}
tester只是SourcecodeTester的一个实例,没有成员变量,只是持有doCompile()和doTest()。
以下是SourcecodeTester的来源。我省略了doCompile()的事情。
public class SourcecodeTester {
static long executeTimeout = 1000;
public class ExecuteResult {
JudgeResult result;
Exception exception;
ArrayList<TestResult> testResults;
}
public class TestResult {
JudgeResult result;
Exception exception;
String output;
}
public ExecuteResult doTest(Compiler compiler, FileDescription fd, Testcase[] testcases )
{
// pahse 2. execute
JudgeResult result = JudgeResult.Pass;
Exception exception = null;
ArrayList<TestResult> testResults = new ArrayList<>();
try {
for( Testcase testcase : testcases )
{
testResults.add( execute(compiler, testcase, fd ) );
}
} catch( Exception e ) {
e.printStackTrace();
result = JudgeResult.SystemError;
exception = e;
}
// do some works
return new ExecuteResult(result, exception, testResults );
}
private TestResult execute(Compiler compiler, Testcase testcase, FileDescription fd )
{
Runtime runTime = Runtime.getRuntime();
String executeCommand = assembleExecuteCommand(compiler, fd);
JudgeResult executeResult = JudgeResult.Fail;
Exception executeException = null;
String executeOutput = "";
try {
boolean timeout = false;
long startTime = System.currentTimeMillis();
Process executeProcess = runTime.exec(executeCommand);
writeToProcessInput(executeProcess, testcase.getInput()); // write to process input
while( executeProcess.isAlive() && !timeout )
{
Thread.sleep(10);
if((System.currentTimeMillis()-startTime) > executeTimeout )
timeout = true;
}
if( timeout )
{
executeProcess.destroy();
throw new JudgeException("execution timeout!" + (System.currentTimeMillis()-startTime) + "ms", JudgeResult.ExecutionTimeout);
}
// exam exitValue
int exitValue = executeProcess.exitValue();
// read from process output
char[] processOutput = readFromProcessOutput(executeProcess);
// read from process error
char[] processError = readFromProcessError(executeProcess);
if( exitValue != 0 ) {
throw new JudgeException("execution fail with exitvalue : " + exitValue + " >\n" + String.valueOf(processError), JudgeResult.ExecutionError);
}
else if( processError.length != 0 ) {
throw new JudgeException("execution fail with error : " + String.valueOf(processError), JudgeResult.ExecutionError );
}
String output = String.valueOf(testcase.getOutput()).replaceAll("\r\n", "\n");
executeOutput = String.valueOf(processOutput);
if( Arrays.equals(processOutput, output.toCharArray()) ) {
executeResult = JudgeResult.Pass;
}
else {
executeResult = JudgeResult.Fail;
}
}
catch( JudgeException e ) {
e.printStackTrace();
executeResult = JudgeResult.ExecutionError;
executeException = e;
}
catch( Exception e ) {
e.printStackTrace();
executeResult = JudgeResult.SystemError;
executeException = e;
}
return new TestResult( testcase.getId(), executeResult, executeException, executeOutput );
}
private void writeToProcessInput(Process _process, char[] _dataToWrite ) throws IOException
{
OutputStreamWriter osw = new OutputStreamWriter(_process.getOutputStream() );
BufferedWriter writer = new BufferedWriter( osw );
writer.write( _dataToWrite );
// osw.write(_dataToWrite);
writer.close();
osw.close();
}
private char[] readFromProcessOutput(Process _process) throws IOException
{
return readFromStream( new InputStreamReader( _process.getInputStream() ) );
}
private char[] readFromProcessError(Process _process) throws IOException
{
return readFromStream( new InputStreamReader( _process.getErrorStream() ) );
}
private char[] readFromStream(InputStreamReader isr) throws IOException {
int numOfByteRead;
char[] readBuffer = new char[1024];
StringBuffer standardOutput = new StringBuffer();
while ((numOfByteRead = isr.read(readBuffer)) > 0) {
standardOutput.append(readBuffer, 0, numOfByteRead);
}
return standardOutput.toString().toCharArray();
}
}
当我从命令行或Eclipse编译并执行Enter.java时, 它工作正常,我可以从控制台输入几个数字,没有异常发生。
但是我将它提交给OnlineJudge,然后发生NoSuchElementException。 用于测试的输入字符数组只包含由空格字符分隔的多个数字。
最后,我想问的是,
之间的差异以及它的工作方式有何不同
为什么Enter.java上的scanner.nextInt()会抛出NoSuchElementException?
如何将OnlineJudge修改为Enter.java的工作方式相同。