Windows系统对拍程序,其中包含c++11用法,请使用c++11标准编译。此对拍程序会在发现错误时显示错误行号以及对应内容,方便比对。

此对拍程序自动使用g++对源代码进行编译。如果出现找不到g++的错误,请将g++所在目录添加至系统的环境变量列表中;

也可直接注释掉主函数前几行不用自动编译,并将编译好的pai_data.exe(生成数据)、pai_user.exe(用户程序)、pai_std.exe(标准解答程序)放至与本程序所在同目录下。

准备就绪后编译并运行本程序即可。

UPD 2019-04-10:添加了对标程的计时。

UPD 2019-04-18:修复当文件尾没有换行时会导致错误判断的问题。

  1. #include <cerrno>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <ctime>
  6.  
  7. // 设置区
  8. namespace Settings {
  9. const int MAX_LEN = ; // 发现错误时,显示错误行数据的最大长度
  10. const int CASE_CNT = ; // 对拍测试次数
  11. const int BUFFER_SIZE = << ; // 每行的缓冲区大小
  12. const char *const dataFile = "data.cpp"; // 随机生成数据的源代码文件名
  13. const char *const userFile = "user.cpp"; // 需要测试的源代码文件名
  14. const char *const stdFile = "std.cpp"; // 标准答案的源代码文件名
  15. const char *const dataExeName = "pai_data.exe";
  16. const char *const userExeName = "pai_user.exe";
  17. const char *const stdExeName = "pai_std.exe";
  18. const char *const dataOutputName = "pai_data.txt";
  19. const char *const userOutputName = "pai_user.txt";
  20. const char *const stdOutputName = "pai_std.txt";
  21. } // namespace Settings
  22.  
  23. using namespace Settings;
  24. using namespace std;
  25.  
  26. char cmd[BUFFER_SIZE], info[BUFFER_SIZE * ];
  27. char buf1[BUFFER_SIZE], buf2[BUFFER_SIZE];
  28.  
  29. template <typename... T>
  30. int run(const char *str, T... args) {
  31. sprintf(cmd, str, args...);
  32. return system(cmd);
  33. }
  34.  
  35. bool fileCompare(const char *stdOutput, const char *userOutput) {
  36. FILE *fp_std = fopen(stdOutput, "r"), *fp_user = fopen(userOutput, "r");
  37. if (fp_std == nullptr || fp_user == nullptr) {
  38. sprintf(info, "Open file failed: %s\n", strerror(errno));
  39. return false;
  40. }
  41. bool flag = true;
  42. for (int i = ; !feof(fp_std) && !feof(fp_user); ++i) {
  43. char *p1 = fgets(buf1, BUFFER_SIZE, fp_std);
  44. char *p2 = fgets(buf2, BUFFER_SIZE, fp_user);
  45. if (p1 == nullptr && p2 == nullptr) {
  46. flag = true;
  47. break;
  48. } else {
  49. int len1 = p1 ? strlen(p1) : -, len2 = p2 ? strlen(p2) : -;
  50. if (p1 && p1[len1 - ] == '\n') p1[len1 - ] = , --len1;
  51. if (p2 && p2[len2 - ] == '\n') p2[len2 - ] = , --len2;
  52. if (p1 == nullptr || p2 == nullptr || len1 != len2 ||
  53. strcmp(p1, p2)) {
  54. if (len1 > MAX_LEN)
  55. sprintf(p1 + MAX_LEN, "... (%d characters omitted)",
  56. len1 - MAX_LEN);
  57. if (len2 > MAX_LEN)
  58. sprintf(p2 + MAX_LEN, "... (%d characters omitted)",
  59. len2 - MAX_LEN);
  60. sprintf(info,
  61. "Difference found in line %d:\n std: %s\n user: %s\n",
  62. i, p1 ? p1 : "(EOF Detected)",
  63. p2 ? p2 : "(EOF Detected)");
  64. flag = false;
  65. break;
  66. }
  67. }
  68. }
  69. fclose(fp_std), fclose(fp_user);
  70. return flag;
  71. }
  72.  
  73. int main() {
  74. int totaltimeCnt = ;
  75. printf("Compiling... ");
  76. if (run("g++ %s -o %s", userFile, userExeName) ||
  77. run("g++ %s -o %s", stdFile, stdExeName) ||
  78. run("g++ %s -o %s", dataFile, dataExeName)) {
  79. puts("Compile failed.");
  80. printf("Press ENTER to exit.\n");
  81. getchar();
  82. return ;
  83. }
  84.  
  85. puts("Finished.");
  86. clock_t stUser, edUser, stStd, edStd;
  87. bool Accepted = true;
  88. for (int i = , ret; i <= CASE_CNT; ++i) {
  89. printf("Case %03d: ", i);
  90. run("%s >%s", dataExeName, dataOutputName);
  91.  
  92. // run std solution
  93. stStd = clock();
  94. ret = run("%s <%s >%s", stdExeName, dataOutputName, stdOutputName);
  95. edStd = clock();
  96. if (ret) {
  97. printf("Non Zero Exit Code: Std solution returned value %d\n", ret);
  98. Accepted = false;
  99. break;
  100. }
  101.  
  102. // run user's solution
  103. stUser = clock();
  104. ret = run("%s <%s >%s", userExeName, dataOutputName, userOutputName);
  105. edUser = clock();
  106. if (ret) {
  107. printf("Non Zero Exit Code: User's solution returned value %d\n",
  108. ret);
  109. Accepted = false;
  110. break;
  111. }
  112.  
  113. if (!fileCompare(stdOutputName, userOutputName)) {
  114. printf("Wrong answer.\n------------------------------\n");
  115. printf("%s", info);
  116. printf("------------------------------\n");
  117. Accepted = false;
  118. break;
  119. }
  120.  
  121. printf("Accepted. StdTime:%4d ms, UserTime:%4d ms\n",
  122. int(edStd - stStd), int(edUser - stUser));
  123. totaltimeCnt += int(edUser - stUser);
  124. }
  125. if (Accepted) {
  126. printf("\nUser's solution got accepted after %d tests.\n", CASE_CNT);
  127. printf("Average time spent: %.2f ms.\n",
  128. double(totaltimeCnt) / CASE_CNT);
  129. }
  130. printf("Press ENTER to exit.\n");
  131. getchar();
  132. return ;
  133. }

