设为首页 加入收藏

TOP

命令行参数解析的一些心得 (一)
2014-11-23 23:30:09 来源: 作者: 【 】 浏览:1
Tags:命令 参数 解析 一些 心得

解析命令行参数,这个看起来很简单,但是其中有不少小问题,在这里我先记录下这几天coding的一些心得体会,和大家共同探讨一下。

首先明确需求。

要解析命令行参数,最起码得有输入输出吧。

输入一般有这么几种:

1.跟在可执行文件后的一长串参数选项,表达式

2.配置文件

3.标准输入,这个可以由其他程序的输出通过管道重定向而来。

输出:

这个就比较单一了,要么屏幕,要么文件。

看起来输入比较麻烦,那就主要分析一下输入吧。上面这三种输入方式其实都可以通过参数选项进行控制,所以进而归类到如何解析参数选项和表达式呢。

我选用了boost::program_options和boost::property_tree两个库来帮忙。

这两者的设计目的截然不同,program_options主要是用来parse入口参数,它的存储介质是variable_map,这是个std::map的继承版本。本质上也是键值有序对,所以很显然,variable_map的层次结构只有一层。

而property_tree的设计目的是用来存储层次结构的数据,所以里面有路径这一说法,但是我觉得很奇怪,为啥program_options不使用property_tree作为存储介质呢?

借助property_tree解析xml,json,ini,info的能力,program_options可以很方便的存储和读取配置文件啊。

所以我决定把两者拼起来。

首先设计一个基类:

1 class parser_cmd_line

2 {

3 public:

4 /**

5 * Parse the main parameters. It depends on the init_option_data and special_parser function \n

6 *

7 * @param argc arguments number from

8 * @param argv arguments from main

9 */

10 void parser(int argc, char *argv[]);

11 virtual ~parser_cmd_line(){}

12 protected:

13 /**

14 * This function init the data_, which needs to be rewrote, it includes sereral steps: \n

15 * 1. Add option term with long and short term. \n

16 * 2. Add option description and option handler. \n

17 * 3. Both terms above are pair format ,

18 * 4. The handler uses boost::function, which should bind to the function you need.

19 */

20 virtual void init_option_data(){}

21 /**

22 * Add a user designed parser, you can parse some special style input as the "style_" offered.

23 * It also needs to be rewrote.

24 * @param argc

25 * @param argv

26 */

27 virtual void special_parser(int argc, char *argv[], const char * style[] = style_){}

28

29 typedef function fPtr;

30 vector > data_;

31 static const char * style_[];

32 options_description opts;

33 };

  parser是对外的接口,负责解析命令行参数,init_option_data和special_parser 留给用户实现,主要是用来初始化一些内建的选项,和对特定形式的表达式进行解析。往往得针对每个选项,都会有些特定的操作,所以我在此使用了boost::function库,它可以很方便的绑定函数,传递变量。但是有利也有弊端,使用boost::function带来的一个问题是,我无法在map中建立这样的有序对,因为map本质上是一个同源容器,它无法存储不同类型的数据。(参见http://stackoverflow.com/questions/646737/map-of-boost-function-of-different-types)所以我只能换tuple了,这也是boost中的一个库,有点类似范化的pair,可以比pair容纳更多元素。

有了这些定义,下面实现parser就变得很简单了。program-option还有个缺陷,即假如输入为定义的选项时会丢出一个异常,其实这往往不是用户想要的,比较好的方式是给出一个提示,这就是第21-27行干的事。

1 void parser_cmd_line::parser(int argc, char * argv[])

2 {

3 init_option_data();

4

5 typedef vector >::const_iterator vci;

6 for(vci it = data_.begin(); it != data_.end(); ++it)

7 {

8 std::string option_name = it->get<0>();

9 if(!it->get<1>().empty())

10 {

11 option_name += ",";

12 option_name += it->get<1>();

13 }

14 const string &desc = it->get<2>();

15 opts.add_options()(option_name.c_str(), desc.c_str());

16 }

17

18 specia

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇计算质数 下一篇一步一步写算法(之快速排序)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: