Boost Library 프로그램 옵션을 사용하는 필수 및 선택적 인수
Boost Program Options Library를 사용하여 명령 줄 인수를 구문 분석하고 있습니다.
다음과 같은 요구 사항이 있습니다.
- "도움말"이 제공되면 다른 모든 옵션은 선택 사항입니다.
- "도움말"이 제공되지 않으면 다른 모든 옵션이 필요합니다.
어떻게 처리 할 수 있습니까? 이것을 처리하는 내 코드는 다음과 같습니다. 매우 중복 적이며 수행하기 쉬운 것이 있어야한다고 생각합니다.
#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
}
이 문제를 직접 겪었습니다. 솔루션의 핵심은 함수 po::store
가 오류를 발생 시키는 variables_map
동안 채우 po::notify
므로 vm
알림을 보내기 전에 사용할 수 있다는 것입니다.
따라서 Tim 에 따라 원하는대로 각 옵션을 required로 설정하되 po::notify(vm)
도움말 옵션을 처리 한 후에 실행 하십시오. 이렇게하면 예외가 발생하지 않고 종료됩니다. 이제 옵션이 required로 설정된 상태에서 누락 된 옵션으로 인해 required_option
예외가 발생하고 해당 get_option_name
메서드를 사용 하면 오류 코드를 비교적 간단한 catch
블록 으로 줄일 수 있습니다 .
추가로, 옵션 변수는 po::value< -type- >( &var_name )
메커니즘을 통해 직접 설정되므로을 통해 액세스 할 필요가 없습니다 vm["opt_name"].as< -type- >()
.
rcollyer와 Tim에 따른 완전한 프로그램은 다음과 같습니다.
#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: .
*/
옵션이 충분히 쉽게 필요하도록 지정할 수 있습니다. [ 1 ], 예 :
..., value<string>()->required(), ...
but as far as I know there's no way to represent relationships between different options to the program_options library.
One possibility is to parse the command line multiple times with different option sets, then if you've already checked for "help" you can parse again with the three other options all set as required. I'm not sure I'd consider that an improvement over what you have, though.
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;
}
}
'Programing' 카테고리의 다른 글
적절한 Realm 사용 패턴 / 모범 사례? (0) | 2020.10.25 |
---|---|
루프에서 함수 만들기 (0) | 2020.10.24 |
컴파일러 오류 : "초기화 요소가 컴파일 시간 상수가 아닙니다." (0) | 2020.10.24 |
웹 사이트의 한 섹션을 번역하지 않도록 Google 번역에 어떻게 지시 할 수 있습니까? (0) | 2020.10.24 |
이름이 지정되지 않은 또 다른 CacheManager가 동일한 VM (ehCache 2.5)에 이미 있습니다. (0) | 2020.10.24 |