跳转至

Validator

前置知識:通用

本頁面將簡要介紹 validator 的概念與用法。

概述

Validator(中文:校驗器)用於檢驗造好的數據的合法性。當造好一道題的數據,又擔心數據不合法(不符合題目的限制條件:上溢、圖不連通、不是樹……)時,出題者通常會藉助 validator 來檢查。1

因為 Coderforces 支持 hack 功能,所以所有 Codeforces 上的題目都必須要有 validator。UOJ 也如此。Polygon 內建了對 validator 的支持。

使用方法

直接在命令行輸入 ./val 即可。數據通過 stdin 輸入。如果想從文件輸入可 ./val < a.in

若數據沒有問題,則什麼都不會輸出且返回 0;否則會輸出錯誤信息並返回一個非 0 值。

提示

  • 寫 validator 時,不能對被 validate 的數據做任何假設,因為它可能包含任何內容。因此,出題者要對各種不合法的情況進行判斷(使用 Testlib 會大大簡化這一流程)。
    • 例如,輸入一個點數為 \(n\) 的樹,主要工作是判斷 \(n\) 是否符合範圍和判斷輸入的是樹與否。但是切不可在判斷過 \(n\) 範圍之後就不對接下來輸入的邊的起點與終點的範圍進行判斷,否則可能會導致 validator RE。
    • 即使不會 RE 也不應該不判斷,這會導致你的報錯不正確。如上例,如果不判斷,報錯可能會是「不是一棵樹」,但是正確的報錯應當是「邊起點/終點不在 \([1,n]\) 之間」。
  • 不能對選手的讀入方式做任何假設。因此,必須保證能通過 validate 的數據完全符合輸入格式。
    • 例如,選手可能逐字符地讀入數字,在數字與數字之間只讀入一個空格。所以在編寫 validator 時,數據中的每一個空白字符都要在 validator 中顯式地讀入(如空格和換行)。
  • 結束時不要忘記 inf.readEof()
  • 如果題目開放 hack(或者説,validator 的錯誤信息會給別人看),請使報錯信息儘量友好。
    • 讀入變量時使用「項別名」。
    • 在判斷使用的表達式不那麼易懂時,使用 ensuref 而非 ensure。

示例

以下是 CF Gym 100541A - Stock Market 的 validator:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "testlib.h"

int main(int argc, char* argv[]) {
  registerValidation(argc, argv);
  int testCount = inf.readInt(1, 10, "testCount");
  inf.readEoln();

  for (int i = 0; i < testCount; i++) {
    int n = inf.readInt(1, 100, "n");
    inf.readSpace();
    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.readSpace();
    }
    inf.readEoln();
  }

  inf.readEof();
}

外部鏈接

參考資料與註釋