powershell批處理——io校驗
在刷題時,時常回想,OJ平臺是如何校驗競賽隊員提交的代碼的,OJ平臺并不看代碼,而是使用“黑盒測試”,用測試數據來驗證。對于每題,都事先設定了很多組輸入數據(datain)和輸出數據(dataout),OJ主要是看輸入datain,看產生的輸出是否與dataout一致。
如果需要一次性知道自己的所有測試輸入數據是否能得到正確輸出,一個一個測試就太慢了,批處理操作就能很好解決這個問題。本篇文章主要介紹一下這個ioCode
小項目,主要用于批處理校驗輸入輸出,搭建本地的評測平臺。
項目目錄結構
- input目錄:存放輸入數據文件,以
.in
后綴結尾 - output目錄:存放輸出數據文件,以
.out
后綴結尾,每個輸出的文件名與對應的輸入的文件名相同 - start.ps1:編寫的腳本文件
start.ps1源代碼:
function ioCheck{param($content, #程序輸出內容$answer #輸出的答案內容)$cnt = $answer.lengthif($content.length -ne $cnt){return 0 #內容行數不等,直接返回0}for($i=0;$i -lt $cnt;$i++){if($answer[$i] -ne $content[$i]){return 0} }return 1
}function ioCode{param([string]$command,[string]$inPath = './input',[string]$outPath = './output')$list = New-Object System.Collections.ArrayList #創建正確輸出的文件名集合$inFiles = Get-ChildItem -Path $inPath -Filter *.in #獲取輸入文件集$len = $inFiles.length$cnt = 0 foreach($file in $inFiles){try {$fullOut = cmd.exe /c "$command < $($file.fullName)" #獲取程序實際輸出內容$answerPath = Join-Path -Path $outPath -ChildPath ($file.BaseName + '.out')$answer = Get-Content -Path $answerPath #獲取該輸入文件的對應輸出文件的內容if(ioCheck $fullOut $answer){$list.add($file.Name) | Out-Null #Out-Null表示丟棄輸出$cnt++}}catch {Write-Host "處理文件 $($file.Name) 時出現錯誤: $_"}}Write-Host "正確輸出 $cnt/$len:"return @{CorrectCount = $cntTotalCount = $lenCorrectFiles = $list}
}
首先測試輸入兩個數,看能否成功輸出兩數之和
在input目錄中創建三個文件分別為001.in
,002.in
,003.in
內容分別為
001.in
3 4
002.in
35749 47985
003.in
544 6755
對應的在output目錄創建三個同名的.out
文件,分別為001.out
,002.out
,003.out
內容就是對應.in
文件中兩個輸入數據的相加的結果。
使用
編寫好測試用例,就是可以測試我們寫好的代碼了,這里不僅可以測試C/C++生成的.exe
可執行文件,還可以測試java生成的.class
可執行字節碼文件(前提是電腦具備java環境)。
測試.exe
文件
在當前目錄下準備一個test.cpp
文件,代碼如下:
#include<iostream>
using namespace std;
int main()
{int a, b;cin >> a >> b;cout <<a<<"+"<<b <<"=" << a + b;return 0;
}
將其編譯為可執行文件test.exe
:
g++ -o test.exe test.cpp
在當前目錄下打開powershell控制臺
- 通過點加載start.ps1文件
. './start.ps1'
- 輸入命令
ioCode {command} {inPath} {outPath}
,command為可執行命令,inPath為輸入文件目錄(默認為當前目錄的input目錄),outPath為輸出答案文件目錄(默認為當前目錄的output目錄)
ioCode test.exe
示例:
控制臺輸出顯示我們的三個測試用例都通過了。
測試可執行.class
文件
在當前目錄下準備一個Main.java
文件,代碼如下:
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int a = scanner.nextInt();int b = scanner.nextInt();System.out.println(a+b);}
}
將其編譯為可執行文件Main.class
:
javac Main.java
將其編譯為可執行文件test.exe
:
g++ -o test.exe test.cpp
在當前目錄下打開powershell控制臺
- 通過點加載start.ps1文件
. './start.ps1'
- 輸入命令
ioCode {command} {inPath} {outPath}
,command為可執行命令,inPath為輸入文件目錄(默認為當前目錄的input目錄),outPath為輸出答案文件目錄(默認為當前目錄的output目錄)
ioCode 'java Main' #注意java Main是一個完整的命令,中間帶有空格,需要用引號引起來
示例:
以上就是這個小項目的內容,通過ioCode
可以批處理測試多個輸入輸出用例,并能清晰的看到哪些輸入文件正確輸出方便DeBug。
后面我打算繼續優化一下,主要包括以下內容
- 快速構造輸入,輸出數據。
- 對于不正確的輸出(與給定的輸出文件不匹配),能清晰地指出出第一個不同的地方。
- 顯示批處理執行耗時
更多優化點或不足的地方,期待指教。