在刷 OJ 题目或者进行编程考试或比赛时,经常需要对编写好的程序进行测试,即运行编写好的程序,输入样例输入或者自己编写的输入数据,查看程序输出结果和样例输出或者正确输出是否一致。这种方法有很多弊端,当有多组输入数据或程序运行结果多次错误时,需要多次复制粘贴输入数据,这个过程非常繁琐而且浪费时间;用肉眼检查程序输出和正确输出是否一致很容易出错,尤其是当输出数据非常多时。所以,我在这篇博客里介绍一下通过输入输出重定向和 windows 批处理文件比较程序输出和正确输出的方法。由于 VSCode 能够编写任意格式的文件且自带终端,本博客基于 VSCode 编写代码。如果你没有安装 VSCode,可以参考挑把趁手的兵器——VSCode 配置 C/C++学习环境(小白向)安装 VSCode 并配置 C/C++环境。当然使用你常用的编辑器/IDE,并利用 powershell 或 DOS 窗口运行程序 windows 脚本也是可以的。

概念介绍

  1. 输入输出重定向:最常见的输入输出是标准输入输出,即读键盘输入、写屏幕。但当我们希望在文件中准备好输入数据,将输出或错误信息输入到另一个文件中时,就需要使用重定向。本博客介绍的方法就是将输入数据保存在一个 input.txt 文件中,运行程序时,让程序从 input.txt 文件读取数据,将程序输出数据保存在另一个 output.txt 文件中,从而就避免了多次复制粘贴输入数据的繁琐步骤。
  2. windows 批处理文件:批处理,顾名思义就是进行批量的处理。批处理文件是扩展名为.bat 或.cmd 的文本文件,包含一条或多条命令,由 DOS 或 Windows 系统内嵌的命令解释器来解释运行。本博客提出的方法使用的是 windows 批处理文件中的比较文件差异的 fc 命令。

比较程序输出和样例输出

算法题目通常都会给出多组样例输入和样例输出。用肉眼检查程序输出和样例输出是否一致很容易出错,我们可以利用 windows 脚本运行我们编写的程序并比较程序输出和样例输出是否一致。

我们可以以一个读取两个 int 数据,输出这两个数据之和的简单程序作为例子,这个程序的 C++程序代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main() {
  4. int a, b;
  5. cin >> a >> b;
  6. cout << a + b << "\n";
  7. return 0;
  8. }

不妨将程序其命名为 test.cpp,我们不妨在 VSCode 中新建这样的 cpp 文件,如下图所示:

新建三个 txt 文件 input.txt、output.txt、correct.txt,它们的作用分别为:

  1. input.txt:用于存放输入数据
  2. correct.txt:用于存放正确的输出数据
  3. output.txt:用于存放程序输出数据,这个文件不需要新建和删除,运行 windows 批处理文件后会自动生成

我们不妨在 input.txt 文件中写入1 2作为输入数据,在 correct.txt 写入3作为正确的输出数据,如下所示:

新建一个 windows 脚本,不妨命名为run.bat,里面写入代码:

  1. g++ test.cpp -std=c++17 -o test %编译test.cpp,生成test.exe%
  2. test < input.txt >output.txt %执行test.exe文件,从input.txt文件读取输入,将程序结果输出到output.txt文件%
  3. fc output.txt correct.txt %比较output.txt文件和correct.txt文件是否相同%

如果你安装了Code Runner插件,可以直接右键->run code执行。如果没有安装,那么启动终端,并输入命令.\run.bat,回车即可。

如果有多组输入,多组输出,怎么办呢?我们可以修改一下程序 test.cpp:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main() {
  4. int a, b;
  5. int t = 1; //数据组数
  6. cin >> t;
  7. while (t--) {
  8. cin >> a >> b;
  9. cout << a + b << "\n";
  10. }
  11. return 0;
  12. }

增加一组输入-1 -2,增加一组输出-3,我们可以这样填写 input.txt 文件和 correct.txt 文件:

然后运行run.bat脚本即可比较多组数据的输出。

如果题目每个测试点只有一组数据,在提交时只需要注释掉第 6 行代码cin >> t;即可。

程序对拍

有时程序能够通过样例,但是提交之后评测系统总会报错,也就是说程序中有 bug,这时就需要通过程序对拍来找到一组使程序错误的数据。要完成程序对拍,我们需要 3 个 cpp 文件。

  1. 我们自己编写的有错误的程序,不妨命名为test.cpp
  2. 能够正确解题的程序,不妨命名为correct.cpp。如果是平时练习,我们通常可以在网上搜索到这个题目正确的解题代码;如果是比赛期间,我们只能编写一个暴力但正确的程序。
  3. 能够产生题目要求的输入数据的程序,不妨命名为data.cpp

我们还是以一个读取两个 int 数据,输出这两个数据之和的简单程序作为例子。假设它的输入数据是不超过\([-10^6,10^6]\)之间的两个整数,data.cpp可以这样写:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main() {
  4. uniform_int_distribution<int> u(-1e6, 1e6); //设置随机数的范围和分布
  5. default_random_engine e(time(0)); //设置随机数引擎
  6. cout << u(e) << " " << u(e) << "\n"; //输出随机数
  7. return 0;
  8. }

correct.cpp可以这样写:

  1. #include <stdio.h>
  2. int main() {
  3. int a, b;
  4. scanf("%d%d", &a, &b);
  5. printf("%d", a + b);
  6. }

假设test.cpp为:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main() {
  4. int a, b;
  5. cin >> a >> b;
  6. cout << a + b << "\n";
  7. return 0;
  8. }

编写一个compare.bat脚本:

  1. g++ data.cpp -std=c++17 -o data
  2. g++ test.cpp -std=c++17 -o test
  3. g++ correct.cpp -std=c++17 -o correct
  4. @echo off
  5. :loop
  6. data > input.txt
  7. test < input.txt > output.txt
  8. correct < input.txt > correct.txt
  9. fc output.txt correct.txt
  10. if not errorlevel 1 goto loop
  11. pause
  12. goto loop

compare.bat脚本将data.cpp的输出写入到input.txt文件,将correct.cpp的输出写入到correct.txt文件,将test.cpp的输出写入到output.txt文件。这个脚本是一个死循环,它不会不断产生新的随机输入,并比较test.cppcorrect.cpp的输出,直到两个输出不一致才会停下来。显然test.cpp是正确的程序,因此脚本将无限执行下去:

如果我们将test.cpp修改成这样:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main() {
  4. int a, b;
  5. cin >> a >> b;
  6. cout << a << "\n";
  7. return 0;
  8. }

显然,这是一个错误的程序,执行compare.bat脚本会得到这样的结果:

它会在一组让test.cpp产生错误的数据处停止。这样一个错误数据可以方便我们后续的 debug。

注意,由于产生输入数据的程序只是一个简单的随机数程序,并不能保证一定能得到使程序产生错误的数据,所以数据对拍只能作为帮助我们 debug 的一种方法,但并不是总能奏效。

