[OI] Testlib

HaneDaniko發表於2024-08-15

Testlib 是用於實現 SpecialJudge 的一種方式

為了使用 Testlib,你需要在你的檔案中引用 Testlib.h

testlib.h 下載

使用 Testlib 程式

以 Testlib 的 check 功能示例(實際上 Tesklib 不止可以實現 check 功能)

首先你需要正確的引用到 testlib.h,一般有以下兩種方式

  • 直接丟到編譯器的 MinGW/include 目錄下
  • 直接丟到原始碼目錄下(需要用雙引號引用)

或者你也可以直接寫具體路徑,比如 #include "C:/Desktop/testlib.h" 之類的

或者使用相對路徑

相對路徑就是基於當前資料夾向前或向後翻的一種路徑,比如對於如下目錄結構:

-Desktop
    -Folder1
        -Folder2
            -file.cpp
    -Folder3
        -Folder4
            -testlib.h

假若你想要在 file.cpp 中引用到 testlib.h,你也可以這麼寫:

#include"../../Folder1/Folder2/testlib.h"

其中 ../ 表示返回上級目錄

在將下發的 checker.cpp 程式編譯完成後,就可以按照如下格式進行 checker

(一般來說是在終端中進行編譯執行,進行之前請先跳到 checker 所在目錄,並請將其他檔案也放進去)

Windows checker.exe input output answer

Linux ./checker input output answer

input 題目的輸入檔案,這個檔案也可以用資料生成器跑出來

output 你的程式的輸出檔案

answer 答案檔案 一般情況下,你寫對拍的時候是拿不到這個答案檔案的,但是你仍然可以檢驗一部分正確性:比如透過模擬能判斷出來的部分,或者是格式檢驗的部分。這就需要考驗你對 checker 進行改寫的能力了。一般在這種情況下,你完全可以在 answer 位置傳一個無關緊要的檔案,或者直接把 output 傳進去,但是不能空著

在使用 checker 跑對拍的時候,你可能需要判斷什麼時候應該 pause,事實上是這樣判斷的:

在呼叫 cmd 或 Linux 終端的時候,system() 函式實際上是有返回值的,它返回的是程式主程式的 return 值。而 testlib.h 會在正確時返回 0,出現錯誤時返回 1,因此你可以透過這一點來判斷正確性,即這麼寫:

if(system("checker.exe input output answer")){
    system("pause");
}

編寫 Testlib 程式

顯然,你不應該使用標準輸入輸出函式(互動題等特殊題型除外),而應該使用 testlib 提供的讀入函式

你需要在主函式使用入下內容以初始化 testlib

int main(int argc, char* argv[]) {
    registerTestlibCmd(argc, argv);
}

此外,testlib 不支援使用 <random> 下的大部分內容,如果你真的要用 rand(),testlib 提供了兩種方法:

  • 使用 mt19937
  • 使用內建函式
關於內建函式
 * Use "shuffle", and "rnd.next()" instead of them
 * because these calls produce stable result for any C++ compiler. Read
 * sample generator sources for clarification.
 *
 * Please read the documentation for class "random_t" and use "rnd" instance in
 * generators. Probably, these sample calls will be useful for you:
 *              rnd.next(); rnd.next(100); rnd.next(1, 2);
 *              rnd.next(3.14); rnd.next("[a-z]{1,100}").

關於檔案讀入,上述傳入的三個檔案,分別對應了三個 ifstream 型別的類,分別命名為:

inf 對應 input

ouf 對應 output

ans 對應 answer

它們的讀入函式如下所示:

函式 功能
char readChar() 讀入一個 char
char readChar(char c) 限定讀入字元,不符合則判為 _wa
char readSpace() 讀入一個空格
string readToken() 讀入一個字串,遇到空格、換行、eof 為止、
long long readLong() 讀入一個 longlong
long long readLong(long long L, long long R) 限定讀入範圍(包括 L,R),超出則判為 _wa
int readInt() 讀入一個 int
int readInt(int L, int R), 限定讀入範圍(包括 L,R),超出則判為 _wa
double readReal() 讀入一個實數
double readReal(double L, double R), 限定讀入範圍(包括 L,R),超出則判為 _wa
double readStrictReal(double L, double R, int minPrecision, int maxPrecision), 限定精度範圍(包括 L,R),超出則判為 _wa
string readString() 讀入一個字串
string readLine() 讀入一行 string,到換行或者 eof 為止
void readEoln() 讀入一個換行符
void readEof() 讀入一個 eof
int eof() 已到達檔案末尾則返回 1

關於判定,使用以下三個函式

quitf(st,...) 第一個引數用來傳入引數,告訴程式該答案正確還是不正確,有兩種,一種為 _ac,一種為 _wa,後面主要是用於輸出判斷資訊,會顯示出來給人看,用法和格式化輸出一致,如 quitf(_wa,"Answer is wrong, except %d, but read %d",ans,p);

quitp(score,..) 用來判 “部分正確”,第一個引數用來傳入一個 \([0,1]\) 的實數,表示得分百分比,後面就一樣了

testlib 程式會在讀入格式錯誤,或者檔案未被讀完的時候報出 wrong output format 錯誤,為了避免這個錯誤,你也可以使用 while(!ouf.seekEof()) ouf.readToken() 來讀完剩下的內容