一个简单的本地判题脚本

源码

Windows下

鉴于本人是追求实用(能跑就行),同理猜测读者也不关心这到底怎么实现,或者说不着急关心,于是直接附上 Windows 环境下的 Python 源码,开盒即用,只需要你有一点 Python 的基础,会装 subprocess 和 tqdm 库就行,然后在脚本所在的目录新建一个名为标准代码的文件夹,并在里面放入一个std.c作为测试输出的基准参照,同理新建一个测试代码的文件夹并放入test.c作为被测试的代码,同时安装好gcc,运行脚本,就能大功告成了。

import subprocess
import random
import sys
from tqdm import tqdm

def random_int_list(start, stop, length):
    start, stop = (int(start), int(stop)) if start <= stop else (
        int(stop), int(start))
    length = int(abs(length)) if length else 0
    random_list = []
    for i in range(length):
        random_list.append(random.randint(start, stop))
    return random_list

def iotest(filename, path, data):
    obj = subprocess.Popen([filename], stdin=subprocess.PIPE,
                           stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=path, encoding="utf-8",shell=True)
    obj.stdin.write(data)
    out_info, out_error = obj.communicate()  # 简单写法,out_info:标准输出
    # print(out_info,out_error)
    return out_info

if __name__ == '__main__':
    stdpath = "%s\\标准代码\\" % sys.path[0]      # 标准代码所在路径
    testpath = "%s\\测试代码\\" % sys.path[0]     # 测试代码所有路径
    #编译标准及测试代码
    result = subprocess.check_output("gcc -std=c99 -o std std.c", shell=True, cwd=stdpath)
    result = subprocess.check_output("gcc -std=c99 -o test test.c", shell=True, cwd=testpath)

    f = open('%s\测试结果.txt' % sys.path[0], 'w+', encoding='utf-8', newline="")
    print('随机测试中...')
    pas=0       # 通过次数
    freq=10    # 测试次数
    for index in tqdm(range(freq)):
        # 生成测试数据
        rtest = random_int_list(0, 99, 10)
        s = ''
        for i in rtest:
            s = "%s%s " % (s, i)
        s = "%s\n" % s
        # 进行测试
        output = iotest(".\\test.exe", testpath, s)
        stdoutput = iotest(".\\std.exe", stdpath, s)
        f.write("随机测试 - r,%d数据点\n"%index)
        f.write("标准输入\n%s" % s)
        f.write("实际输出\n%s\n" % output)
        f.write("期望输出\n%s\n\n" % stdoutput)
        if output==stdoutput:
            f.write('通过「随机测试 - r,%d数据点」测试点\n\n'%index)
            pas=pas+1
        else:
            f.write('未通过「随机测试 - r,%d数据点」测试点\n\n'%index)
    f.close()
    print('随机测试 %d/%d'%(pas,freq))
    print('测试完成')

同时附上样例标准代码:

#include <stdio.h>
#define N 10
void inputarray(int *arr);
void handlearray(int *arr);
void outputarray(int *arr);
void swap(int *p,int *q);
int main()
{
    int array[N]= {0};
    inputarray(array);
    handlearray(array);
    outputarray(array);
    return 0;
}
void swap(int *p,int *q)
{
    int temp=*p;
    *p=*q;
    *q=temp;
}
void handlearray(int *arr)
{
    int *p=arr;
    int max_index=0;
    int min_index=0;
    int max=arr[0];
    int min=arr[0];
    for(int i=1;i<N;i++)
    {
        if(*(p+i)>max)
        {
            max=*(p+i);
            max_index=i;
        }
        if(*(p+i)<min)
        {
            min=*(p+i);
            min_index=i;
        }
    }
    swap((p+max_index),(p+9));
    swap((p+min_index),(p+0));
}
void inputarray(int *arr)
{
    int *p=arr;
    for(int i=0; i<N; i++)
    {
        scanf("%d",(p+i));
    }
}
void outputarray(int *arr)
{
    int *p=arr;
    for(int i=0; i<N; i++)
    {
        printf("%d ",*(p+i));
    }
}

以及样例测试代码:

#include <stdio.h>
int main()
{
    void inv(int *x, int n);
    int i, a[10];
    for (i = 0; i < 10; i++)
        scanf("%d", &a[i]);
    //printf("\n");
    inv(a, 10);
    //printf("The array has been inverted:\n");
    for (i = 0; i < 10; i++)
        printf("%d ", a[i]);
    //printf("\n");
    return 0;
}

void inv(int *x, int n)
{
    int *i, max, min, p, q, *c, *d;
    max = *x;
    min = *(x + 1);
    c = x + 0;
    d = x + 1;
    for (i = x; i < x + 10; i++)
        if (*i > max)
        {
            max = *i;
            c = i;
        }
    for (i = x; i < x + 10; i++)
        if (*i < min)
        {
            min = *i;
            d = i;
        }
    p = *x;
    *x = *d;
    *d = p;
    q = *(x + 9);
    *(x + 9) = *c;
    *c = q;
}

Linux 下的 Python 源码

一个现象就是, Linux 下进行测试的速度明显比 Windows 下快,我测试的时候两者甚至相差 100 余倍,其中原因可留给读者细究。

import subprocess
import random
import sys
from tqdm import tqdm

def random_int_list(start, stop, length):
    start, stop = (int(start), int(stop)) if start <= stop else (
        int(stop), int(start))
    length = int(abs(length)) if length else 0
    random_list = []
    for i in range(length):
        random_list.append(random.randint(start, stop))
    return random_list

def iotest(filename, path, data):
    obj = subprocess.Popen([filename], stdin=subprocess.PIPE,
                           stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=path, encoding="utf-8")
    obj.stdin.write(data)
    out_info, out_error = obj.communicate()  # 简单写法,out_info:标准输出
    # print(out_info,out_error)
    return out_info

if __name__ == '__main__':
    stdpath = "%s/标准代码/" % sys.path[0]      # 标准代码所在路径
    testpath = "%s/测试代码/" % sys.path[0]     # 测试代码所有路径
    #编译标准及测试代码
    result = subprocess.check_output("gcc -std=c99 -o std std.c", shell=True, cwd=stdpath)
    result = subprocess.check_output("gcc -std=c99 -o test test.c", shell=True, cwd=testpath)

    f = open('%s/测试结果.txt' % sys.path[0], 'w+', encoding='utf-8', newline="")
    print('随机测试中...')
    pas=0       # 通过次数
    freq=100    # 测试次数
    for index in tqdm(range(freq)):
        # 生成测试数据
        rtest = random_int_list(0, 99, 10)
        s = ''
        for i in rtest:
            s = "%s%s " % (s, i)
        s = "%s\n" % s
        # 进行测试
        output = iotest("./test", testpath, s)
        stdoutput = iotest("./std", stdpath, s)
        f.write("随机测试 - r,%d数据点\n"%index)
        f.write("标准输入\n%s" % s)
        f.write("实际输出\n%s\n" % output)
        f.write("期望输出\n%s\n\n" % stdoutput)
        if output==stdoutput:
            f.write('通过「随机测试 - r,%d数据点」测试点\n\n'%index)
            pas=pas+1
        else:
            f.write('未通过「随机测试 - r,%d数据点」测试点\n\n'%index)
    f.close()
    print('随机测试 %d/%d'%(pas,freq))
    print('测试完成')
文章作者weyung
文章链接https://weyung.cc/posts/411a7b28/
许可协议CC BY-NC-SA 4.0
上一篇

一个简单的作业提交平台

下一篇

VSCode 写 C