首页 > 解决方案 > boost::program_options 在指定了意外的位置参数时不报告错误

问题描述

这是一个使用 boost 来解析选项的简单程序:

#include <iostream>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

int main(int argc, char **argv) 
{
    try
    {
        size_t param = std::numeric_limits<size_t>::max();

        po::options_description desc("Syntax: [options] \"input binary file\".\nAllowed options:");
        desc.add_options()
            ("help,h", "produce help message")
            ("param,p", po::value<size_t>(&param), "param");

        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
        po::notify(vm);

        if (vm.count("help")) 
        {
            std::cout << desc << "\n";
        }
        else
        {
            std::cout << "Running with param " << param << std::endl;
            return 0;
        }
    }
    catch(std::exception& e) {
        std::cerr << "error: " << e.what() << "\n";
    }
    catch(...) {
        std::cerr << "Exception of unknown type!\n";
    }
    return 1;
}

以下是产生的输出:

然而,这一切都是意料之中的: hex2txt.exe foo输出Running with param 0

我本来希望得到一个错误,因为“foo”不是预期的。我在这里做错了什么?

标签: c++boostboost-program-options

解决方案


默认情况下接受位置。您可以检查是否收到任何内容,也可以指定不允许:

po::positional_options_description positionals;
po::store(po::command_line_parser(args.size(), args.data())
                .options(desc)
                .positional(positionals)
                .run(),

演示

住在科利鲁

#include <boost/program_options.hpp>
#include <iostream>
#include <iomanip>

namespace po = boost::program_options;

int main() {
    std::vector<char const*> const cases[] = {
        { "hex2txt.exe" }, // outputs Running with param 0
        { "hex2txt.exe", "--param", "3" }, // outputs Running with param 3
        { "hex2txt.exe", "--toto" }, // outputs error: unrecognised option '--toto'
        // All this is expected, however:
        { "hex2txt.exe", "foo" }, // outputs Running with param 0
    };

    for (auto args : cases) {
        std::cout << "------";
        for (auto arg : args)
            std::cout << " " << std::quoted(arg);
        std::cout << "\n";

        try {
            size_t param = 0; // std::numeric_limits<size_t>::max();

            po::options_description desc(
                "Syntax: [options] \"input binary file\".\nAllowed options:");
            desc.add_options()("help,h", "produce help message")(
                "param,p", po::value<size_t>(&param), "param");

            po::positional_options_description positionals;

            po::variables_map vm;
            po::store(po::command_line_parser(args.size(), args.data())
                    .options(desc)
                    .positional(positionals)
                    .run(),
                vm);
            po::notify(vm);

            if (vm.count("help")) {
                std::cout << desc << "\n";
            } else {
                std::cout << "Running with param " << param << std::endl;
                //return 0;
            }
        } catch (std::exception const& e) {
            std::cerr << "error: " << e.what() << "\n";
        } catch (...) {
            std::cerr << "Exception of unknown type!\n";
        }
    }
}

印刷

------ "hex2txt.exe"
Running with param 0
------ "hex2txt.exe" "--param" "3"
Running with param 3
------ "hex2txt.exe" "--toto"
error: unrecognised option '--toto'
------ "hex2txt.exe" "foo"
error: too many positional options have been specified on the command line

推荐阅读