#include #include #include #include #include #include #include #include #include /* $ ./a.out example.txt The following parameters are not defined: #0 #1 #2 #3 $ ./a.out example.txt first second The following parameters are not defined: #2 #3 $ ./a.out example.txt first second third fourth In this text first is a parameter, and the same is true for second meaning that first and second can be whatever we want. Also, as a test we add fourth as well, thus skipping the third argument (but as a test we include third here). */ int main(int argc, char** argv) { if (argc < 2) { std::cerr << "USAGE: " << argv[0] << " TEXT [PARAMETERS...]\n"; return 1; } std::ifstream ifs { argv[1] }; if (!ifs) { std::cerr << "Error: Unable to open file '" << argv[1] << "'\n"; return 2; } std::vector text { std::istream_iterator{ifs}, std::istream_iterator{} }; int index { 0 }; std::map parameters; std::transform(argv + 2, argv + argc, std::inserter(parameters, parameters.end()), [&index](std::string const& argument) { return std::make_pair("#" + std::to_string(index++), argument); }); // Find undefined parameters std::set unset_parameters { }; std::copy_if(std::begin(text), std::end(text), std::inserter(unset_parameters, std::end(unset_parameters)), [¶meters](std::string const& word) { if (word.front() != '#') return false; return parameters.find(word) == std::end(parameters); }); // Report error on undefined parameters if (unset_parameters.size() > 0) { std::cerr << "The following parameters are not defined:\n"; std::copy(std::begin(unset_parameters), std::end(unset_parameters), std::ostream_iterator{std::cerr, "\n"}); return 3; } // Substitute in the parameters std::transform(std::begin(text), std::end(text), std::begin(text), [¶meters](std::string const& word) { if (word.front() != '#') return word; return parameters[word]; }); // Print the finnished text std::copy(std::begin(text), std::end(text), std::ostream_iterator{std::cout, " "}); std::cout << std::endl; }