|
| 1 | +#include <iostream> |
| 2 | +#include "file.h" |
| 3 | + |
| 4 | +// Compare two files using NOIP rules. |
| 5 | +// i.e. ignore spaces before \n or \n before EOF |
| 6 | +// |
| 7 | +// Return value: |
| 8 | +// return true if the output passes the case; |
| 9 | +// otherwise the function will output the error to stdout and returns false |
| 10 | +bool compare(std::ifstream &&outputStream, std::ifstream &&answerStream) { |
| 11 | + File output(std::move(outputStream)), answer(std::move(answerStream)); |
| 12 | + for (;;) { |
| 13 | + // Handle EOF |
| 14 | + if (!output.next()) { |
| 15 | + DEBUG_OUTPUT("!output.next()"); |
| 16 | + |
| 17 | + if (answer.willEOF() |
| 18 | + && answer.getLine()==output.getLine() |
| 19 | + && answer.getColumn() == output.getColumn() |
| 20 | + && answer.getBufferPosition() == output.getBufferPosition()) |
| 21 | + return true; |
| 22 | + |
| 23 | + if (answer.charactersInRemainingLine(false) && output.getLine()==answer.getLine()) |
| 24 | + std::cerr << "wrong answer Too short on line " << answer.getLine() << "."; |
| 25 | + else if (answer.charactersInRemainingFile(true)) |
| 26 | + std::cerr << "wrong answer Too few lines."; // actually too few |
| 27 | + else std::cerr << "wrong output format Wrong format"; |
| 28 | + return false; |
| 29 | + } |
| 30 | + |
| 31 | + if (!answer.next()) { |
| 32 | + DEBUG_OUTPUT("!answer.next()"); |
| 33 | + if (output.charactersInRemainingLine(true) && output.getLine()==answer.getLine()) |
| 34 | + std::cerr << "wrong answer Too long on line " << answer.getLine() << "."; |
| 35 | + else if (output.charactersInRemainingFile(true)) |
| 36 | + std::cerr << "wrong answer Too many lines."; // actually too many |
| 37 | + else std::cerr << "wrong output format Wrong format"; |
| 38 | + return false; |
| 39 | + } |
| 40 | + |
| 41 | + output._dbg();answer._dbg(); |
| 42 | + // Compare |
| 43 | + if (output.get() != answer.get()) { |
| 44 | + DEBUG_OUTPUT("output.get() != answer.get()"); |
| 45 | + auto line = answer.getLine(); |
| 46 | + auto column = answer.getColumn(); |
| 47 | + auto charRead = output.get(); |
| 48 | + auto expected = answer.get(); |
| 49 | + bool outputHasMore = output.charactersInRemainingLine(true); |
| 50 | + bool answerHasMore = answer.charactersInRemainingLine(true); |
| 51 | + DEBUG_OUTPUT("outputHasMore=" << outputHasMore << ",answerHasMore=" << answerHasMore); |
| 52 | + if (outputHasMore || answerHasMore) { |
| 53 | + if (outputHasMore && answerHasMore) { |
| 54 | + std::cerr << "wrong answer On line " << line << " column " << column << ", read "; |
| 55 | + if (charRead <= 32 || charRead >= 127) |
| 56 | + std::cerr << "(ASCII " << static_cast<int>(charRead) << ")"; |
| 57 | + else |
| 58 | + std::cerr << charRead; |
| 59 | + std::cerr << ", expected " << expected << "."; |
| 60 | + } else |
| 61 | + std::cerr << "Too " << (answerHasMore ? "short" : "long") << " on line " << line << "."; |
| 62 | + return false; |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | + return true; |
| 67 | +} |
| 68 | + |
| 69 | +int main(int argc, char *argv[]) { |
| 70 | + if (argc < 4) { |
| 71 | + std::cerr << "FAIL Program must be run with the following arguments: <input-file> <output-file> <answer-file>" << std::endl; |
| 72 | + return -1; |
| 73 | + } |
| 74 | + |
| 75 | + // the input file (argv[1]) is ignored since it's not needed. |
| 76 | + auto outputFile = std::ifstream(argv[2], std::ifstream::binary); |
| 77 | + if (outputFile.fail()) { |
| 78 | + std::cerr << "wrong output format Output file not found: \"" << argv[2] << "\"" << std::endl; |
| 79 | + return -1; |
| 80 | + } |
| 81 | + auto answerFile = std::ifstream(argv[3], std::ifstream::binary); |
| 82 | + if (answerFile.fail()) { |
| 83 | + std::cerr << "FAIL Answer file not found: \"" << argv[3] << "\"" << std::endl; |
| 84 | + return -1; |
| 85 | + } |
| 86 | + if (compare(std::move(outputFile), std::move(answerFile))) |
| 87 | + std::cerr << "ok accepted"; |
| 88 | + // otherwise the error is already outputed in compare |
| 89 | +} |
0 commit comments