在 Boost Program Options 中,如何判断是否指定了默认选项?

问题描述

我正在编写一个程序,它需要一个大小、一个冗余和一些明文,然后输出明文的代码。我希望用于编码的大小和冗余按如下方式计算:

  • 如果既未指定大小也未指定冗余,则冗余为 3/7,大小为所需大小。
  • 如果指定了大小但未指定冗余,则大小是指定的大小,冗余是将明文拟合为指定大小的结果。如果明文小于适合该大小的 1/3,则是错误的,因为最大冗余为 2/3(2/3 和 3/7 来自汉明码)。如果明文太大,那也是一个错误
  • 如果指定了冗余但未指定大小,则大小与需要的一样大。
  • 如果两者都指定,则结果未定义。它可以与最后指定的任何一个一起使用,也可以任意选择一个

代码https://github.com/phma/propolis;这是相关部分:

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

using namespace std;
namespace po=boost::program_options;

int lastSizeRed=0;

void onSize(int size)
{
  lastSizeRed='s';
}

void onRed(string red)
{
  lastSizeRed='r';
}

int main(int argc,char **argv)
{
  int testflag=0,option_index=0,makedata=0;
  bool geneletters=false;
  int c,quality;
  double redundancy=0;
  int size=0;
  string text,infilename,outfilename;
  stringbuf filebuf;
  string redundancyStr,formatStr,patternStr;
  fstream infile;
  int format=FMT_PS,pattern=0;
  bool validCmd=true,helpFlag=false;
  po::options_description generic("Options");
  po::options_description hidden("Hidden options");
  po::options_description cmdline_options;
  po::positional_options_description p;
  po::variables_map vm;
  generic.add_options()
    ("size,s",po::value<int>(&size)->notifier(onSize),"Symbol size")
    ("redundancy,r",po::value<string>(&redundancyStr)->default_value("3/7")->notifier(onRed),"Redundancy (0,2/3]")
    ("text,t",po::value<string>(&text),"Text to encode")
    ("input,i",po::value<string>(&infilename),"File containing text to encode")
    ("output,o",po::value<string>(&outfilename),"Output file")
    ("format,f",po::value<string>(&formatStr)->default_value("ps"),"Output format")
    ("quality",po::value<int>(&quality)->default_value(1),"Quality of raster image (0-10)")
    ("pattern",po::value<string>(&patternStr),"Write a test pattern")
    ("writetables","Write decoding tables")
    ("geneletters","Optimize letters with genetic algorithm")
    ("test","Run tests")
    ("help","Show options");
  initialize();
  cmdline_options.add(generic).add(hidden);
  debugletters=0;
  try
  {
    po::store(po::command_line_parser(argc,argv).options(cmdline_options).positional(p).run(),vm);
    po::notify(vm);
    if (vm.count("test"))
      testflag=1;
    if (vm.count("writetables"))
      makedata=1;
    if (vm.count("geneletters"))
      geneletters=true;
    if (vm.count("help"))
      cout<<"Usage: propolis [options]\n"<<generic;
    cout<<"count(size)="<<vm.count("size")<<" count(redundancy)="<<vm.count("redundancy")<<" lastSizeRed="<<lastSizeRed<<endl;
  }
  catch (exception &ex)
  {
    cerr<<ex.what()<<endl;
    validCmd=false;
  }
  if (redundancyStr.length())
  {
    redundancy=parse_redundancy(redundancyStr);
    if (redundancy>0 && vm.count("redundancy"))
      size=0;
    else
    {
      cerr<<"Could not parse redundancy: "<<redundancyStr<<endl;
      validCmd=false;
    }
  }
  if (formatStr.length())
  {
    format=formatnum(formatStr);
    if (format<0)
      validCmd=false;
  }
  if (patternStr.length())
  {
    pattern=patternnum(patternStr);
    if (format<0)
      validCmd=false;
  }
}

我在“大小”和“冗余”上尝试了 vm.count;无论是否指定,它都会为“冗余”返回 1。我尝试在两个选项中添加 notifier;它总是通知冗余,即使在大小之后指定它也先通知冗余(./propolis -s 4 -r 1/2lastSizeRed 设置为 's')。

解决方法

解决方案是使用 extra parser 而不是通知程序。如果未在命令行指定值,则使用默认值调用通知程序;仅使用命令行选项调用额外的解析器。

pair<string,string> checkSizeRed(const string &s)
{
  if (s.find("-s")==0 || s.find("--size")==0)
    lastSizeRed='s';
  if (s.find("-r")==0 || s.find("--red")==0)
    lastSizeRed='r';
  return make_pair(string(),string());
}
    po::store(po::command_line_parser(argc,argv).options(cmdline_options)
          .extra_parser(checkSizeRed).positional(p).run(),vm);

如果最后指定了 lastSizeRed,则将 --size 设置为 's',如果最后指定 --redundancy,则设置为 'r',如果都没有指定,则设置为 0。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...