Валидаторы на testlib.h
Difference between ru4 and ru5, changed 20 character(s)
Если вы написали несколько задач и подготовили для них тесты, вероятно, вы будете крайне неприятно себя чувствовать, если какие-то из тестов окажутся некорректными (в том смысле, что они не будут согласованы с условием задачи): значение какой-то величины будет больше допустимой верхней границы для нее, граф не будет удовлетворять требованиям связности или же не будет являться деревом...↵
Это естественно, что вы будете себя так чувствовать. Даже опытные авторы задач не застрахованы от ошибок (это случается даже на самых престижных соревнованиях: пример тому — финал чемпионата мира ACM ICPC 2007 г.)↵

Настоятельно рекомендуется писать специальную программу (называемую валидатором), чтобы формально проверить каждый тест на соответствие всем требованиям условия задачи.↵
Валидаторы обязательны для задач, которые готовятся для Codeforces. [Polygon](https://polygon.codeforces.com) имеет встроенную поддержку валидаторов.↵

Написать валидатор с помощью testlib.h на самом деле очень легко. ↵

## Пример↵

Ниже приводится валидатор, который была написан для задачи [problem:100541A]:↵

~~~~~↵
#include "testlib.h"↵

int main() {↵
    registerValidation();↵
    int testCount = inf.readInt(1, 10, "testCount");↵
    inf.readEoln();↵
    ↵
    for (int i = 0; i < testCount; i++) {↵
        int n = inf.readInt(1, 100, "n");↵
        inf.read
Char(' 'Space();↵
        inf.readInt(1, 1000000, "w");↵
        inf.readEoln();↵

        for(int i = 0; i < n; ++i) {↵
            inf.readInt(1, 1000, "p_i");↵
            if (i < n-1)↵
                inf.read
Char(' 'Space();↵
        }↵
        inf.readEoln();↵
    }↵

    inf.readEof();↵
}↵
~~~~~↵

Самое замечательное в этом валидаторе то, что он очень простой, и в нем очень трудно написать что-то неправильно.↵

В репозитории Github можно найти другие [примеры валидаторов](https://github.com/MikeMirzayanov/testlib/tree/master/validators).↵

## Функции и методы↵

Первая строка вашего кода должна содержать вызов `registerValidation()`: немного магии, и вы можете использовать необходимые методы. ↵

[cut]↵

Большинство методов для валидатора начинаются с префикса _read_  и именно выполняют чтение: перемещают указатель во входном потоке на следующую позицию после прочтения чего-либо. В процессе чтения обнаруживаются нарушения (входные данные не соответствуют тому, что вы пытаетесь прочитать: например, вы предпринимаете попытку прочитать целое число, а во входных данных встречается строка) и выбрасывается ошибка.↵

**Замечания**:↵

- Валидатор строг. Он проверяет корректное расположение пробелов. Например, последовательность вызовов вида _прочесть число_, _прочесть пробел_, _прочесть число_ гарантирует наличие ровно одного пробела между числами; в противном случае валидатор сообщит об ошибке.↵
- Некоторые методы частично поддерживают синтаксис регулярных выражений. Конечно, это не полноценные регулярные выражения, которые вы можете использовать во многих языках программирования. Это очень простая версия, в которой поддерживается следующее:↵
    - **Множество** символов: например, `[a-z]` &mdash; любые строчные латинские буквы, `[^a-z]` &mdash;  любые символы за исключением строчных латинских букв.↵
    - **Диапазон**, например, шаблон `[a-z]{1,5}` описывает строки длиной от 1 до 5 символов, содержащие только строчные латинские буквы.↵
    - Оператор **Или**,  например, шаблон `mike|john` &mdash; это или строка `mike`, или строка `john`.↵
    - **Необязательные** символы, например, шаблон `-?[1-9][0-9]{0,3}` допускает ненулевые целые числа от -9999 до 9999 (обратите внимание на необязательный знак "минус").↵
    - **Повторения**, например, шаблон `[0-9]*` допускает последовательности (как пустые, так и непустые) цифр, а шаблон  `[0-9]+` только непустые последовательности цифр.↵
- Также заметим, что при распознавании регулярных выражений используется очень простой жадный алгоритм. Например, шаблон `[0-9]?1` не допускает `1` в силу жадного поведения распознавателя.↵

Ниже представлен полный список функций и методов↵

|Метод / функция|Что делает|↵
|-|-|↵
|void registerValidation()| Эта функция должна быть вызвана в начале вашего кода, чтобы использовать валидатор. После вызова этой функции вы получаете доступ к входному потоку посредством переменной `inf`. |↵
|char readChar()| Этот метод возвращает текущий символ и перемещает указатель на один символ вперед.|↵
|char readChar(char c)| Аналогичен `readChar()`, но обеспечивает проверку, что прочитанный символ именно `c`.|↵
|char readSpace()| Аналогичен `readChar(' ')`.|↵
|void unreadChar(char c)| Возвращает символ `c` во входной поток.|↵
|string readToken()|Читает и возвращает очередную лексему (токен).|↵
|string readToken(string regex)|Аналогичен `readToken()`, но выполняет проверку соответствия лексемы (токена) указанному регулярному выражению `regex`.|↵
|string readWord()|Аналогичен `readToken()`.|↵
|string readWord(string regex)|Аналогичен `readToken(string regex)`.|↵
|long long readLong()|Читает и возвращает длинное целое (`long long` в C/C++ и `long` в Java)|↵
|long long readLong(int L, int R)|Аналогичен `readLong()`, но выполняет проверку, что значение находится в диапазоне $[L, R]$ (включительно)|↵
|int readInt(), <br> int readInteger()|Читает и возвращает целое число (тип `int` как в Java, так и в C/C++)|↵
|int readInt(int L, int R), <br> int readInteger(L, R)|Аналогичны `readInt()`, но выполняет проверку, что значение находится в диапазоне $[L, R]$ (включительно)|↵
|double readReal(), <br> double readDouble()|Читают и возвращают вещественное число (`double`).|↵
|double readReal(double L, double R), <br> double readDouble(double L, double R)|Аналогичны `readReal()`, `readDouble()`, но выполняют проверку, что значение находится в диапазоне $[L, R]$.|↵
|double readStrictReal(double L, double R, int minPrecision, int maxPrecision), <br> double readStrictDouble(double L, double R, int minPrecision, int maxPrecision)|Аналогичны `readReal(L, R)`, `readDouble(L, R)`, но выполняют дополнительную проверку, что количество цифр после десятичной точки находится в диапазоне $[minPrecision, maxPrecision]$. Экспоненциальная запись числа или другие нестандартные формы записи не допускаются.|↵
|string readString(), <br> string readLine()|Прочитывают строку, начиная с текущей позиции до EOLN.  Перемещают указатель во входном потоке на первый символ следующей строки (если она существует).|↵
|string readString(string regex), <br> string readLine(string regex)|Аналогичны `readString()` and `readLine()`, но выполняют проверку, что строка соответствует указанному регулярному выражению `regex`.|↵
|void readEoln()|Читает EOLN или завершает работу с ошибкой. Заметим, что этот метод чудесным образом работает как для Windows, так и для Linux. В Windows он прочитывает #13#10, а в Linux #10.|↵
|void readEof()|Читает EOF или завершает работу с ошибкой.|↵


#### Параметр _variableName_↵

Рекомендуется использовать последний строковый параметр _variableName_ в методах readInt/readInteger/readLong/readDouble/readWord/readToken/readString/readLine, чтобы сделать сообщение об ошибке более удобным для чтения. Т.е. предпочтительнее использовать `inf.readInt(1, 100, n)` вместо `inf.readInt(1, 100)`. При возникновении ошибки в первом случае будет выводиться сообщение вида  `FAIL Integer parameter [name=n] equals to 0, violates the range [1, 100]`.↵

#### Использование _ensure/ensuref_↵

Чтобы проверить некоторые требования (например, то, что граф не содержит петель, т.е. что $x_i \ne y_i$), используйте `ensuref(x_i != y_i, "Graph can't contain loops")`.  Допускается использование спецификаторов формата языка C, подобных `ensuref(s.length() % 2 == 0, "String 's' should have even length, but s.length()=%d", int(s.length()))`.↵
Также вы можете использовать более простую форму `ensure(x > y)`, в этом случае будет печататься нарушенное условие, если оно не выполняется: `FAIL Condition failed: "x > y"`.↵

Ссылки: [страница testlib.h на Github](https://github.com/MikeMirzayanov/testlib/blob/master/testlib.h)↵

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
ru11 Russian KAN 2022-07-07 20:21:26 2128
en24 English KAN 2022-07-07 20:16:48 4201 Tiny change: 'alidation()` which d' -> 'alidation(argc, argv)` which d'
ru10 Russian KAN 2022-07-07 19:00:36 2066 added global methods
ru9 Russian KAN 2022-07-07 18:43:02 2171 updated functions
ru8 Russian MikeMirzayanov 2018-12-29 14:28:59 20 Мелкая правка: ' readLong(int L, int R)|Аналог' -> ' readLong(long long L, long long R)|Аналог'
ru7 Russian arsijo 2018-11-02 01:08:48 527
en23 English arsijo 2018-11-02 01:01:28 400
ru6 Russian Zlobober 2016-10-01 20:36:24 32
en22 English Zlobober 2016-02-24 02:54:05 32
en21 English I_love_Hoang_Yen 2015-06-18 14:09:58 20 Tiny change: ' readLong(int L, int R)|Same a' -> ' readLong(long long L, long long R)|Same a'
ru5 Russian riadwaw 2015-06-10 22:35:00 20
en20 English I_love_Hoang_Yen 2015-06-10 21:00:28 20
ru4 Russian MikeMirzayanov 2015-06-10 12:29:16 118
en19 English MikeMirzayanov 2015-06-10 12:27:46 410
en18 English PrinceOfPersia 2015-06-10 08:57:32 218
ru3 Russian MikeMirzayanov 2015-06-10 02:25:07 67
en17 English MikeMirzayanov 2015-06-10 02:24:34 67
ru2 Russian MikeMirzayanov 2015-06-10 02:20:24 3
ru1 Russian elena 2015-06-10 02:18:13 7940 Первая редакция перевода на Русский
en16 English elena 2015-06-10 01:13:44 30 Tiny change: 'inus sign), note that it will match '-0'.\n - *' -> 'inus sign).\n - *'
en15 English MikeMirzayanov 2015-06-09 17:33:29 1546
en14 English PrinceOfPersia 2015-06-09 17:16:10 56
en13 English I_love_Hoang_Yen 2015-06-09 14:08:48 125
en12 English I_love_Hoang_Yen 2015-06-09 14:06:24 246 Tiny change: '| Same as readChar(' ').|\n|void ' -> '| Same as `readChar(' ')`.|\n|void '
en11 English I_love_Hoang_Yen 2015-06-09 13:56:28 86 Update styling
en10 English I_love_Hoang_Yen 2015-06-09 13:53:23 1840 (published)
en9 English I_love_Hoang_Yen 2015-06-09 13:38:13 291
en8 English I_love_Hoang_Yen 2015-06-09 13:34:33 28 Tiny change: ' C/C++)|\n\n|readInt' -
en7 English I_love_Hoang_Yen 2015-06-09 13:01:14 3 Tiny change: 'readInt(), readIntege' -> 'readInt(),\nreadIntege'
en6 English I_love_Hoang_Yen 2015-06-09 12:54:26 2 Tiny change: ' in range [L, R].|\n|readS' -> ' in range $[L, R]$.|\n|readS'
en5 English I_love_Hoang_Yen 2015-06-09 12:54:01 60
en4 English I_love_Hoang_Yen 2015-06-09 12:52:57 1888
en3 English I_love_Hoang_Yen 2015-06-09 12:34:31 206
en2 English I_love_Hoang_Yen 2015-06-09 12:04:31 331
en1 English I_love_Hoang_Yen 2015-06-09 12:01:01 1478 Initial revision (saved to drafts)