powershell批处理io校验功能
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">powershell批处理——io校验</a></li><li><a href="#_label1">使用</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">测试.exe文件</a></li><li><a href="#_lab2_1_1">测试可执行.class文件</a></li></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>powershell批处理——io校验</h2><p>在刷题时,时常回想,OJ平台是如何校验竞赛队员提交的代码的,OJ平台并不看代码,而是使用“黑盒测试”,用测试数据来验证。对于每题,都事先设定了很多组输入数据(datain)和输出数据(dataout),OJ主要是看输入datain,看产生的输出是否与dataout一致。</p>
<p>如果需要一次性知道自己的所有测试输入数据是否能得到正确输出,一个一个测试就太慢了,批处理操作就能很好解决这个问题。刚好在学习powershell,本篇文章主要介绍一下这个ioCode项目。</p>
<p>项目目录结构</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202505/2025051209222122.png" /></p>
<ul><li>input目录:存放输入数据文件,以<code>.in</code>后缀结尾</li><li>output目录:存放输出数据文件,以<code>.out</code>后缀结尾,每个输出的文件名与对应的输入的文件名相同</li><li>start.ps1:编写的脚本文件</li></ul>
<p>start.ps1源代码:</p>
<div class="jb51code"><pre class="brush:ps;">function ioCheck{
param(
$content, #程序输出内容
$answer #输出的答案内容
)
$cnt = $answer.length
if($content.length -ne $cnt){
return -1#行数不一致返回-1
}
for($i=0;$i -lt $cnt;$i++){
if($answer[$i] -ne $content[$i]){
return $i+1#内容不一致,返回第一个不同的行数
}
}
return 0#相同返回0
}
function ioCode{
param(
$command,
$inPath = './input',
$outPath = './output'
)
$allStartTime = Get-Date
$acList = New-Object System.Collections.ArrayList#创建正确输出的文件名集合
$errList = New-Object System.Collections.ArrayList#创建错误输出的文件名集合
$inFiles = Get-ChildItem -Path $inPath -Filter *.in#获取输入文件集
$len = $inFiles.length
$cnt = 0
foreach($file in $inFiles){
try {
$startTime = Get-Date
$fullOut = (cmd.exe /c "$command < $($file.fullName)") -split "\r\n|\r|\n"#获取程序实际输出内容
$endTime = Get-Date
$duration = $endTime - $startTime#获取程序执行时间
$answerPath = Join-Path -Path $outPath -ChildPath ($file.BaseName + '.out')
$answer = Get-Content -Path $answerPath -ReadCount 0#获取该输入文件的对应输出文件的内容,-ReadCount 0指定返回一个字符串数组
$res = ioCheck $fullOut $answer
if($res -eq 0){
$item = @{
fileName = $file.Name
exeTime = $duration
}
$acList.add($item) | Out-Null#Out-Null表示丢弃输出
$cnt++
}else{
$item = @{
fileName = $file.Name
errLine = $res
}
$errList.add($item) | Out-Null
}
}
catch {
Write-Host "处理文件 $($file.Name) 时出现错误: $_"
}
}
$allEndTime = Get-Date
$allExeTime = $allEndTime-$allStartTime
Write-Host "正确输出 $cnt/$len:,总耗时:$($allExeTime.Milliseconds)ms"
foreach($item in $acList){
Write-Host "Y: $($item.fileName) 耗时:$($item.exeTime.Milliseconds)ms"
}
foreach($item in $errList){
Write-Host "N: $($item.fileName) errCode:$($item.errLine)"
}
return @{
CorrectCount = $cnt
TotalCount = $len
acList = $acList
errList = $errList
}
}</pre></div>
<p>首先测试输入两个数,看能否成功输出两数之和</p>
<p>在input目录中创建三个文件分别为<code>001.in</code>,<code>002.in</code>,<code>003.in</code></p>
<p>内容分别为</p>
<blockquote><p>3 4</p></blockquote>
<blockquote><p>35749 47985</p></blockquote>
<blockquote><p>544 6755</p></blockquote>
<p>对应的在output目录创建三个同名的<code>.out</code>文件,分别为<code>001.out</code>,<code>002.out</code>,<code>003.out</code></p>
<p>内容就是对应<code>.in</code>文件中两个输入数据的相加的结果。</p>
<p class="maodian"><a name="_label1"></a></p><h2>使用</h2>
<p>编写好测试用例,就是可以测试我们写好的代码了,这里不仅可以测试C/C++生成的<code>.exe</code>可执行文件,还可以测试java生成的<code>.class</code>可执行字节码文件(前提是电脑具备java环境)。</p>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>测试.exe文件</h3>
<p>在当前目录下准备一个<code>test.cpp</code>文件,代码如下:</p>
<div class="jb51code"><pre class="brush:csharp;">#include<iostream>
using namespace std;
int main()
{
int a, b;
cin >> a >> b;
cout<< 7;
return 0;
}</pre></div>
<p>将其编译为可执行文件<code>test.exe</code>:</p>
<div class="jb51code"><pre class="brush:ps;">g++ -o test.exe test.cpp
</pre></div>
<p>在当前目录下打开powershell控制台</p>
<p>通过点加载start.ps1文件</p>
<div class="jb51code"><pre class="brush:ps;">. './start.ps1'</pre></div>
<p>输入命令<code>ioCode {command} {inPath} {outPath}</code>,command为可执行命令,inPath为输入文件目录(默认为当前目录的input目录),outPath为输出答案文件目录(默认为当前目录的output目录)</p>
<div class="jb51code"><pre class="brush:bash;">ioCode test.exe
</pre></div>
<p>示例:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202505/2025051209222123.png" /></p>
<p>控制台输出显示我们的三个测试用例都通过了。</p>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>测试可执行.class文件</h3>
<p>在当前目录下准备一个<code>Main.java</code>文件,代码如下:</p>
<div class="jb51code"><pre class="brush: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);
}
}</pre></div>
<p>将其编译为可执行文件<code>Main.class</code>:</p>
<div class="jb51code"><pre class="brush:plain;">javac Main.java</pre></div>
<p>在当前目录下打开powershell控制台</p>
<p>通过点加载start.ps1文件</p>
<div class="jb51code"><pre class="brush:bash;">. './start.ps1'</pre></div>
<p>输入命令<code>ioCode {command} {inPath} {outPath}</code>,command为可执行命令,inPath为输入文件目录(默认为当前目录的input目录),outPath为输出答案文件目录(默认为当前目录的output目录)</p>
<div class="jb51code"><pre class="brush:bash;">ioCode 'java Main'#注意java Main是一个完整的命令,中间带有空格,需要用引号引起来</pre></div>
<p>示例:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202505/2025051209222124.png" /></p>
<p>测试可执行<code>.py</code>文件</p>
<p>在当前目录下准备一个<code>Main.java</code>文件,代码如下:</p>
<div class="jb51code"><pre class="brush:java;">a,b=map(int,input().split())
print(a+b)</pre></div>
<p>在当前目录下打开powershell控制台</p>
<p>通过点加载start.ps1文件</p>
<div class="jb51code"><pre class="brush:ps;">. './start.ps1'</pre></div>
<p>输入命令<code>ioCode {command} {inPath} {outPath}</code>,command为可执行命令,inPath为输入文件目录(默认为当前目录的input目录),outPath为输出答案文件目录(默认为当前目录的output目录)</p>
<div class="jb51code"><pre class="brush:py;">ioCode 'python test.py'#注意python test.py是一个完整的命令,中间带有空格,需要用引号引起来</pre></div>
<p>示例:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202505/2025051209222125.png" /></p>
<p>以上就是这个小项目的内容,通过<code>ioCode</code>可以批处理测试多个输入输出用例,并能清晰的看到哪些输入文件正确输出方便DeBug。</p>
頁:
[1]