powershell批处理——io校验

powershell批处理——io校验

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

如果需要一次性知道自己的所有测试输入数据是否能得到正确输出,一个一个测试就太慢了,批处理操作就能很好解决这个问题。本篇文章主要介绍一下这个ioCode小项目,主要用于批处理校验输入输出,搭建本地的评测平台。

项目目录结构

在这里插入图片描述

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

start.ps1源代码:

function ioCheck{
    param(
        $content, #程序输出内容
        $answer #输出的答案内容
    )
    $cnt = $answer.length
    if($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 = $cnt
        TotalCount = $len
        CorrectFiles = $list
    }
}

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

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

内容分别为

001.in

3 4

002.in

35749 47985

003.in

544 6755

对应的在output目录创建三个同名的.out文件,分别为001.out002.out003.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控制台

  1. 通过点加载start.ps1文件
. './start.ps1'
  1. 输入命令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控制台

  1. 通过点加载start.ps1文件
. './start.ps1'
  1. 输入命令ioCode {command} {inPath} {outPath},command为可执行命令,inPath为输入文件目录(默认为当前目录的input目录),outPath为输出答案文件目录(默认为当前目录的output目录)
ioCode 'java Main'  #注意java Main是一个完整的命令,中间带有空格,需要用引号引起来

示例:

在这里插入图片描述

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

后面我打算继续优化一下,主要包括以下内容

  1. 快速构造输入,输出数据。
  2. 对于不正确的输出(与给定的输出文件不匹配),能清晰地指出出第一个不同的地方。
  3. 显示批处理执行耗时

更多优化点或不足的地方,期待指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值