跳转至

通用

本页面介绍 Testlib checker/interactor/validator 的一些通用状态/对象/函数、一些用法及注意事项。请在阅读其他页面前完整阅读本页面的内容。

通用状态

结果 Testlib 别名 含义
Ok _ok 答案正确。
Wrong Answer _wa 答案错误。
Presentation Error _pe 答案格式错误。注意包括 Codeforces 在内的许多 OJ 并不区分 PE 和 WA。
Partially Correct _pc(score) 答案部分正确。仅限于有部分分的测试点,其中 score 为一个正整数,从 (没分)到 (可能的最大分数)。(quitf+_pc 只是为了兼容旧的 pascal-testlib,如果想要输出部分分,建议使用 quitp1
Fail _fail validator 中表示输入不合法,不通过校验。
checker 中表示程序内部错误、标准输出有误或选手输出比标准输出更优,需要裁判/出题人关注。(也就是题目锅了)

通常用程序的返回值表明结果,但是也有一些其他方法:创建一个输出 xml 文件、输出信息到 stdout 或其他位置……这些都通过下方函数表中的 quitf 函数来完成。

通用对象

对象 含义
inf 输入文件流
ouf 选手输出流
ans 参考输出流

通用函数

非成员函数:

调用 含义
void registerTestlibCmd(int argc, char* argv[]) 注册程序为 checker
void registerInteraction(int argc, char* argv[]) 注册程序为 interactor
void registerValidation()/void registerValidation(int argc, char* argv[]) 注册程序为 validator
void registerGen(int argc, char* argv[], int randomGeneratorVersion) 注册程序为 generator
randomGeneratorVersion 推荐为 1
void quit(TResult verdict, string message)/void quitf(TResult verdict, string message, ...) 结束程序,返回 verdict,输出 message
void quitif(bool condition, TResult verdict, string message, ...) 如果 condition 成立,调用 quitf(verdict, message, ...)
void quitp(F points, string message, ...) 结束程序,返回部分分。大部分 OJ(如洛谷、UOJ)的 points 需要提供一个 内的实数,表示得分百分比,还有部分 OJ(如 Lyrio)的 points 需要提供一个 的实数(OJ 会自动舍弃小数部分),表示百分制下的测试点得分

流成员函数:

调用 含义
char readChar() 读入一个字符
char readChar(char c) 读入一个字符,必须为 c
char readSpace() 等同于 readChar(' ')
string readToken()/string readWord() 读入一个串,到空白字符(空格、Tab、EOLN 等)停止
string readToken(string regex)/string readWord(string regex) 读入一个串,必须与 regex 匹配
long long readLong() 读入一个 64 位整数
long long readLong(long long L, long long R) 读入一个 64 位整数,必须在 之间
vector<long long> readLongs(int n, long long L, long long R) 读入 个 64 位整数,必须均在 之间
int readInt()/int readInteger() 读入一个 32 位整数
int readInt(int L, int R)/int readInteger(L, R) 读入一个 32 位整数,必须在 之间
vector<int> readInts(int n, int L, int R)/vector<int> readIntegers(int n, int L, int R) 读入 个 32 位整数,必须均在 之间
double readReal()/double readDouble() 读入一个双精度浮点数
double readReal(double L, double R)/double readDouble(double L, double R) 读入一个双精度浮点数,必须在 之间
double readStrictReal(double L, double R, int minPrecision, int maxPrecision)/double readStrictDouble(double L, double R, int minPrecision, int maxPrecision) 读入一个双精度浮点数,必须在 之间,小数位数必须在 之间,不得使用指数计数法等非正常格式
string readString()/string readLine() 读入一行(包括换行符),同时将流指针指向下一行的开头
string readString(string regex)/string readLine(string regex) 读入一行,必须与 regex 匹配
void readEoln() 读入 EOLN(在 Linux 环境下读入 LF,在 Windows 环境下读入 CR LF
void readEof() 读入 EOF
void quit(TResult verdict, string message)/void quitf(TResult verdict, string message, ...) 结束程序,若 Streamouf 返回 verdict,否则返回 _fail;输出 message
void quitif(bool condition, TResult verdict, string message, ...) 如果 condition 成立,调用 quitf(verdict, message, ...)

未完待续……

极简正则表达式

上面的输入函数中的一部分允许使用「极简正则表达式」特性,如下所示:

  • 字符集。如 [a-z] 表示所有小写英文字母,[^a-z] 表示除小写英文字母外任何字符。
  • 范围。如 [a-z]{1,5} 表示一个长度在 范围内且只包含小写英文字母的串。
  • 「或」标识符。如 mike|john 表示 mikejohn 其一。
  • 「可选」标识符。如 -?[1-9][0-9]{0,3} 表示 范围内的非零整数(注意那个可选的负号)。
  • 「重复」标识符。如 [0-9]* 表示零个或更多数字,[0-9]+ 表示一个或更多数字。
  • 注意这里的正则表达式是「贪婪」的(「重复」会尽可能匹配)。如 [0-9]?1 将不会匹配 1(因为 [0-9]?1 匹配上,导致模板串剩余的那个 1 无法匹配)。

首先 include testlib.h

请确保 testlib.h 是你 include 的 第一个 头文件,Testlib 会重写/禁用(通过名字冲突的方式)一些与随机有关的函数(如 random()),保证随机结果与环境无关,这对于 generator 非常重要,generator 页面 会详细说明这一点。

使用项别名

推荐给 readInt/readInteger/readLong/readDouble/readWord/readToken/readString/readLine 等的有限制调用最后多传入一个 string 参数,即当前读入的项的别名,使报错易读。例如使用 inf.readInt(1, 100, "n") 而非 inf.readInt(1, 100),报错信息将为 FAIL Integer parameter [name=n] equals to 0, violates the range [1, 100]

使用 ensuref/ensure()

这两个函数用于检查条件是否成立(类似于 assert())。例如检查 ,我们可以使用

1
ensuref(x[i] != y[i], "Graph can't contain loops");

还可以使用 C 风格占位符如

1
2
3
ensuref(s.length() % 2 == 0,
        "String 's' should have even length, but s.length()=%d",
        int(s.length()));

它有一个简化版 ensure(),我们可以直接使用 ensure(x> y) 而不添加说明内容(也不支持添加说明内容),如果条件不满足报错将为 FAIL Condition failed: "x > y"。很多情况下不加额外的说明的这种报错很不友好,所以我们通常使用 ensuref() 并加以说明内容,而非使用 ensure()

Warning

注意全局与成员 ensuref/ensure() 的区别

全局函数 ::ensuref/ensure() 多用于 generator 和 validator 中,如果检查失败将统一返回 _fail

成员函数 InStream::ensuref/ensure() 一般用于判断选手和参考程序的输出是否合法。当 InStreamouf 时,返回 _wa;为 inf(一般不在 checker 中检查输入数据,这应当在 validator 中完成)或 ans 时,返回 _fail。详见 Checker - 编写 readAns 函数

本文主要翻译并综合自 Testlib - Codeforces 系列。testlib.h 的 GitHub 存储库为 MikeMirzayanov/testlib