ACM、OJ,算法在線判題系統。java
幫朋友完成畢業設計而寫的,軟件環境windows系統,語言是C# winform(由於我不熟悉asp.net,如今暫用winform寫的demo)。c++
看了下其餘相關論文、黑盒測試思想,基本都是基於PHP,jsp的oj系統,我綜合其簡單思想,如今只是C#而寫的語言,目前gcc、g++、vc(vs2010)測試經過,java,還在debug中。算法
這裏有個須要說明下,在acm的比賽中,數據的輸出輸入平臺是控制檯(命令行).....編程
例如 windows
題目: A+B Problemasp.net
描述jsp
輸入工具
輸出測試
輸入樣例spa
1 2
輸出樣例
3
代碼以下:
1 #include<stdio.h> 2 int main() 3 { 4 int a,b; 5 while(scanf("%d%d",&a,&b)!=EOF) 6 { 7 printf("%d/n",a+b); 8 } 9 return 0; 10 }
通常都是編譯,生成運行,輸入,輸出。
而自動化,是直接提交,返回結果。
咱們分析下一個簡易的評判端工做流程:
接收提交的代碼
||
編譯代碼 = _編譯錯誤 = 返回編程錯誤結果
||
運行編譯後的程序
||
對輸出的結果進行判斷
上面這個工做流程我省略了大部分的細節,只是讓你們都先對整個流程有個總體的把握。
接着咱們再開始說說一個通用的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(當前進程開始時間)相關的屬性。
關鍵代碼以下:
1 Process p = new Process(); 2 //設定程序名 3 p.StartInfo.FileName = "cmd.exe"; 4 //關閉Shell的使用 5 p.StartInfo.UseShellExecute = false; 6 //重定向標準輸入 7 p.StartInfo.RedirectStandardInput = true; 8 //重定向標準輸出 9 p.StartInfo.RedirectStandardOutput = true; 10 //重定向錯誤輸出 11 p.StartInfo.RedirectStandardError = true; 12 //設置不顯示窗口 13 p.StartInfo.CreateNoWindow = true; 14 15 // 保存源文件 16 System.IO.File.WriteAllText(Application.StartupPath + @"\test\1000.c", txt_coder.Text, Encoding.Default); 17 // 獲取gcc 執行文 18 string strPath = Application.StartupPath + @"\mingw\bin\gcc.exe 1000.c"; 19 p.Start(); 20 // 切換到test目錄下 21 p.StandardInput.WriteLine("cd test"); 22 //執行gcc命令 23 p.StandardInput.WriteLine(strPath); 24 25 // 等待編譯完成 26 Thread.Sleep(500); 27 // 文件重定向,用的管道 28 p.StandardInput.WriteLine("a.exe<in.txt>myout.txt"); 29 // 檢查生成的myout.txt 和 指定的out.txt的數據對比 30 p.StandardInput.WriteLine("FC myout.txt out.txt"); 31 p.StandardInput.WriteLine("exit"); // 退出 32 string str = p.StandardOutput.ReadToEnd(); // cmd顯示的字符串,放入str中 33 p.Close(); 34 p.Dispose(); 35 36 // 測試顯示···· 37 MessageBox.Show(str); 38 39 // 若是out.txt與myout.txt相同,cmd顯示無差別,不一樣,則顯示5個*,詳細本身在cmd測試fc命令 40 if (str.IndexOf("**") < 0) 41 MessageBox.Show("恭喜你,AC拉", "友情提示"); 42 else MessageBox.Show("sorry,WA拉", "友情提示");
項目下載:http://download.csdn.net/download/orange1438/6941779
做者:orange1438 出處:http://www.cnblogs.com/orange1438/ 本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。