搞信息學競賽的我們常常會因爲WA而苦惱——明明自己的測試數據都是對的怎麼一提交就錯了呢?這裏介紹一種方法——對拍,它能使我們不耗費多餘的時間苦苦手打測試數據。
實現方法
對拍,顧名思義,就是將兩個程序給相同的輸入,看看輸出是否一樣。
既然如此,我們就需要幾個步驟來實現它:
- 生成測試數據;
- 兩個程序分別跑一遍,生成兩個輸出;
- 比較兩個輸出。
有人可能看到這裏覺得可以用文件操作來完成。沒錯,是可以完成,但容易出錯。而一種更方便也更能裝逼的方法就是對拍了。
準備材料
- 你自己的程序;
- 不一定高效,但保證正確的程序;
- 數據生成器;
- 對拍程序。
第1、2項不多說,只需注意要把這4項放在同一個文件夾裏。現在重點說說第3、4項。
3.數據生成器
#include<iostream>
#include<cstdlib>//rand()需包含頭文件
using namespace std;
int main(int argc,char *argv[]){
printf("%d %d",rand()%10+1,rand()%10+1);//生成1~10的隨機數
return 0;
}
最簡單的隨機數生成器就完成了!我們暫且將它稱爲baby數據生成器
看到這裏的小夥伴不要太激動,如果你把這份代碼拷貝下來運行幾次後,你會發現每次生成的兩個隨機數都是一樣的。這是因爲我們沒有設置隨機數種子,所以,下一步,我們要設置隨機數種子。
#include<iostream>
#include<time.h>
#include<cstdlib>
using namespace std;
int main(int argc,char *argv[]){
srand(time(NULL));//加上這條代碼,就是將現在時間設爲隨機數種子的意思
printf("%d %d",rand()%10+1,rand()%10+1);
return 0;
}
好了,數據生成器2.0完成了,我們把它稱爲簡易版數據生成器吧
但是,這樣還不夠完美,因爲time(NULL)一秒才能更新一次,也就是說我們的簡易版數據生成器要至少一秒才能生成一個數據,太慢了!具體怎麼優化,我們等講完對拍程序了再說。
4.對拍程序
首先,我們新建一個批處理文件。啥?你居然不會?右鍵單擊——點擊新建——新建文本文檔——將文本文檔後綴名改成 .bat 即可。什麼?你不會更改後綴名?點擊計算機——點擊左上角的查看——將文件後綴名勾選框打勾。
好了,我們有了一個批處理文件。右鍵單擊它——點擊編輯。
1.生成一組數據:假設你的數據生成器命名爲rand.exe。現在,我們把這個測試數據重定向到一個文本里。
rand.exe > in.txt
是不是hin簡單?接下來,我們把文件輸入到程序裏。
rand.exe > in.txt
my.exe < in.txt
right.exe < in.txt
其中,數據生成器、自己的程序、正確的程序的名字可以自己自定義。
第3步:把輸出重定向到另一個文件裏
rand.exe > in.txt
my.exe < in.txt > my.txt
right.exe < in.txt > right.txt
最後,比較兩個文件(比較命令:fc)
rand.exe > in.txt
my.exe < in.txt > my.txt
right.exe < in.txt > right.txt
fc my.txt right.txt
好了,baby對拍程序寫好了!
但是,這個程序支持的功能是一次性的對拍,萬一數據難找點,估計你的手會 斷 抽筋。
那麼,能不能循環呢?當然可以!
@echo off
:start
rand.exe > in.txt
my.exe < in.txt > my.txt
right.exe < in.txt > right.txt
fc my.txt right.txt
if not errorlevel 1 goto start
set /p in=<in.txt
echo %in%
pause
goto start
哎哎,看不懂的兄臺憋走啊!
給你解釋好行了吧~
@echo off表示關閉回顯
:start 是一個標記,用於循環
中間部分我就不講了
if not errorlevel 1 goto start ,errorlevel是上一個語句的返回值,在文件不同時返回1,否則返回0;goto start就是循環
pause ,暫停,給你看數據
ps:如果有某些細節寫錯了,大佬們幫忙修正下哈
但是,這還不夠,我們再看回數據生成器。
相信很多人還不知道main函數裏的兩個參數是什麼意思吧,其實argc就是傳人的函數個數,*argv[]就是參數表。
前面我們說到,time(NULL)製造的隨機數種子效率太慢,其實,windows中還自帶一個隨機數生成器——%random%
那麼,數據生成器可以優化成這樣:
#include<iostream>
#include<time.h>
#include<cstdlib>
#include<sstream>
using namespace std;
stringstream s;
int main(int argc,char *argv[]){
int random;
if(argc>1){//就是把字符串轉化成整數,用其他方法也行
s.clear();
ss<<argv[1];
ss>>random;
}
srand(random);
printf("%d %d",rand()%10+1,rand()%10+1);
return 0;
}
stringstream使用方法參考這裏
然後,對拍程序裏這麼寫:
@echo off
:start
rand.exe %random% > in.txt
my.exe < in.txt > my.txt
right.exe < in.txt > right.txt
fc my.txt right.txt
if not errorlevel 1 goto start
set /p in=<in.txt
echo %in%
pause
goto start
好了,這下大功告成!我們可以用超級無敵宇宙霹靂吊炸天數據生成器和超級無敵宇宙霹靂吊炸天對拍程序愉快地玩耍了!
ps:別對名字有太大意見啦~