Mandatory and optional arguments using the parameters of the Boost Library program

I use the Boost program parameter library to parse command line arguments.

I have the following requirements:

  • After providing "help", all other options are optional;
  • When "help" is not provided, all other parameters are required.

How can I handle this? Here is my code handling this and I found it very redundant and I think it should be easy to do, right?

#include <boost/program_options.hpp> #include <iostream> #include <sstream> namespace po = boost::program_options; bool process_command_line(int argc, char** argv, std::string& host, std::string& port, std::string& configDir) { int iport; try { po::options_description desc("Program Usage", 1024, 512); desc.add_options() ("help", "produce help message") ("host,h", po::value<std::string>(&host), "set the host server") ("port,p", po::value<int>(&iport), "set the server port") ("config,c", po::value<std::string>(&configDir), "set the config path") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); if (vm.count("help")) { std::cout << desc << "\n"; return false; } // There must be an easy way to handle the relationship between the // option "help" and "host"-"port"-"config" if (vm.count("host")) { std::cout << "host: " << vm["host"].as<std::string>() << "\n"; } else { std::cout << "\"host\" is required!" << "\n"; return false; } if (vm.count("port")) { std::cout << "port: " << vm["port"].as<int>() << "\n"; } else { std::cout << "\"port\" is required!" << "\n"; return false; } if (vm.count("config")) { std::cout << "config: " << vm["config"].as<std::string>() << "\n"; } else { std::cout << "\"config\" is required!" << "\n"; return false; } } catch(std::exception& e) { std::cerr << "Error: " << e.what() << "\n"; return false; } catch(...) { std::cerr << "Unknown error!" << "\n"; return false; } std::stringstream ss; ss << iport; port = ss.str(); return true; } int main(int argc, char** argv) { std::string host; std::string port; std::string configDir; bool result = process_command_line(argc, argv, host, port, configDir); if (!result) return 1; // Do the main routine here } 
+65
c ++ boost required optional boost-program-options
Mar 22 '11 at 17:37
source share
4 answers

I myself ran into this problem. The key to the solution is that the function po::store fills the variables_map , and po::notify causes errors that have occurred, so vm can be used before sending any notifications.

So, according to Tim , set each parameter as needed, but run po::notify(vm) after you consider the help option. Thus, it will be released without any exceptions. Now, with the parameters set, the missing parameter will raise the required_option exception and using its get_option_name method, you can reduce the error code to a relatively simple catch .

As an additional note, your parameter variables are set directly through the mechanism po::value< -type- >( &var_name ) , so you do not need to access them through vm["opt_name"].as< -type- >() .

+81
Apr 01 2018-11-11T00:
source share

Here is the complete program according to rcollyer and Tim, with whom loans come:

 #include <boost/program_options.hpp> #include <iostream> #include <sstream> namespace po = boost::program_options; bool process_command_line(int argc, char** argv, std::string& host, std::string& port, std::string& configDir) { int iport; try { po::options_description desc("Program Usage", 1024, 512); desc.add_options() ("help", "produce help message") ("host,h", po::value<std::string>(&host)->required(), "set the host server") ("port,p", po::value<int>(&iport)->required(), "set the server port") ("config,c", po::value<std::string>(&configDir)->required(), "set the config path") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); if (vm.count("help")) { std::cout << desc << "\n"; return false; } // There must be an easy way to handle the relationship between the // option "help" and "host"-"port"-"config" // Yes, the magic is putting the po::notify after "help" option check po::notify(vm); } catch(std::exception& e) { std::cerr << "Error: " << e.what() << "\n"; return false; } catch(...) { std::cerr << "Unknown error!" << "\n"; return false; } std::stringstream ss; ss << iport; port = ss.str(); return true; } int main(int argc, char** argv) { std::string host; std::string port; std::string configDir; bool result = process_command_line(argc, argv, host, port, configDir); if (!result) return 1; // else std::cout << "host:\t" << host << "\n"; std::cout << "port:\t" << port << "\n"; std::cout << "config:\t" << configDir << "\n"; // Do the main routine here } /* Sample output: C:\Documents and Settings\plee\My Documents\Visual Studio 2010\Projects\VCLearning\Debug>boost.exe --help Program Usage: --help produce help message -h [ --host ] arg set the host server -p [ --port ] arg set the server port -c [ --config ] arg set the config path C:\Documents and Settings\plee\My Documents\Visual Studio 2010\Projects\VCLearning\Debug>boost.exe Error: missing required option config C:\Documents and Settings\plee\My Documents\Visual Studio 2010\Projects\VCLearning\Debug>boost.exe --host localhost Error: missing required option config C:\Documents and Settings\plee\My Documents\Visual Studio 2010\Projects\VCLearning\Debug>boost.exe --config . Error: missing required option host C:\Documents and Settings\plee\My Documents\Visual Studio 2010\Projects\VCLearning\Debug>boost.exe --config . --help Program Usage: --help produce help message -h [ --host ] arg set the host server -p [ --port ] arg set the server port -c [ --config ] arg set the config path C:\Documents and Settings\plee\My Documents\Visual Studio 2010\Projects\VCLearning\Debug>boost.exe --host 127.0.0.1 --port 31528 --config . host: 127.0.0.1 port: 31528 config: . C:\Documents and Settings\plee\My Documents\Visual Studio 2010\Projects\VCLearning\Debug>boost.exe -h 127.0.0.1 -p 31528 -c . host: 127.0.0.1 port: 31528 config: . */ 
+32
Apr 01 2018-11-21T00:
source share

You can indicate that the option is required quite easily [ 1 ], for example:

 ..., value<string>()->required(), ... 

but as far as I know, there is no way to represent the relationship between the various options in the program_options library.

One of the possibilities is to play the command line several times with different sets of parameters, and then, if you have already checked the "help", you can again analyze the other three parameters, which are all set as necessary. I'm not sure I think that there is an improvement over what you have.

+10
Apr 01 '11 at 18:27
source share
  std::string conn_mngr_id; std::string conn_mngr_channel; int32_t priority; int32_t timeout; boost::program_options::options_description p_opts_desc("Program options"); boost::program_options::variables_map p_opts_vm; try { p_opts_desc.add_options() ("help,h", "produce help message") ("id,i", boost::program_options::value<std::string>(&conn_mngr_id)->required(), "Id used to connect to ConnectionManager") ("channel,c", boost::program_options::value<std::string>(&conn_mngr_channel)->required(), "Channel to attach with ConnectionManager") ("priority,p", boost::program_options::value<int>(&priority)->default_value(1), "Channel to attach with ConnectionManager") ("timeout,t", boost::program_options::value<int>(&timeout)->default_value(15000), "Channel to attach with ConnectionManager") ; boost::program_options::store(boost::program_options::parse_command_line(argc, argv, p_opts_desc), p_opts_vm); boost::program_options::notify(p_opts_vm); if (p_opts_vm.count("help")) { std::cout << p_opts_desc << std::endl; return 1; } } catch (const boost::program_options::required_option & e) { if (p_opts_vm.count("help")) { std::cout << p_opts_desc << std::endl; return 1; } else { throw e; } } 
+1
Feb 10 '16 at 19:08
source share



All Articles