1. 程式人生 > >『c++的資料與對拍』

『c++的資料與對拍』

<前言>
在驗證猜想時,對拍可是個好工具哦!


<更新提示>

<第一次更新>新技能get✔


<正文>

對拍

關於對拍,主要是用於在考試,比賽時的程式驗證,可以通過自己針對性的資料找出程式的錯誤之處。可以與暴力程式比較,驗證自己演算法或猜想的正確性,也可以在做題時放後臺執行,用於檢測程式碼是否存在錯誤。當你能熟練的運用對拍時,它將是一個極其有用的工具。

如何實現對拍

實現對拍,我們需要準備4個cpp檔案,分別是:
1 一定正確的暴力程式(right.cpp)
2 等待驗證的高分程式(test.cpp)
3 生成資料的程式(make_data.cpp)
4 對拍,檢查的程式(checker.cpp)
然後我們執行right.cpp,test.cpp,得到兩個exe檔案,再新建一個input.in檔案,作為它們共同的檔案輸入源。準備好這7個檔案後,我們執行checker.cpp,即可進行對拍。

程式碼編寫

right.cpp,test.cpp

根據題目需要編寫。
注意,right.cpp是答案一定正確的暴力程式test.cpp是待驗證的程式。其中,我們用freopen和fclose函式來實現檔案輸入輸出,唯一的要求是兩個程式的輸入檔案需要相同。示例程式碼如下:

//right.cpp
//樸素演算法實現序列的區間求和
#include<bits/stdc++.h>
using namespace std;
int main()
{
    freopen("input.in","r",stdin);
    freopen("right.out","w",stdout);
    int
n,a,b,p[10080]={},ans=0; cin>>n>>a>>b; for(int i=1;i<=n;i++) { cin>>p[i]; } for(int i=a;i<=b;i++) { ans+=p[i]; } cout<<ans<<endl; fclose(stdin); fclose(stdout); return 0; }
//test.cpp
//利用字首和實現序列的區間求和
#include<bits/stdc++.h>
using namespace std; int main() { freopen("input.in","r",stdin); freopen("test.out","w",stdout); int a,n,b,s[10080]={}; cin>>n>>a>>b; for(int i=1;i<=n;i++) { cin>>s[i]; s[i]+=s[i-1]; } cout<<s[b]-s[a-1]<<endl; fclose(stdin); fclose(stdout); return 0; }

切記:檔名可以由自己決定,但兩個cpp檔案的輸入檔案必須相同。(在示例中即為input.in檔案)

make_data.cpp

我們利用偽隨機數來生成資料,其中,生成資料的講究有很多,已經超出了我們的探討的範圍,請自行查詢相關的資料。
我們可以使用該資料生成模板:

#include<bits/stdc++.h>
using namespace std;
void make_data(int num)
{
    FILE* fp=fopen("input.in","w");
    srand(num);
    //...
    fprintf(fp,"",);
    fclose(fp);
}

注意:fopen函式中的檔名可以自己定,但需要與right.cpp和test.cpp的檔案輸入名相同(在示例中,fopen函式的檔名必須為input.in)。然後,基本的資料生成操作就是由rand()函式生成資料,將其賦值在某個變數中,再用fprintf函式輸出到檔案中即可。關於rand()函式,我們只需知道它能自動生成一個104級別的隨機數,我們用乘法,取模等操作得到自己想要規模的資料,使用方法為直接賦值到變數。而fprintf函式是用於輸出檔案,其中要在括號的最前面加上fp,後半段用法與printf函式用法相同,即fprintf(fp,"/*此處用法與printf相同*/",/*此處用法與printf相同*/)

對應上文,如下是一個序列區間求和的資料生成程式:

//make_data.cpp
#include<bits/stdc++.h>
using namespace std;
void make_data(int num)
{
    FILE* fp=fopen("input.in","w");
    srand(num);
    int t=rand()%100*100,l=rand()*777%50,r=l+(rand()%38);
    fprintf(fp,"%d %d %d\n",t,l,r);
    for(int i=1;i<t;i++)
    {
        fprintf(fp,"%d\n",rand()*8848%9901);
    } 
    fprintf(fp,"%d\n",rand()*9999%10097);
    fclose(fp);
}
checker.cpp

我們主要使用system函式來呼叫程式並判斷。
可以使用如下模板:

#include<bits/stdc++.h>
#include "make_data.cpp"
using namespace std;
int main()
{
    srand(time(0));
    for(int t=1;t<=N;t++)
    {
        make_data(rand());
        system("test.exe");
        system("right.exe");
        printf("No:%d\n",t);
        if(system("fc test.out right.out"))
        {
            printf("Wrong Asnwer\n");
            while(1); 
        } 
    }
    printf("END\n");
    while(1);
}

注意:模板中N代表你需要對拍的資料組數。system函式中呼叫的是exe檔案,檔名與cpp檔案相同(在示例中,即為right.exe和test.exe),和上一節“如何實現對拍”中的一樣,需要我們先執行一遍right.cpp和test.cpp來生成這兩個exe檔案,反覆強調的檔名一定不能錯。接著,if語句中的system函式一定不能忘打比較引數”fc”,比較的兩個檔名為test.cpp和right.cpp所生成的輸出檔案(在示例中即為test.out與right.out)。這樣就完成checker.cpp了。

對應上文,如下是一個對拍5000組資料的檢查程式:

//checker.cpp
#include<bits/stdc++.h>
#include "make_data.cpp"
using namespace std;
int main()
{
    srand(time(0));
    for(int t=1;t<=5000;t++)
    {
        make_data(rand());
        system("test.exe");
        system("right.exe");
        printf("No:%d\n",t);
        if(system("fc test.out right.out"))
        {
            printf("Wrong Asnwer\n");
            while(1); 
        } 
    }
    printf("END\n");
    while(1);
}
執行與使用

執行checker前,在檢查一遍是否準備好了檔案,4個cpp,2個exe,一個自己建的空檔案作為兩個執行程式的共同輸入源,資料生成的輸出源(在示例中,即為input.in)。接著執行checker.cpp,開始對拍。
在執行過程中,如果沒有錯誤,對拍會自動進行,可以放在後臺執行,如果出現錯誤,對拍會自動停止,按ctrl+c退出,然後你就可以在資料生成的輸出源中找到使你程式出錯的那一組資料(在示例中即為input.in)。
注意了,所有檔案在同一目錄下哦!
這裡寫圖片描述
對拍的效果如圖哦。


<後記>


<廢話>