【问题标题】:How do I detect typo with Boost.program_options?如何使用 Boost.program_options 检测错字?
【发布时间】:2011-10-25 10:57:15
【问题描述】:

我使用 boost.program_options 库。考虑这个简化的案例。

po::options_description desc("Usage");
desc.add_options()
("uninstall,u", "uninstall program")
("custom,c", po::wvalue<std::wstring>(), "specify custom action");

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);

我想在这样的命令行上产生错误:

testprog.exe -u c- action1

注意,用户打错了“c-”而不是“-c”。但是解析器将此理解为单个 -u 选项。我该如何处理这种情况?

【问题讨论】:

    标签: c++ boost boost-program-options


    【解决方案1】:

    我想在这样的命令行上产生错误:

    testprog.exe -u c- action1
    

    注意,用户打错了“c-”而不是“-c”。但是解析器 将此理解为单个 -u 选项。我该如何处理这种情况?

    指示program_options 库不接受任何位置参数,您将获得所需的行为

    代码和编译:

    macmini:stackoverflow samm$ cat po.cc
    #include <boost/program_options.hpp>
    #include <boost/version.hpp>
    
    #include <iostream>
    
    int
    main(int argc, char* argv[])
    {
        namespace po = boost::program_options;
        po::options_description desc("Usage");
        desc.add_options()
            ("uninstall,u", "uninstall program")
            ("custom,c", po::wvalue<std::wstring>(), "specify custom action")
            ;
    
        po::variables_map vm;
        po::command_line_parser cmd_line( argc, argv );
        cmd_line.options( desc );
        cmd_line.positional( po::positional_options_description() );
    
        try {
            po::store( cmd_line.run(), vm );
    
            po::notify(vm);
        } catch ( const std::exception& e ) {
            std::cerr << e.what() << std::endl;
            return -1;
        }
    
        return 0;
    }
    macmini:stackoverflow samm$ g++ po.cc -I /opt/local/include -L/opt/local/lib -lboost_program_options -Wl,-rpath,/opt/local/lib
    

    运行:

    macmini:stackoverflow samm$ ./a.out -u c- action1
    too many positional options
    macmini:stackoverflow samm$ ./a.out -u -c action1
    macmini:stackoverflow samm$ 
    

    【讨论】:

      【解决方案2】:

      argc-1program_options 找到的参数数量进行比较?如果不匹配,则存在语法错误。

      它不会捕获所有情况,但它可能会捕获对您重要的情况。

      【讨论】:

      • 我喜欢这个答案,但如果你提供一些示例代码会更好
      【解决方案3】:

      我认为您可以做到这一点的唯一方法是确保您需要的每个参数都存在,例如通过测试每种类型的计数。

      if (vm.count("uninstall")) { ... }
      if (vm.count("custom")) { ... }
      

      如果您需要的选项不存在(即计数为 0)或存在(例如,无法指定 -u-c 将是两者的计数为 &gt;0),您可能会生成错误。

      【讨论】:

      • -c 选项是可选的。用户可以指定单个 -u 选项或同时指定 -u 和 -c 选项。问题是,如果用户犯了上述错字,库会将命令行视为只有一个参数,并且程序可能会为他或她做一些意想不到的事情。
      • 在这种情况下,您别无选择,只能以某种方式验证参数,因此如果提供了-u,请在采取行动之前检查传入的参数是否与您的要求匹配。 AFAIK,没有其他方法 - 解释用户错误....
      • -u 选项注册为没有值的选项。因此,如果我尝试验证传入的参数,则会引发 boost::bad_any_cast 异常。 std::wstring value = vm["custom"].as<:wstring>();
      • 通常有这样的事情(尤其是听起来像卸载的事情),总是值得与用户仔细检查(“你确定你想卸载吗?”)如果这是一个错误,这允许用户停止操作。对于custom,应捕获验证异常并显示相应的使用消息。这就是我所说的验证用户输入的意思。
      • 我同意你的观点,在继续之前提示用户是值得的。另一方面,-u 和 -u + -c 动作的描述看起来很相似,他/她可能看不出区别。 bad_any_cast 异常也 always 为 -u 选项引发,因为它被注册为没有值的选项。所以我觉得抓住它没有任何意义。
      猜你喜欢
      • 1970-01-01
      • 2013-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-28
      • 1970-01-01
      • 2016-10-26
      • 2019-12-10
      相关资源
      最近更新 更多