Windows系统对拍程序

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

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

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

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

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

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 = 20;  // 发现错误时,显示错误行数据的最大长度
 10 const int CASE_CNT = 200;                 // 对拍测试次数
 11 const int BUFFER_SIZE = 1 << 10;          // 每行的缓冲区大小
 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 * 3];
 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 = 1; !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) : -1, len2 = p2 ? strlen(p2) : -1;
 50             if (p1 && p1[len1 - 1] == '\n') p1[len1 - 1] = 0, --len1;
 51             if (p2 && p2[len2 - 1] == '\n') p2[len2 - 1] = 0, --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 = 0;
 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 0;
 83     }
 84 
 85     puts("Finished.");
 86     clock_t stUser, edUser, stStd, edStd;
 87     bool Accepted = true;
 88     for (int i = 1, 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 0;
133 }
View Code

 

转载于:https://www.cnblogs.com/sandychn/p/10355239.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值