我希望收到一个CR,用于以下命令行程序选项的使用boost::program_options初始化。我想知道是否有更好的使用boost::program_options或使用其他可用库/代码的方法:
#include <iostream>
#include <boost/program_options.hpp>
using namespace std;
namespace po = boost::program_options;
int main(int ac, char* av[]) {
/// Command line options initialize
po::options_description visible_desc("Usage: program [options] [path/]logger_filename");
po::options_description full_desc;
po::positional_options_description pd;
bool verbose, anomaly_detection, analyze_activity;
string normal_login_word;
string log_file_path;
string week_start_day;
auto generic_group = po::options_description("Generic options");
generic_group.add_options()
("help,h", "produce help message")
("verbose", po::value<bool>(&verbose)->default_value(false), "Show detailed times of login.")
;
auto calender_group = po::options_description("Calender options");
calender_group.add_options()
("week-start-day,d", po::value<string>(&week_start_day)->default_value("Monday"), "Week starting day ('--week-start-day help' for a list).")
;
auto log_group = po::options_description("Logger options");
log_group.add_options()
;
auto hidden_options_group = po::options_description("Logger options");
hidden_options_group.add_options()
("log-path,l", po::value<string>(&log_file_path)->default_value("/home/sherlock/message_from_computer"), "Path to login/logout logger.")
;
auto anomalies_group = po::options_description("Mode options");
anomalies_group.add_options()
("analyze-log", po::value<bool>(&analyze_activity)->default_value(true), "Analyze activity - show activity times and summarise activity.")
("anomaly-detection", po::value<bool>(&anomaly_detection)->default_value(false), "Check for anomalies in logger.")
("normal-login-word", po::value<string>(&normal_login_word)->default_value("login"), "For anomaly detector- word that should symbol a login line in login/logout logger (after '+' sign).")
;
pd.add("log-path", -1);
visible_desc.add(generic_group).add(calender_group).add(log_group).add(anomalies_group);
full_desc.add(generic_group).add(calender_group).add(log_group).add(anomalies_group).add(hidden_options_group);
/// Command line options applying
po::variables_map vm;
po::store(
po::command_line_parser(ac, av)
.options(full_desc)
.positional(pd)
.run(), vm);
po::notify(vm);
/*
... Analyze options ...
*/
return 0;
}在@pacmaninbw和@alx23zcrs之后,我创建了一个新的更新帖子:V2-在CR之后[命令行中的程序选项初始化]
发布于 2019-10-14 11:37:21
我试过boost::program_options,但只是不喜欢它。
boost::program_options具有这样的特性:某些选项是加性的或隐藏的--这就是为什么它们的使用需要如此多的额外工作(您必须指定所使用的每个选项,并说明它们是如何处理的)。如果没有这些特性,您可以使用配置文件-- *.ini格式 --并简单地读取和存储该文件所具有的所有选项,而不需要整个文件的混乱。实现配置文件读取器并不难,而且Windows还内置了从.ini文件中读取参数的函数。
同样,您可以通过一个.ini文件而不是命令行来提供输入参数,如果您有超过5个参数,而我在测试中往往有几十个参数,这就更方便了。
在我的例子中,我实现了一个类ConfigFile,它基本上包装了一个键以格式部分/名称表示的std::map<string,string>;添加了获取/设置int/double/string值的函数,以及读取整个ini文件的功能。
如果您想通过ConfigFile类读取命令行:您可以重新解释cmd参数并将它们存储在ConfigFile类中。基于字符串的选项可以按原样存储,也可以选择添加前缀部分。为了支持基于索引的选项,您应该提供一个字符串向量来解释它们。
我不知道有任何开源库实现这样的东西,虽然我没有检查任何。但这是很容易实现的自己。我可能会将我的实现与其他一些实用工具特性一起发布为一个开放源码,但现在不行。所以..。
CMD解析示例:
class CConfig
{
public:
// sKeys is used to store index based inputs of CMD
void ParseCMD( int argc,
const char** argv,
std::vector<std::string> sKeys = {});
std::string GetString(std::string key, std::string defaultValue);
double GetDouble(std::string key, double defaultValue);
int GetInt( std::string key, int defaultValue);
void SetString(std::string key, std::string value);
void SetDouble(std::string key, double value);
void SetInt( std::string key, int value);
private:
std::mutex m_mutex;
std::map<std::string, std::string> m_map;
};
void CConfig::ParseCMD( int argc,
const char** argv,
std::vector<std::string> sKeys)
{
std::lock_guard<std::mutex> g(m_mutex);
size_t index = 0;
for (int i = 1; i < argc; i++)
{
if (argv[i][0] != '-')
{
if (sKeys.size() <= index)
{
std::cout "\n[warning]: unassigned input parameters; total number of index-based input parameters is: " << sKeys.size();
continue;
}
m_map[sKeys[index]] = argv[i][0];
continue;
}
if (i + 1 < argc && argv[i + 1][0] != '-')
{
m_map[argv[i]+1] = argv[i + 1];
i++;
}
else
{
// simply defines this key with empty value
m_map[argv[i]+1] = {};
}
}
if (sKeys.size() > index)
{
// or add option for making it into an error and not just a warning print
std::cout << "\n[warning]: not all index-based values were assigned");
}
}
// in main simply write:
int main(int argc, const char* argv[])
{
CConfig config;
config.ParseCMD(argc, argv, {/*list of strings for identification*/});
...
}https://codereview.stackexchange.com/questions/230672
复制相似问题