火龙信奥
  • 分享
  • 课程
  • 在线题库
  • CSES
    • GESP
    • CSP
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 知识课堂
  • 在线比赛
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

复赛 | windows下写对拍

作者: 作者的头像   huolong , 时间:2026-09-25 22:11:27 , 所有人可见, 阅读  48

在算法竞赛(如 CSP、NOIP、蓝桥杯等)中,我们经常遇到这样的情况:样例过了,交上去却得了零分(WA)。肉眼去几百行的代码里找 Bug 犹如大海捞针。

这时候,“对拍”(Pairing Test)就成了程序员的终极核武器。

本文将带你在 Windows 环境下,使用 C++ 编写一个自动化对拍程序,让电脑帮你成千上万次地自我纠错。


一、 什么是“对拍”?

对拍的核心思想非常简单,它需要 4 个核心部分: 1. 数据生成器(gen.cpp):随机生成合法的输入数据。 2. 正解/暴力程序(std.cpp):逻辑绝对正确、时间复杂度可能较慢的暴力程序(或者你确信正确的代码)。 3. 待测程序(my.cpp):你自己写的、可能存在 Bug 的高效算法程序。 4. 对拍控制脚本(run.cpp 或 .bat):指挥它们循环运行、对比结果。

对拍的运行流程:

[数据生成器 gen] ---> 生成输入数据 (data.in)
                          |
       +------------------+------------------+
       |                                     |
       v                                     v
[待测程序 my]                         [暴力程序 std]
       |                                     |
       v                                     v
输出结果 (my.out)                     正确答案 (std.ans)
       |                                     |
       +------------------+------------------+
                          |
                          v
               [对比工具:一样吗?]
               /                \
             (是)               (否)
             /                    \
        进入下一轮              【抓获 Bug!停下!保留现场】

二、 实战演练:四步打造对拍系统

假设我们现在有一道题目,要求计算 两数之和。

第一步:准备好你的待测程序(my.cpp)

这是你写的代码(假设里面可能藏着 Bug):

#include <iostream>
using namespace std;

int main() {
    int a, b;
    // 注意:对拍时程序直接用标准输入输出即可,不需要写 freopen!
    if (cin >> a >> b) {
        cout << a + b << endl;
    }
    return 0;
}

第二步:写一个暴力正确程序(std.cpp)

这个程序不需要考虑时间复杂度多高,只要能用最稳妥、最笨的方法算出正确答案就行。

#include <iostream>
using namespace std;

int main() {
    int a, b;
    while (cin >> a >> b) {
        cout << a + b << endl;
    }
    return 0;
}

第三步:写一个随机数据生成器(gen.cpp)

利用 C++ 的 <random> 或 <ctime> 随机生成符合题目数据范围的输入。

#include <bits/stdc++.h>
using namespace std;

int main() {
    // 以时间为种子,保证每次生成的随机数不同
    srand(time(0)); 

    // 随机生成两个 -1000 到 1000 之间的数字作为 a 和 b
    int a = rand() % 2000 - 1000;
    int b = rand() % 2000 - 1000;

    cout << a << " " << b << endl;
    return 0;
}

第四步:编写 C++ 版对拍控制器(run.cpp)

很多教程喜欢用 Windows 的 .bat 批处理文件写对拍,但用 C++ 编写对拍器 跨平台、更好控制、更符合程序员习惯。

新建一个 run.cpp 文件:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int k = 1; // 记录对拍到第几轮了
    while (true) {
        // 1. 编译各个程序(确保你已经把它们编译成了 .exe)
        // 如果你用 Dev-C++ 或 VS Code 已经编译好了,这行可以注释掉

        // 2. 生成随机数据到 data.in
        system("gen.exe > data.in");

        // 3. 分别运行你的程序和暴力程序,重定向输入输出
        system("my.exe < data.in > my.out");
        system("std.exe < data.in > std.ans");

        // 4. 对比两个程序的输出结果 (fc 是 Windows 自带的文件比较命令)
        // /W 会忽略空格和换行符差异
        if (system("fc my.out std.ans > nul") != 0) {
            // 如果返回值不为 0,说明结果不一致!发生 WA!
            cout << "第 " << k << " 组数据:\n";
            cout << "发现不同!程序挂了!\n";
            break; // 停止对拍,保留现场
        } else {
            // 结果一致,输出 AC
            cout << "第 " << k << " 组数据:AC\n";
        }
        k++;
    }
    return 0;
}

三、 如何在 Windows 下运行它?

  1. 编译所有文件: 将上面的 my.cpp、std.cpp、gen.cpp、run.cpp 分别编译,生成对应的可执行文件:
  2. my.exe
  3. std.exe
  4. gen.exe
  5. run.exe (确保它们四个在同一个文件夹下。)

  6. 双击运行对拍: 直接双击运行 run.exe(或者在该目录下打开命令行窗口运行 run.exe)。

  7. 查看结果:

  8. 如果程序一直刷 第 x 组数据:AC,说明你的 my.cpp 在随机数据下表现完美。
  9. 如果某一轮出现了 发现不同!程序挂了!,循环会停下来。此时文件夹里会多出三个文件:data.in(出错的数据)、my.out(你的输出)、std.ans(正确输出)。
  10. 你可以直接打开 data.in,把里面的恶心数据复制到本地代码里进行断点调试(Debug),轻松揪出 Bug。

四、 避坑指南

  1. 程序中千万别写 freopen: 在写 my.cpp 和 std.cpp 时,绝对不能加文件输入输出,必须纯靠 cin/cout 或 scanf/printf,因为对拍器的 system("my.exe < data.in > my.out") 已经帮你接管了重定向。
  2. 随机数的范围要够大: 用 rand() 时注意 rand() 最大只能到 32767。如果题目数据范围到 $10^9$,需要写 (rand() << 15) | rand() 来拼接生成大随机数。
  3. 浮点数对拍注意精度: 如果题目输出是浮点数,Windows 的 fc 命令对微小误差很敏感,通常需要写一个专门的 cmp.cpp 来判断两浮点数之差是否小于 1e-7。

—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

关于火龙

  • 关于我们
  • 学员获奖
  • 预约试听
  • ACM课程
  • CSP课程
  • 学习指南

帮助中心

  • 用户协议
  • 打字练习 HOT
  • 在线画图
  • DevC++下载
  • CSP报名
  • GESP官网

推荐课程

  • C++零基础入门(可试看)
  • C++进阶提升
  • GESP考级辅导
  • GESP打卡
  • CSP-J/S打卡

公众号

火龙信奥公众号二维码

© 2017-2026 义乌市睿码科技有限公司版权所有 浙ICP备2021013995号

火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码