用VSCode终端实现重定向比较程序输出和正确输出的更多相关文章

  1. python 利用subprocess调用cmd命令程序,并正确输出控制台的输出中文

    平台Python3.7 1.利用控制台运行程序后在控制台会输出中文提示,但是用python调用subprocess.run函数后返回的输出是乱码,于是,解决方法是用subprocess.check_o ...

  2. Linux nohup 关闭终端的时候,程序依然能在后台运行( linux重定向及nohup不输出的方法)

    先说一下linux重定向: 0.1和2分别表示标准输入.标准输出和标准错误信息输出,可以用来指定需要重定向的标准输入或输出.在一般使用时,默认的是标准输出,既1.当我们需要特殊用途时,可以使用其他标号 ...

  3. WIN32程序挂钩SetLastError,输出错误描述到控制台

    WIN32程序挂钩SetLastError,输出错误描述到控制台 作者:徐灵甫 一.窗口模式应用程序(GUI)启用控制台的方法为: 步骤 方法 1 启动/关闭控制台 AllocConsole()Fre ...

  4. 解决VSCode终端中文乱码问题

    VSCode终端其实调用的是cmd.exe,所以当这里出现中文乱码的时候要解决的是cmd的编码设置问题. 可以通过chcp命令查看cmd的编码设置,GBK2312的代码页编号是936,然后改成utf- ...

  5. Linux程序员福利 - 追女友神奇(Linux终端运行炫酷程序)

    概述 作为IT人员,给同事的感觉呆板,不会会浪漫,不懂情趣.其实不然,我们可以用我们的技能创造出IT人员独有的浪漫.girlLove脚本就可以实现IT人员的浪漫.girlLove本质上是一个简易的问答 ...

  6. Python01 VSCode开发环境和入门程序

    1.Python的下载和安装 最新版本python3.7.3 https://www.python.org/downloads/release/python-373/ web-based: 在线安装包 ...

  7. C# 基础控制台程序的创建,输出,输入,定义变量,变量赋值,值覆盖,值拼接,值打印

    基础学习内容有 Console.WriteLine("要输出的内容");//往外输出内容的 Console.ReadLine(); //等待用户输入,按回车键结束,防止程序闪退 控 ...

  8. 重定向、feed输出:控制台输出的内容存放到文件

    重定向.feed输出:控制台输出的内容存放到文件 1.重定向 os.system('wget -r -p -np -k http://www.baidu.com/ -o wget.log' ) 2.f ...

  9. 《手把手教你学C语言》学习笔记(7)---程序的输入与输出

    程序设计中,为了观察程序的运行状态和结构,需要输出指定的内容:为了让程序能够更加灵活,可以根据需求输入内容,让计算机处理和运行:所以程序的输入输出就显的尤为重要.主要包括printf和scanf函数. ...

随机推荐

  1. 获取Eureka服务列表的各种场景

    一.第一类服务注册到eureka中,获取服务列表 1.基于SpringClientFactory获取服务列表 /** * <一句话功能简述> * <功能详细描述> * * @a ...

  2. 通过LinkedHashMap实现LRU算法

    一.基于LinkedHashMap源码分析 方法调用流程(这里只是以put方法位例) put() -> putVal() -> afterNodeInsertion() -> rem ...

  3. 基于pyqt5和openpyxl和Pyinstaller的青年大学习检查未学习人数的脚本

    前几天接到团支书的一个需求,因为学校给的名单是青年大学习已学习的名单,然而要知道未学习的名单只能从所有团员中再排查一次,过程相当麻烦.团支书跟我抱怨后,刚好我也学过一些操作办公软件的基础.打包pyth ...

  4. linux操作系统优化系列-RAID不同阵列模式的选择

    背景 笔者所在的某通信运营商某大数据项目由于应用面临瓶颈需要扩充服务器设备,当初上这个项目的时候,服务器上线前的工作(配置raid,安装操作系统,Infiniband网络调试,系统漏洞安全加固)都是我 ...

  5. 桌面支持qt版本是多少检查

    桌面支持qt版本是多少 # rpm -qa |grep qt |grep 3 |sortqt3-3.3.8b-60.nd7.2.x86_64qt-4.8.6-13.nd7.3.x86_64qt5-qt ...

  6. Mysql_二进制方式安装详解

    mysql 安装 1.安装方式 1.二进制安装 2.源码包安装 3.rpm包安装 1.二进制安装 1)上传或者下载包 [root@db01 ~]# rz #或者 [root@web01 ~]# wge ...

  7. IT菜鸟之OSI七层模型

    OSI七层模型从下到上分别是: 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 第一层物理层: 物理层是传输媒介(网线.无线.光纤) 在线路中起到的作用:是将0/1转换成电信号或光信号 物 ...

  8. Windows10查看电脑的USB接口是2.0还是3.0

    Windows10查看电脑的USB接口是2.0还是3.0原创小晓酱手记 最后发布于2019-08-22 16:09:48 阅读数 3662 收藏展开 同事要拷贝资料给我,问我电脑的USB接口是2.0还 ...

  9. lua type 获取 类型

    lua中的类型作一小记 print(type("Hello world")) --> string print(type(10.4*3)) --> number pri ...

  10. Linux(CentOS7)下rpm安装MySQL8.0.16

    记录一下自己在 CentOS7 下 rpm 安装 MySQL8.0.16 的过程. 一.准备工作 1. 下载MySQL所需要的安装包 从 MySQL官网 下载,上传至 CentOS 系统 /usr/l ...