第六种:交互题的spj
本平台暂不支持交互题,所以题库里的交互题目前没有进行处理通过
可以参考 洛谷的交互题spj 对应写法
第七种[带有testlib.h]的另一种解决方式
…遇见后后续更新
2021-10-21更新
将以下文件入口对应
inf->标准输入 argv[1]
ouf->用户输出 argv[3]
ans->答案结果 argv[2]
void registerTestlibCmd(int argc, char* argv[]) { __testlib_ensuresPreconditions(); testlibMode = _checker; __testlib_set_binary(stdin); if (argc > 1 && !strcmp("--help", argv[1])) __testlib_help(); // if (argc < 4 || argc > 6) // { // quit(_fail, std::string("Program must be run with the following arguments: ") + // std::string("<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]") + // "\nUse \"--help\" to get help information"); // } appesMode = false; // if (argc == 3) {///改 // resultName = ""; // appesMode = false; // } // // if (argc == 4) { // resultName = make_new_file_in_a_dir(argv[3]); // appesMode = false; // }///改 // if (argc == 6) // { // if (strcmp("-APPES", argv[5]) && strcmp("-appes", argv[5])) // { // quit(_fail, std::string("Program must be run with the following arguments: ") + // "<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]"); // } // else // { // resultName = argv[4]; // appesMode = true; // } // } inf.init(argv[1], _input); ouf.init(argv[3], _output); ans.init(argv[2], _answer);/// 改 } void registerTestlib(int argc, ...) { if (argc < 3 || argc > 5) quit(_fail, std::string("Program must be run with the following arguments: ") + "<input-file> <output-file> <answer-file> [<report-file> [<-appes>]]"); char** argv = new char*[argc + 1]; va_list ap; va_start(ap, argc); argv[0] = NULL; for (int i = 0; i < argc; i++) { argv[i + 1] = va_arg(ap, char*); } va_end(ap); registerTestlibCmd(argc + 1, argv); delete[] argv; }
第八种 使用validation.h的BAPC2018(较难)
首先站是原始的BAPC后台validation.h文件:
// A header library to safely parse team input. // It does not support floating points or big integers. // The easiest way to use this is to symlink it from a validator directory, // so that it will be picked up when creating a contest zip. // The default checking behaviour is lenient for both white space and case. // When validating .in and .ans files, the case_sensitve and space_change_sensitive flags should be // passed. When validating team output, the flags in problem.yaml should be used. #include <algorithm> #include <stdexcept> #include <fstream> #include <iostream> #include <limits> using namespace std; const string case_sensitive_flag = "case_sensitive"; const string space_change_sensitive_flag = "space_change_sensitive"; class Validator { const int ret_AC = 42, ret_WA = 43; bool case_sensitive; bool ws; public: Validator(int argc, char **argv, istream &in = std::cin) : in(in) { for(int i = 0; i < argc; ++i) { if(argv[i] == case_sensitive_flag) case_sensitive = true; if(argv[i] == space_change_sensitive_flag) ws = true; } if(ws) in >> noskipws; } // No copying, no moving. Validator(const Validator &) = delete; Validator(Validator &&) = delete; // At the end of the scope, check whether the EOF has been reached. // If so, return AC. Otherwise, return WA. ~Validator() { eof(); AC(); } void space() { if(ws) { char c; in >> c; if(c != ' ') expected("space", string("\"") + c + "\""); } // cerr << "read space!\n"; } void newline() { if(ws) { char c; in >> c; if(c != '\n') expected("newline", string("\"") + c + "\""); } // cerr << "read newline!\n"; } // Just read a string. string read_string() { return read_string_impl(); } // Read a string and make sure it equals `expected`. string read_string(string expected) { return read_string_impl(expected); } // Read an arbitrary string of a given length. string read_string(size_t min, size_t max) { string s = read_string(); if(s.size() < min || s.size() > max) expected("String of length between " + to_string(min) + " and " + to_string(max), s); return s; } // Read the string t. void test_string(string t) { string s = read_string(); if(case_sensitive) { if(s != t) expected(t, s); } else { if(lowercase(s) != lowercase(t)) expected(t, s); } } // Read a long long. long long read_long_long() { string s = read_string_impl("", "integer"); long long v; try { size_t chars_processed = 0; v = stoll(s, &chars_processed); if(chars_processed != s.size()) WA("Parsing " + s + " as long long failed! Did not process all characters"); } catch(const out_of_range &e) { WA("Number " + s + " does not fit in a long long!"); } catch(const invalid_argument &e) { WA("Parsing " + s + " as long long failed!"); } return v; } // Read a long long within a given range. long long read_long_long(long long low, long long high) { auto v = read_long_long(); if(low <= v && v <= high) return v; expected("integer between " + to_string(low) + " and " + to_string(high), to_string(v)); } int read_int() { return read_long_long(std::numeric_limits<int>::min(), std::numeric_limits<int>::max()); } int read_int(int low, int high) { int v = read_long_long(std::numeric_limits<int>::min(), std::numeric_limits<int>::max()); if(low <= v && v <= high) return v; expected("integer between " + to_string(low) + " and " + to_string(high), to_string(v)); } // Read a long double. long double read_long_double() { string s = read_string_impl("", "integer"); long double v; try { size_t chars_processed; v = stold(s, &chars_processed); if(chars_processed != s.size()) WA("Parsing ", s, " as long double failed! Did not process all characters."); } catch(const out_of_range &e) { WA("Number " + s + " does not fit in a long double!"); } catch(const invalid_argument &e) { WA("Parsing " + s + " as long double failed!"); } return v; } // Check the next character. bool peek(char c) { if(!ws) in >> ::ws; return in.peek() == char_traits<char>::to_int_type(c); } // Return WRONG ANSWER verdict. [[noreturn]] void expected(string exp = "", string s = "") { if(s.size()) cout << "Expected " << exp << ", found " << s << endl; else if(exp.size()) cout << exp << endl; exit(ret_WA); } template <typename T> [[noreturn]] void WA(T t) { cout << t << endl; exit(ret_WA); } template <typename T, typename... Ts> [[noreturn]] void WA(T t, Ts... ts) { cout << t; WA(ts...); } template <typename... Ts> void assert(bool b, Ts... ts) { if(!b) WA(ts...); } private: // Read an arbitrary string. // expected: if not "", string must equal this. // wanted: on failure, print "expected <wanted>, got ..." string read_string_impl(string expected_string = "", string wanted = "string") { if(ws) { char next = in.peek(); if(isspace(next)) expected(wanted, "whitespace"); } string s; if(in >> s) { if(!case_sensitive) { s = lowercase(s); expected_string = lowercase(expected_string); } if(!expected_string.empty() && s != expected_string) WA("Expected string \"expected\", but found ", s); return s; } expected(wanted, "nothing"); } // Return ACCEPTED verdict. [[noreturn]] void AC() { exit(ret_AC); } void eof() { if(in.eof()) return; // Sometimes EOF hasn't been triggered yet. if(!ws) in >> ::ws; char c = in.get(); if(c == char_traits<char>::eof()) return; expected("EOF", string("\"") + char(c) + "\""); } // Convert a string to lowercase is matching is not case sensitive. string &lowercase(string &s) { if(!case_sensitive) return s; transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } istream ∈ };
我们尤其需要注意公有成员方法:
Validator(int argc, char **argv, istream &in = std::cin) : in(in) { for(int i = 0; i < argc; ++i) { if(argv[i] == case_sensitive_flag) case_sensitive = true; if(argv[i] == space_change_sensitive_flag) ws = true; } if(ws) in >> noskipws; }
main中的前几行代码:
// Set up the input and answer streams. std::ifstream in(argv[1]); std::ifstream ans(argv[2]);
因为本平台都是使用文件的形式进行判断所提交的代码,这里可以用流的形式进行操作,将42、43改成对应的0、1然后将main中添加如下代码:
// Set up the input and answer streams. std::ifstream in(argv[1]); std::ifstream ans(argv[2]); std::ifstream user(argv[3]); Validator out(argc, argv, user); // 以下代码为输入
然后将公有成员构造方法改成:
Validator(int argc, char **argv, std::ifstream &in) : in(in) { for(int i = 0; i < argc; ++i) { if(argv[i] == case_sensitive_flag) case_sensitive = true; if(argv[i] == space_change_sensitive_flag) ws = true; } if(ws) in >> noskipws; }
即可完美解决