赞
踩
对拍,将两份代码的结果进行文件比较,从而找出一组hack数据,然后你就可以开开心心的对自己的错误代码进行debug了。而在CSP和NOIP考试中,用到的是Linux系统,所以两者的对拍程序稍微有一些区别。
首先,你要有东西可以拿来作比较。所以,你要有一份你需要hack的代码 sol.cpp;
然后你自己写一个暴力程序,或者在平时的话可以借用他人的AC代码,得到 bf.cpp;
要让程序运行,肯定需要数据输入才可以,那么就再写一个random.cpp,进行数据生成;
值得注意的是,要留意你的暴力程序的时间复杂度,适当调整一下随机数据的范围。数据较小的情况下虽然出错的概率很低,但是在脚本批量生成的情况下,总可以找出问题所在。
那么,在Windows系统下,我们分别运行三个程序再加上freopen,就可以得到三个exe文件和三个txt文件(具体见代码)。这时候就差不多了,再运行对拍程序,就可以进行数据生成和比较文件了。
以最简单的 A+B problem 为例子,我们就可以得到以下四个程序
- // sol.cpp
- #include<bits/stdc++.h>
-
- using namespace std;
-
- int main(){
- freopen("random.txt","r",stdin);
- freopen("sol.txt","w",stdout);
- int a,b;
- scanf("%d%d",&a,&b);
- printf("%d\n",a+b);
- return 0;
- }
- // bf.cpp
- #include<bits/stdc++.h>
-
- using namespace std;
-
- int main(){
- freopen("random.txt","r",stdin);
- freopen("bf.txt","w",stdout);
- int a,b;
- scanf("%d%d",&a,&b);
- while (b) ++a,--b;
- printf("%d\n",a);
- return 0;
- }
- // random.cpp
- #include<bits/stdc++.h>
-
- using namespace std;
-
- int main(){
- freopen("random.txt","w",stdout);
- srand(time(0));//初始化种子,使得每次数据随机
- int a,b;
- a=rand();b=rand();
- printf("%d %d\n",a,b);
- return 0;
- }
- //对拍程序
- #include<bits/stdc++.h>
-
- using namespace std;
-
- double st,ed;
-
- int main(){
- while (1) {
- system("random.exe");
- //先运行生成数据的代码,得到一组随机数据
- st=clock();
- //利用clock函数进行时间计算,此时st记录的是运行程序之前的时间
- system("sol.exe");
- ed=clock();
- //同理,ed记录运行程序之后的时间,ed-st即可以得出程序运行所需要的时间
- system("bf.exe");
- //运行暴力程序,得到正解
- if (system("fc sol.txt bf.txt")) { //利用fc进行文件比较
- // fc比较文件时如果有不同的地方则会返回true,如果没有不同,即答案正确的时候就会返回false
- printf("WA!\n");
- return 0;
- //此时的random.txt中的数据则为出错的随机数据,即hack数据
- }
- else printf("AC time:%lf ms\n",ed-st);
- //如果此时答案正确,则输出时间
- //当然,也可以这么写
- /*
- if (system("fc sol.txt bf.txt)){
- printf("WA!\n");
- return 0;
- }
- else if (ed-st>limited) {
- printf("TLE!\n");
- return 0;
- }
- else printf("AC time:%lf ms\n",ed-st);
- */
- //其中limited由自己在while(1)之前进行定义,或直接用数值代替
- }
- return 0;
- }
其实大体上和Windows系统相差不大,稍微注意一下就OK了,(但是不说明细节就是千古罪人),干脆就将Windows系统下的代码复制一遍,再将不同之处标出来就OK了。(绝对不是在水字数)
- // sol.cpp
- #include<bits/stdc++.h>
-
- using namespace std;
-
- int main(){
- freopen("random.out","r",stdin);
- freopen("sol.out","w",stdout);
- //注意freopen,Linux系统下用的是 .in 和 .out
- int a,b;
- scanf("%d%d",&a,&b);
- printf("%d\n",a+b);
- return 0;
- }
- // bf.cpp
- #include<bits/stdc++.h>
-
- using namespace std;
-
- int main(){
- freopen("random.out","r",stdin);
- freopen("bf.out","w",stdout);
- //和sol是一样的
- int a,b;
- scanf("%d%d",&a,&b);
- while (b) ++a,--b;
- printf("%d\n",a);
- return 0;
- }
- // random.cpp
- #include<bits/stdc++.h>
-
- using namespace std;
-
- int main(){
- freopen("random.out","w",stdout);
- //同上
- srand(time(0));//初始化种子,使得每次数据随机
- int a,b;
- a=rand();b=rand();
- printf("%d %d\n",a,b);
- return 0;
- }
- //对拍程序
- #include<bits/stdc++.h>
-
- using namespace std;
-
- double st,ed;
-
- int main(){
- while (1) {
- system("g++ random.cpp");
- system("./a.out");
- system("g++ sol.cpp");
- st=clock();
- system("./a.out");
- ed=clock();
- system("g++ bf.cpp");
- system("./a.out");
- if (system("diff sol.out bf.out")) {
- printf("WA!\n");
- return 0;
- }
- else printf("AC time:%lf ms\n",ed-st);
- /*
- if (system("diff sol.txt bf.txt)){
- printf("WA!\n");
- return 0;
- }
- else if (ed-st>limited) {
- printf("TLE!\n");
- return 0;
- }
- else printf("AC time:%lf ms\n",ed-st);
- */
- }
- return 0;
- }
需要注意的是,Linux和Windows差别较大的就是freopen和system里面的东西了,运用的时候需要注意一下。
其实对拍听上去很高级,东西也就这么一点点。但是要注意的是,freopen和system里面的名称一定要和程序以及输入输出文件相对应。
然后再稍微注意一下,Windows比较文件用的是 fc,但是Linux比较文件用的是 diff ,其他就没有太大的问题了。然后,你就可以愉快的去对拍了(bushi)。
完结完结。溜了溜了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。