Q:写个 Special Judge 太难了,面对各种各样奇怪的输出,搞不好 spj 就 RE 了。
A:试试用 Testlib 写 checker?根本不用担心各种各样奇怪的格式问题。
Q:写个数据生成器太难了,同样一套数据生成器,同样的生成参数,放到 Linux 下生成的数据就变了个样,这咋整啊?
A:用 Testlib 写 generator 吧,同样的数据生成器,同样的参数,保证在任何环境下参数都一样。
Q:草,最近一场模拟赛出题人用脚造数据,明明是一棵树,他给造了个环出来。
A:你可以教他用 Testlib 写 Validator。
Q:最近想出个交互题,不知道交互器咋写。
A:用 Testlib 吧,写 interactor 也方便了不少呢。
Q:所以 Testlib 究竟是啥东西?为啥这么牛逼?
1 啥是 Testlib
Testlib 是一套历史悠久的出题辅助工具库。它可以用于书写数据生成器(Generator),数据校验器(Validator),答案检查器(checker),交互器(interactor)。
著名编程竞赛平台 Codeforces 是 Testlib 的最大使用者。在 Codeforces 上出题,上面提到的四种程序都需要使用 Testlib 完成(详见 ouuan 写的 OI 出题指南)。
最新版本的 Testlib 可以在 Github 上找到。
2 Testlib 的 IO 库
面对各种各样奇怪的输出文件,出题人都会感到十分头疼。
使用常规的 IO 来读取数据,鲁棒性很难得到保证。因此 Testlib 通过一套完善的 API 来读取数据,从而确保能在任何奇怪数据的考验下,都能给出正确的结果。
因为 Testlib 的 IO 库实在太重要了,我们对 Testlib 的介绍,首先从它的 IO 函数开始。
2.1 流对象
对象名
描述
inf
输入文件流
ouf
选手输出流
ans
标准答案流
调用不同流对象的成员函数,就可以从不同的流中读入数据。
2.2 流函数
因为 Testlib 的流函数非常多,这里只列出一些常用函数。
有些函数有等价的表示,下面也一并给出。
函数
描述
char readChar()
读入一个字符。
char readChar(char c)
读入一个字符,要求必须为 c。
char readSpace()
读入一个空格,等价于 readChar(' ')。
void unreadChar(char c)
把字符 c 返回到流中。
string readToken() 或 string readWord()
读入一个串,不包含任何空字符(空格,制表符,换行等)。
string readToken(string regex) 或 string readWord(string regex)
读入一个串,且必须与 regex 一致。
long long readLong()
读入一个 64 位带符号整数。
long long readLong(long long L,long long R)
读入一个 64 位带符号整数,要求在 $[L,R]$ 的范围内。
vector readLongs(int n, long long L, long long R)
一次性读入 $n$ 个 64 位带符号整数,要求每个数都在 $[L,R]$ 的范围内。
int readInt() 或 int readInteger()
读入一个 32 位带符号整数。
int readInt(int L,int R) 或 int readInteger(int L,int R)
读入一个 32 位带符号整数,要求在 $[L,R]$ 范围内。
vector readInts(int n, int L, int R) 或 vector readIntegers(int n, int L, int R)
一次性读入 $n$ 个 32 位带符号整数,要求每个数都在 $[L,R]$ 范围内。
double readReal() 或 double readDouble()
读入一个双精度浮点数。
double readReal(double L, double R) 或 double readDouble(double L, double R)
读入一个双精度浮点数,要求在 $[L,R]$ 范围内。
double readStrictReal(double L, double R, int minPrecision, int maxPrecision) 或 double readStrictDouble(double L, double R, int minPrecision, int maxPrecision)
读入一个双精度浮点数,要求在 $[L,R]$ 范围内,且它的小数位数必须介于 $[minPrecision,maxPrecision]$ 之间,且不允许使用科学计数法等其他形式(例如 1.0e+2 这样的形式就是不允许的)。
string readString() 或 string readLine()
读入一整行(包含换行符),将流指针指向新行的第一个字符(如果存在)。
string readString(string regex) 或 string readLine(string regex)
读入一整行(包含换行符),且要求读入的串与 regex 一致。
void readEoln()
读入换行符,注意在 Windows 下会读入 CR LF,而在 Linux 下会读入 LF。
void readEof()
读入文件结束符 EOF。
调用的时候,只需按照 流对象.流函数 这样的语法调用,即可从指定的流中执行读入操作。例如 inf.readInt() 就可以从输入