ACM、OJ,算法在线判题系统。
帮朋友完成毕业设计而写的,软件环境windows系统,语言是C# winform(因为我不熟悉asp.net,现在暂用winform写的demo)。
看了下其他相关论文、黑盒测试思想,基本都是基于PHP,jsp的oj系统,我综合其简单思想,现在只是C#而写的语言,目前gcc、g++、vc(vs2010)测试通过,java,还在debug中。
这里有个需要说明下,在acm的比赛中,数据的输出输入平台是控制台(命令行).....
例如
题目: A+B Problem
描述
输入
输出
输入样例
1 2
输出样例
3
代码如下:
#include<stdio.h>
int main()
{
int a,b;
while(scanf("%d%d",&a,&b)!=EOF)
{
printf("%d/n",a+b);
}
return ;
}
一般都是编译,生成运行,输入,输出。
而自动化,是直接提交,返回结果。
我们分析下一个简易的评判端工作流程:
接收提交的代码
||
编译代码 = _编译错误 = 返回编程错误结果
||
运行编译后的程序
||
对输出的结果进行判断
上面这个工作流程我省略了大部分的细节,只是让大家都先对整个流程有个整体的把握。
接着我们再开始说说一个通用的oj一步一步是如何设计实现的。
一.接收代码(提交代码)
这部分可以通过很多途径,也并非本文的要点,在此忽略,抱歉抱歉。。。我写的demo,是直接保存为*.c的文件
二.编译代码
也许习惯在windows下用IDE的童鞋们很少接触命令行编译这东西吧?
没错,我们需要用到的就是命令行编译,在命令行下调用编译器的命令行编译程序,让它来完成编译工作。
举个windows下的例子:我这里用的是mingw的编译工具gcc。
首先安装好,我demo是用的C——free这个IDE自带的mingw。
然后,你可以试试运行cmd打开控制台
准备好一个c/c++程序,在控制台输入“gcc c:/test.c”
这时你就会发现目录里多了a.exe这个文件.
a.exe就是编译好的文件,如果你的代码出现问题,cl会把错误提示在控制台上显示出来
你也可以编写代码来编译这个test.c文件
C#代码是:
Process.start("gcc test.c");
三.运行程序
这是一个简易的OJ系统中的关键部分。
首先,我们需要对这个运行的程序进行计时,若程序超出时间,必须能自动kill它。否则,评判机将可能因为运行程序死循环而停止工作下一步的工作或者同时运行过多死循环的程序而崩溃。。
第二,我们需要把这个程序的输出和输入重定向到文本。
输入流:自动评判机是不会从键盘输入数据到控制台的,所以从键盘的输入需要重定向到文本(我们可以事先写好这个文本的内容),这样,就可以模拟手动从键盘向程序输入数据了。
输出流:在自动评判的时候没有人为介入,所以输出到屏幕显示并无意义,我们需要把原本输出到屏幕的内容重定向输出到文本。而且这样可以对用户的程序输出流进行保存,也方便接下来的答案评判处理
鉴于这部分比较沉长~决定拿出来作为一个单独的篇章来写,有兴趣的童鞋可以等一下下,我会很用力的写好它。。
四.对输出的结果进行判断
这里需要用到第三步骤的输出流重定向的文件。。
我们回头看下第三步骤,重定向输入输出流到文件,也就是说,我们的输入文件是事先根据题目准备好的。
ps: 超出时间暂时没写了,p.VirtualMemorySize(当前进程的虚拟内存,还有一个物理内存); p.UserProcessorTime(当前用户运行时间);p.StartTime(当前进程开始时间)相关的属性。
关键代码如下:
Process p = new Process();
//设定程序名
p.StartInfo.FileName = "cmd.exe";
//关闭Shell的使用
p.StartInfo.UseShellExecute = false;
//重定向标准输入
p.StartInfo.RedirectStandardInput = true;
//重定向标准输出
p.StartInfo.RedirectStandardOutput = true;
//重定向错误输出
p.StartInfo.RedirectStandardError = true;
//设置不显示窗口
p.StartInfo.CreateNoWindow = true; // 保存源文件
System.IO.File.WriteAllText(Application.StartupPath + @"\test\1000.c", txt_coder.Text, Encoding.Default);
// 获取gcc 执行文
string strPath = Application.StartupPath + @"\mingw\bin\gcc.exe 1000.c";
p.Start();
// 切换到test目录下
p.StandardInput.WriteLine("cd test");
//执行gcc命令
p.StandardInput.WriteLine(strPath); // 等待编译完成
Thread.Sleep();
// 文件重定向,用的管道
p.StandardInput.WriteLine("a.exe<in.txt>myout.txt");
// 检查生成的myout.txt 和 指定的out.txt的数据对比
p.StandardInput.WriteLine("FC myout.txt out.txt");
p.StandardInput.WriteLine("exit"); // 退出
string str = p.StandardOutput.ReadToEnd(); // cmd显示的字符串,放入str中
p.Close();
p.Dispose(); // 测试显示····
MessageBox.Show(str); // 如果out.txt与myout.txt相同,cmd显示无差异,不同,则显示5个*,详细自己在cmd测试fc命令
if (str.IndexOf("**") < )
MessageBox.Show("恭喜你,AC拉", "友情提示");
else MessageBox.Show("sorry,WA拉", "友情提示");
项目下载:http://download.csdn.net/download/orange1438/6941779
作者:orange1438
出处:http://www.cnblogs.com/orange1438/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。