【问题标题】:Boost::Program_options, passing an unknown command line argumentBoost::Program_options,传递一个未知的命令行参数
【发布时间】:2013-07-19 09:10:31
【问题描述】:

我正在使用 boost::program_options 为我的程序传递配置文件。特别是我经常使用命令行覆盖一些选项。例如,如果我注册了两个选项“opt1”和“opt2”,我可以通过使用

运行我的程序来成功覆盖默认值
 myProgram.exe --opt1=option_value_1 --opt2=option_value_2

一切都好,但我已经有几次错误地运行我的程序了

 myProgram.exe --opt1=option_value_1 opt2=option_value_2

在这种情况下(缺少双连字符)不会引发错误。事实上,我显然可以将 myProgram 运行为

 myProgram.exe list of any unregistered and unknown values

它仍然可以正常运行。我希望至少能得知发生了一些意想不到的事情。我的问题有解决方案吗?

【问题讨论】:

  • 验证未知的选项值(它们应该出现在输入文件列表中或您从未知参数中获取的任何内容中,例如检查这些文件是否存在)。

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


【解决方案1】:

您应该从 parse 命令中删除 allow_unregistered()。你的命令应该只是

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

那么未知选项会抛出异常。

http://www.boost.org/doc/libs/1_54_0/doc/html/program_options/howto.html#idp123440592

如果你想要异常/错误,如果选项没有“--”你应该编写额外的解析器,像这样,可以帮助你

std::pair<std::string, std::string> fix_option(const std::string& value)
{
   std::string name = value;
   std::string val;
   std::string::size_type pos = name.find("=");
   if (pos != std::string::npos)
   {
      val = name.substr(pos + 1);
      name = name.substr(0, pos);
   }
   if (name.substr(0, 2) != "--")
   {
      throw std::logic_error(std::string("invalid command, no -- in command: ") + name);
   }
   return std::make_pair(name.substr(2), val);
}

code example

结果:

./new --help=j

output: j

./new help=j

output: 
terminate called after throwing an instance of 'std::logic_error'
  what():  invalid command, no -- in command: help

【讨论】:

  • 谢谢,人们会期望 boost 已经提供了一些内部检查。如果您想同时支持单连字符表示法,这种方法将不起作用。无论如何,这很适合我的特殊需求。
  • @pegazik '如果您想同时支持单连字符表示法,这种方法将不起作用。' 为什么?你是如何实施的?通常单连字符表示法是通过附加的单字符快捷方式实现的。
【解决方案2】:

似乎boost::program_options 默认不识别位置参数。这意味着像opt2=option_value_2 这样的非选项参数将被忽略。但是,文档并不清楚。您可以使用basic_command_line_parser::positional() 启用对位置参数的处理。

举例

try {
    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).
                options(desc).positional({}).run(),
              vm);
    po::notify(vm);
} catch (po::too_many_positional_options_error &e) {
    // A positional argument like `opt2=option_value_2` was given
    cerr << e.what() << endl;
    exit(1);
} catch (po::error_with_option_name &e) {
    // Another usage error occurred
    cerr << e.what() << endl;
    exit(1);
}

说明

基本上,

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

已被替换为

po::store(po::command_line_parser(argc, argv)
            .options(desc).positional({}).run(),
          vm);

据我了解文档,parse_command_line(argc, argv, desc)command_line_parser(argc, argv).options(desc).run() 的简写。通过添加对positional() 的调用,我们可以处理位置参数。通过指定{},不允许使用位置参数。当给定的位置参数过多时,会抛出 too_many_positional_options_error 的实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    相关资源
    最近更新 更多