对拍(windows)

 

一、课程目标

  1. 准备工作
  2. 编译运行与重定向
  3. 结果比对
  4. 数据生成器
  5. 对拍脚本
  6. 计时模式

二、目标详解

1、准备工作

1.1 编译工具

首先需要安装gcc/g++的编译工具MinGW32,如果已经安装了devcpp的话,是自带MinGW32的。

1.2 编辑器

需要一个写代码的编辑器,一般用devcpp就好,当然想用别的例如记事本也可以。

1.3 路径配置

对拍要在命令行里面调用gcc/g++命令,需要先配置好path路径。假设devcpp安装在E:\Dev-cpp5.4.0\Dev-Cpp,则g++的目录为E:\Dev-cpp5.4.0\Dev-Cpp\MinGW32\bin,需要将之配置进path。

配置

  • 打开控制面板,到系统 -> 高级系统设置,弹出“系统属性页”。
  • 点“环境变量”按钮弹出“环境变量”窗口
  • 在系统变量里面找到Path,点“编辑”按钮,弹出编辑窗口
  • 在“变量值”的最后面加上”; E:\Dev-cpp5.4.0\Dev-Cpp\MinGW32\bin”。
  • 一路确定。
  • 然后打开终端验证(如果已经开着要先关掉再打开)

验证:windows的运行里打cmd回车,弹出终端,输入g++回车,显示:

  • g++ 不是内部或外部命令….,表示没有配置成功
  • g++: fatal error: no input files,表示已经配置成功

1.4 cd到代码目录

终端打开的时候,默认工作目录在C:\Users\Administrator(或其它用户名目录)。对拍的时候,终端要cd到代码目录(如E:\code)。

e:  //回车切换到E盘
cd  code //回车,进入E: \code目录

验证:用dir命令就可以查看到当前目录,例如:

2、编译运行与重定向

2.1 编译运行

例如代码为hello.cpp(已经编写好代码,读入一行字符串,然后输出),则在windows的终端窗口,执行以下命令:

g++ hello.cpp -o hello.exe //编译
hello.exe //运行

2.2 重定向读

程序的输入:可以用 < 命令重定向到一个文件读取

     hello.exe < 1.in

2.3 重定向写

程序的输出:可以用 > 命令重定向写入到一个文件里

     hello.exe > 1.out

in和out文件也可以用编辑器来打开(查看、修改),与代码文件同一个目录。

3、结果比对

现在对于某道题,可以手工生成in数据和ans文件,然后调用重定向生成out文件,用
fc命令比对ans文件和out了。

fc命令:用来比对两个文件内容是否一致,如fc 1.out 1.ans。

如果文件内容一致,显示如下:

如果文件内容不一致,显示如下:

4、数据生成器

数据生成器是根据题目要求编写的代码文件,用来生成符合题目要求的输入数据,保存到in文件里。例如:

  g++ data.cpp -o data.exe
  data.exe > 1.in

主要是使用rand()函数生成各种随机数据,因此要包含ctdlib和ctime两个头文件。具体例子如下(n个数字的序列):

#include <iosteam>
#include <cstdlib>
#inlcude <ctime>

int main() {
  srand(ctime(0)); //用时间做随机种子
  int n = rand()%10000+1; //1..10000的随机长度
  cout<<n<<endl;
  for(int i=1; i<=n; i++) {
    int x = rand()%1000+1; //1..1000的随机元素
    cout<<x<<" ";
  }
  return 0;
}

5、对拍脚本

用两份代码,其中一份是朴素代码(正确的),另一份是其它方法实现的(可能是优化代码),循环多次用数据生成器生成随机数据,然后两份代码分别输出结果进行比对,如果完全一致说明对拍通过,否则退出。此时出问题的数据被保存,可以用来调试错误。

@echo off
:loop
data.exe > duipai.in
simple.exe < duipai.in > simple.out 
good.exe < duipai.in > good.out
fc /A simple.out good.out
if %errorlevel%==0 goto loop
echo WA
pause

也可以不用批处理,直接用c++编写对拍脚本,如下:

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std; 
int main(){
    for(int i=1;i<=10000;i++){
        system("data.exe > duipai.in");
        double st=clock();
        system("simple.exe < duipai.in > simple.out");
        double ed=clock();
        system("good.exe < duipai.in > good.out ");
        if(system("fc /A simple.out good.out")){
            cout<<"WA"<<endl;
            return 0; 
        }
        else{
            printf("Ac,测试点 #%d, 用时 %.0lfms\n",i,ed-st);
        }
    }
    return 0;
}

三、扩展

1、超过多少次退出

@echo off
set /A cnt = 0
:loop
set /A cnt = %cnt% + 1
if %cnt% GTR 10 (
  echo 超过10次,退出
  goto end
)
data.exe > duipai.in
simple.exe < duipai.in > simple.out 
good.exe < duipai.in > good.out
fc /A simple.out good.out
if %errorlevel%==0 goto loop
echo WA
goto end

:end
pause

2、随机数太慢

srand(time(0))一秒钟产生一个随机数,对拍会比较慢。

在windows脚本里可以用%random%产生随机数,如下修改:

data.exe %random% > duipai.in

同时在data.cpp里也传入参数作为随机数种子:

int main(int argc, char *argv[]) {
  if(argc<=1)
    srand(time(0));
  else {
    int seed;
    stringstream ss;
    ss.clear();
    ss<<argv[1];
    ss>>seed;
    srand(seed);
  }
  ......
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值