Windows系统对拍程序的更多相关文章

  1. [转]Linux/Windows下脚本对拍程序

    [新]简单写法 (转载自:https://blog.csdn.net/ylsoi/article/details/79824655) 要求:文件输入输出,且输入输出文件需要对应 Linux: #inc ...

  2. 手把手教你写对拍程序(PASCAL)

    谁适合看这篇文章? ACMERS,OIERS或其它参加算法竞赛或需要算法的人 对操作系统并不太熟悉的人 不会写对拍的人 在网上找不到一个特别详细的对拍样例的人 不嫌弃我写的太低幼的人 前言 在NOIP ...

  3. 制造测试数据的程序及对拍程序概述(Like CyaRon)

    作为一名OIer,比赛时,对拍是必须的 不对拍,有时可以悔恨终身 首先,对拍的程序 一个是要交的程序 另一个可以是暴力.搜索等,可以比较慢,但是必须正确 下面是C++版对拍程序(C++ & c ...

  4. [zt]手把手教你写对拍程序(PASCAL)

    谁适合看这篇文章? ACMERS,OIERS或其它参加算法竞赛或需要算法的人 对操作系统并不太熟悉的人 不会写对拍的人 在网上找不到一个特别详细的对拍样例的人 不嫌弃我写的太低幼的人 前言 在NOIP ...

  5. 对拍程序 x

    一.介绍 在做题或者正式比赛过程中总会把水题做水做乱,但因为样例有坑所以直接过了样例,然后拿去评测结果发现全WA.那如何在这种情况下检查自己程序或算法的正确性呢?对拍是一个简便省事的方案. 所谓“对拍 ...

  6. 使用Prism6 建立 Windows 10 通用程序.

    使用Prism6 建立 Windows 10 通用程序. 目标: 使用prism6,建立Windows 通用程序项目. 1, 解决方案—添加新建项目—通用—空白应用—输入名称—确定—确定 2 ,引用上 ...

  7. 需要正确安装 Microsoft.Windows.ShellExperienceHost 和 "Microsoft.Windows.Cortana" 应用程序。

    windows 10 开始菜单修复工具 Win10开始菜单修复工具出现的原因,自从升级到Windows  10,一直BUG不断,而其中有一个BUG非常的让你印象深刻,就是开始菜单无响应,你用着用着电脑 ...

  8. windows中的程序放在linux上因为字符集不同出错

    问题 在把windows下的一个python脚本挪到linux下的时候,出现了一个奇怪的问题,就是标题那样的报错,很明显,shell没有用对应的python解释器去解释脚本,而是直接用shell解释了 ...

  9. Mac OS下编写对拍程序

    介绍 对拍是信息学竞赛中重要的技巧,它通过一个效率低下但正确率可以保证的程序,利用庞大的随机生成数据来验证我们的高级算法程序.对拍最大的优势在于可以通过人力所不能及的速度和数量达到验证的效果.下面我们 ...

随机推荐

  1. Bringing up interface eth0: Device eth0 does not seem to be presen

    在公司的电脑虚拟机上安装了centos 6.5 ,然后我把他克隆下来用在家里电脑的虚拟机上,打开后查看ip,发现只有回环地址lo,没有eth0, 于是重启网络 输入 service network r ...

  2. 建造者模式(Builder)——从组装电脑开始

    建造者模式(Builder)--从组装电脑开始 建造者模式概括起来就是将不同独立的组件按照一定的条件组合起来构成一个相对业务完整的对象.调用者无需知道构造的过程. 我们从组装电脑开始 让我们从买组装电 ...

  3. springboot打成war包并携带第三方jar包

    1.修改打包方式为war     <packaging>war</packaging> 2.添加第三方依赖的jar到pom     我的第三方jar包在resoueces目录下 ...

  4. PTA Is Topological Order

    Write a program to test if a give sequence Seq is a topological order of a given graph Graph. Format ...

  5. Dom中的一些接口

    节点都是单个对象,有时需要一种数据结构,能够容纳多个节点.DOM 提供两种节点集合,用于容纳多个节点:NodeList和HTMLCollection.这两种集合都属于接口规范.许多 DOM 属性和方法 ...

  6. jQuery笔记(四)jQuery中的动画

    jQuery最吸引人的地方莫过于能做出绚丽的动画了,也是能极大提高用户体验的地方,这次我们就来一探jQuery中的动画! 一. show()方法和hide()方法 show()方法与hide()方法是 ...

  7. linux100讲——80 系统函数库介绍

    1.系统自建了函数库,可以在脚本中引用 /etc/init.d/functions 2.自建函数库 使用 source 函数脚本文件 “导入”函数 3. vim /etc/init.d/functio ...

  8. C语言实现 循环队列

    #include <stdio.h>#include <stdlib.h>#include <stdbool.h> typedef struct queue{ in ...

  9. Docker学习笔记(2):使用Dockerfile构建镜像

    Dockerfile是用来构建Docker镜像的文件,是由一系列命令和参数构成的脚本.每条指令都必须为大写字母且后面要跟随至少一个参数,每条指令都会创建一个新的镜像层,并对镜像进行提交. Docker ...

  10. idea基于spring boot的依赖分开打包

    idea版本为2018.3.3 1.在菜单栏点击如图所示图标 Project Structure: 2.选择左侧菜单Artificial,然后在右侧点击 + 号按钮,在弹出的菜单中选择JAR -> ...