ACM中如何對拍?
前言
記錄一下我的學習過程,給自己點回憶,如果小夥伴不想看可以直接跳至後面代碼段。
對拍,我也是才學的,之前打acm有用過,但都是隊友敲對拍,我就專職擼代碼。前幾天朋友問我一個PAT的題目,我寫了一會兒ac了,他用鏈表去做的,但就是沒ac,我幫着debug了一下。因爲我平時不常用鏈表,我也花了一定時間去讀懂他的代碼,分析他的邏輯以及增刪是否有錯誤,這些大約花了我兩三小時去做,但是還是沒有找到bug。我想到了之前打ACM時候做的對拍,因爲我有自己的AC代碼,可以通過對拍去比較兩份代碼得到結果的不同,就去學習了一下對拍。
正文
多的不說了,上代碼(附註釋講解):
#include <cstdio>
#include<iostream>
#include<windows.h>
using namespace std;
int main()
{
int t=10;//你想要測試的數據組數
while(t)
{
t--;
//所有程序不需要使用文件讀寫,就正常程序即可
//製造數據,就是自己編個程序,利用隨機數產生滿足題意的數據即可。
system("makedata.exe > data.txt");
//這裏的b.exe爲AC代碼(或者暴力一定對的代碼)生成的可執行文件
system("b.exe < data.txt > b.txt"); //調用b.exe輸入爲data.txt的內容 輸出結果至b.txt
//這裏的c.exe爲待測試代碼生成的可執行文件
system("c.exe < data.txt > c.txt"); //調用b.exe輸入爲data.txt的內容 輸出結果至b.txt
//FC 一個DOS命令用於比較兩個或兩套文件,並顯示不同處。
if(system("fc b.txt c.txt")) //比較b.txt和c.txt的差距
break;
}
if(t==0) cout<<"no error"<<endl;
else cout<<"error"<<endl;
getchar();//防止一出現錯誤,窗口就關閉了
return 0;
}
最後直接執行這個對拍程序編譯生成的.exe可執行文件即可。
如何同時讓一份代碼跑多組數據
前言
這個是我在一個課程實驗上遇到了,老師給了很多個測試文件比如test1.txt-test5.txt,對應要生成out1.txt-out5.txt。這個時候我就想起來了才學的對拍,就可以用上呀。
正文
首先按照我的想法,就是把system(“b.exe < data.txt > b.txt”)中見的字符串給替換成"b.exe < testi.txt > outi.txt"就行了嘛。代碼如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <sstream>
#include <windows.h>
using namespace std;
//tostring 就是我自己寫的一個把整數轉換爲字符串的函數
string tostring(int x)
{
string res="";
while(x!=0)
{
res+=char('0'+x%10);
x/=10;
}
int ls=res.length();
for(int i=0;i<ls/2;i++)
{
int oth=ls-1-i;
swap(res[i],res[oth]);
}
return res;
}
int main()
{
string inpre = "test";
string txt = ".txt";
string rk = " > ";
string outpre = "tokenOut";
for (int i = 1; i <= 7; i++)
{
string str = "a.exe < ";
str += inpre + tostring(i) + txt + rk;
str += outpre + tostring(i) + txt;
//const char *s=&str[0]; 上下兩份代碼的差異處
system(s); //輸入data.txt 輸出b.txt
//cout << str << endl;
}
return 0;
}
這樣就相當於用個for循環去改變每一次的執行的dos命令裏的文件名即可。
但是當我編譯的時候卻發現程序報錯了,大致錯誤原因是system()的形參要求是const char *,而我的str就是一個字符串變量,那麼必然會報錯的呀?
解決方法
聲明一個const char * s的指針,讓其指向我的str就好了呀。
但是這裏要注意,const char * s是不能通過s指針去修改值的,這也是這個const 的作用。所以每一次要通過str自己去修改就好了。
附可使用代碼:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <sstream>
#include <windows.h>
using namespace std;
string tostring(int x)
{
string res="";
while(x!=0)
{
res+=char('0'+x%10);
x/=10;
}
int ls=res.length();
for(int i=0;i<ls/2;i++)
{
int oth=ls-1-i;
swap(res[i],res[oth]);
}
return res;
}
int main()
{
//system("a.exe < test1.txt > tokenOut1.txt");
string inpre = "test";
string txt = ".txt";
string rk = " > ";
string outpre = "tokenOut";
for (int i = 1; i <= 7; i++)
{
string str = "a.exe < ";
str += inpre + tostring(i) + txt + rk;
str += outpre + tostring(i) + txt;
const char *s=&str[0];//上下兩份代碼唯一不同的地方
system(s); //輸入data.txt 輸出b.txt
cout << str << endl;
}
return 0;
}
用上面的代碼就可以一份代碼跑多組數據,不用每次更改文件輸入輸出的路徑那麼麻煩了。
當然如果有小夥伴有更好的辦法,也可以在評論區教教我啊!
歡迎評論和指正!