I'm trying to get the following syntax parsed with boost::program_options:
a)
$ a.out
verbosity: 0
b)
$ a.out -v
verbosity: 1
c)
$ a.out -v -v
verbosity: 2
d)
$ a.out -vv
verbosity: 2
e) (optional)
$ a.out -v3
verbosity: 3
My program so far:
#include <iostream>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
int main(int argc, char *argv[])
{
po::options_description desc;
desc.add_options()
("verbose,v", po::value<int>(), "verbose");
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
po::notify(vm);
std::cout << "verbosity: " << vm["verbose"].as<int>() << std::endl;
return 0;
}
This works only for e). If I change it to:
po::value<int>()->default_value(0)
it works for a) and e). With
po::value<int>()->default_value(0)->implicit_value(1)
it works for a), b) and e).
How can I get it to parse all of the above cases?
I think I need some combination of a vector of values with zero_tokens(), but I can't seem to get it to work.
to get the number of -v arguments use vm["verbose"].count. of course this will lead to some strange results when combinded with the vm["verbose"].as<>() method.
to really do what you want you will probably have to write your own parsing method for that option. the function would look something like:
std::pair<std::string, std::string> verbosity_count(const std::string& s)
{
if(s.find("-v") || s.find("--verbose"))
{
// process the verbosity count (this will require a static verbosity count var)
return std::make_pair("-v", value as string);
}
else
{
return std::make_pair(std::string(), std::string());
}
return std::make_pair(std::string(), std::string());
}
you would attach this to the command line parser via the extra_parser() method (see boost Program Option docs for exact details, its long and messy).
While it's not beautiful this solves my original question:
#include <iostream>
#include <vector>
#include <string>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
std::pair<std::string, std::string> verbosity(const std::string& s)
{
if(s.find("-v") == 0)
{
size_t value = 1;
try {
value = boost::lexical_cast<size_t>(s.substr(2));
}
catch(...)
{
while(s[1+value] == 'v')
++value;
}
return std::make_pair("verbose", boost::lexical_cast<std::string>(value));
}
return std::make_pair(std::string(), std::string());
}
int main(int argc, char *argv[])
{
po::options_description desc;
desc.add_options()
("verbose,v", po::value<std::vector<std::string> >(), "verbose");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc, 0, verbosity), vm);
po::notify(vm);
size_t verbosity = 0;
if(vm.count("verbose"))
BOOST_FOREACH(const std::string& s, vm["verbose"].as<std::vector<std::string> >())
verbosity += boost::lexical_cast<int>(s);
std::cout << "verbosity: " << verbosity << std::endl;
return 0;
}
精彩评论