【问题标题】:Disallow negative argument for unsigned value with boost::program_options使用 boost::program_options 禁止无符号值的负参数
【发布时间】:2016-04-22 18:06:01
【问题描述】:

假设我有一个程序使用 boost::program_options 来解析命令行参数,并且有一个 unsigned 值:

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

namespace po = boost::program_options;

int main(int argc, char* argv[]) {
    unsigned num;
    po::options_description desc;
    desc.add_options()
        ("num,n", po::value<unsigned>(&num), "Non-negative number");
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
    std::cout << "Number: " << num << '\n';
    return 0;
}

然后,如果我在命令行上传递一个负值,它会接受它并将其包裹起来:

$ ./bponeg -n -1
编号:4294967295

我宁愿负数触发错误(即抛出invalid_option_value),就像我写./bponeg -n abc一样。 从我自己解析后的代码来看,似乎无法区分用户是写-1还是写4294967295

我可以指示 program_options 解析器拒绝 unsigned 值的负输入吗?

【问题讨论】:

  • 只需读取一个有符号值并检查它是否为负数。我不是使用无符号类型的朋友,但无论如何都是位摆弄。 (Ib4 通常讨厌:标准委员会的几位成员同意我的观点,例如 this panel 9:50, 42:40, 1:02:50)
  • @BaummitAugen 无符号值可能超出有符号范围的情况怎么办?
  • @Revolver_Ocelot 如果您需要额外的位,并且无法选择使用下一个更大的有符号整数,那么您必须做您必须做的事情。到目前为止,我从来没有发生过。 vOv
  • @Revolver_Ocelot 如果它是一个命令行参数,我怀疑用户将输入任何无法解析为long long 的内容。如果是这种情况,则读取一个字符串,然后进行内部解析。
  • @BaummitAugen:这是个好主意。你不妨把它作为一个答案。它为我创建的唯一问题是额外的“有符号和无符号整数表达式之间的比较”警告,我必须解决这些问题。

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


【解决方案1】:

可以写一个custom validator,类似于:

struct nonnegative {
    unsigned value;
};

void validate(boost::any& v, const std::vector<std::string>& values, nonnegative*, int)
{
    using namespace boost::program_options;
    validators::check_first_occurrence(v);

    std::string const& s = validators::get_single_string(values);
    if (s[0] == '-') {
        throw validation_error(validation_error::invalid_option_value);
    }

    v = lexical_cast<unsigned>(s);
}

然后只需使用nonnegative 而不是unsigned

但我认为使用int64_t 并在为负数时抛出错误会更容易。代码也更少。

【讨论】:

    猜你喜欢
    • 2019-04-22
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多