powershell批处理io校验功能

Written by

in

文章目录
  • 在刷题时,时常回想,OJ平台是如何校验竞赛队员提交的代码的,OJ平台并不看代码,而是使用“黑盒测试”,用测试数据来验证。对于每题,都事先设定了很多组输入数据(datain)和输出数据(dataout),OJ主要是看输入datain,看产生的输出是否与dataout一致。 如果需要一次性知道自己的所有测试输入数据是否能得到正确输出,一个一个测试就太慢了,批处理操作就能很好解决这个问题。刚好在学习powershell,本篇文章主要介绍一下这个ioCode项目。 项目目录结构 input目录:存放输入数据文件,以.in后缀结尾 output目录:存放输出数据文件,以.out后缀结尾,每个输出的文件名与对应的输入的文件名相同 start.ps1:编写的脚本文件 start.ps1源代码: 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( [string]$command, [string]$inPath = ‘./input’, [string]$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 “rn|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 } } 首先测试输入两个数,看能否成功输出两数之和 在input目录中创建三个文件分别为001.in,002.in,003.in 内容分别为 3 4 35749 47985 544 6755 对应的在output目录创建三个同名的.out文件,分别为001.out,002.out,003.out 内容就是对应.in文件中两个输入数据的相加的结果。
  • 编写好测试用例,就是可以测试我们写好的代码了,这里不仅可以测试C/C++生成的.exe可执行文件,还可以测试java生成的.class可执行字节码文件(前提是电脑具备java环境)。
  • 目录
    • powershell批处理——io校验
    • 使用
      • 测试.exe文件
      • 测试可执行.class文件

    在刷题时,时常回想,OJ平台是如何校验竞赛队员提交的代码的,OJ平台并不看代码,而是使用“黑盒测试”,用测试数据来验证。对于每题,都事先设定了很多组输入数据(datain)和输出数据(dataout),OJ主要是看输入datain,看产生的输出是否与dataout一致。

    如果需要一次性知道自己的所有测试输入数据是否能得到正确输出,一个一个测试就太慢了,批处理操作就能很好解决这个问题。刚好在学习powershell,本篇文章主要介绍一下这个ioCode项目。

    项目目录结构

    • input目录:存放输入数据文件,以.in后缀结尾
    • output目录:存放输出数据文件,以.out后缀结尾,每个输出的文件名与对应的输入的文件名相同
    • start.ps1:编写的脚本文件

    start.ps1源代码:

    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(
    		[string]$command,
            [string]$inPath = './input',
            [string]$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 "rn|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
        }
    }

    首先测试输入两个数,看能否成功输出两数之和

    在input目录中创建三个文件分别为001.in,002.in,003.in

    内容分别为

    3 4

    35749 47985

    544 6755

    对应的在output目录创建三个同名的.out文件,分别为001.out002.out003.out

    内容就是对应.in文件中两个输入数据的相加的结果。

    编写好测试用例,就是可以测试我们写好的代码了,这里不仅可以测试C/C++生成的.exe可执行文件,还可以测试java生成的.class可执行字节码文件(前提是电脑具备java环境)。

    在当前目录下准备一个test.cpp文件,代码如下:

    #include<iostream>
    using namespace std;
    int main()
    {
        int a, b;
        cin >> a >> b;
        cout<< 7;
        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
    

    示例:

    控制台输出显示我们的三个测试用例都通过了。

    在当前目录下准备一个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

    在当前目录下打开powershell控制台

    通过点加载start.ps1文件

    . './start.ps1'

    输入命令ioCode {command} {inPath} {outPath},command为可执行命令,inPath为输入文件目录(默认为当前目录的input目录),outPath为输出答案文件目录(默认为当前目录的output目录)

    ioCode 'java Main'  #注意java Main是一个完整的命令,中间带有空格,需要用引号引起来

    示例:

    测试可执行.py文件

    在当前目录下准备一个Main.java文件,代码如下:

    a,b=map(int,input().split())
    print(a+b)

    在当前目录下打开powershell控制台

    通过点加载start.ps1文件

    . './start.ps1'

    输入命令ioCode {command} {inPath} {outPath},command为可执行命令,inPath为输入文件目录(默认为当前目录的input目录),outPath为输出答案文件目录(默认为当前目录的output目录)

    ioCode 'python test.py'  #注意python test.py是一个完整的命令,中间带有空格,需要用引号引起来

    示例:

    以上就是这个小项目的内容,通过ioCode可以批处理测试多个输入输出用例,并能清晰的看到哪些输入文件正确输出方便DeBug。

    到此这篇关于powershell批处理——io校验的文章就介绍到这了,更多相关powershell批处理内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • 用PowerShell代替批处理吧!

    站内搜索