首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >命令行初始化的程序选项

命令行初始化的程序选项
EN

Code Review用户
提问于 2019-10-13 23:18:49
回答 1查看 643关注 0票数 3

我希望收到一个CR,用于以下命令行程序选项的使用boost::program_options初始化。我想知道是否有更好的使用boost::program_options或使用其他可用库/代码的方法:

代码语言:javascript
复制
#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之后[命令行中的程序选项初始化]

EN

回答 1

Code Review用户

发布于 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解析示例:

代码语言:javascript
复制
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*/});
         ...
   }
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/230672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档