Some experiences in parsing command line parameters

Source: Internet
Author: User

 

Parsing command line parameters seems simple, but there are many minor issues. Here I will record some coding experiences over the past few days and discuss them with you.

First, clarify the requirements.

To parse command line parameters, at least input and output must be included.

There are several input types:

1. A long string of Parameter options and expressions following the executable file

2. Configuration File

3. Standard input, which can be redirected by the output of other programs through pipelines.

Output:

This is relatively simple, either screen or file.

It seems that the input is troublesome. Analyze the input. The above three input methods can be controlled by Parameter options, so how to resolve Parameter options and expressions is further categorized.

I chose the boost: program_options and boost: property_tree libraries for help.

The two are designed to be completely different. program_options is mainly used for parse entry parameters. Its storage medium is variable_map, which is an inherited version of std: map. Essentially, it is also a key-value ordered pair. Obviously, the hierarchy of variable_map has only one layer.

Property_tree is designed to store hierarchical data, so there is a path in it, but I think it is strange, why does program_options not use property_tree as the storage medium?

With the ability of property_tree to parse xml, json, ini, and info, program_options can easily store and read configuration files.

So I decided to combine the two.

First, design a base class:

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_line _line (){}

12 protected:

13 /**

14 * This function init the data _, which needs to be rewrote, it should des 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 abve are pair format <long term, short term>, <description, handler>

18*4. The handler uses boost: function, which shocould 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 <void (const std: string &)> fPtr;

30 vector <tuple <string, fPtr> data _;

31 static const char * style _ [];

32 options_description opts;

33 };

 

Parser is an external interface that parses command line parameters. init_option_data and special_parser are left to the user for implementation. It is mainly used to initialize some built-in options and parse specific expressions. There are usually some specific operations for each option, so I am using the boost: function library, which can easily bind functions and pass variables. However, there are also some drawbacks. One problem caused by the use of boost: function is that I cannot create an ordered pair like <key, function> in map, because map is essentially a single-source container, it cannot store different types of data. (See the http://stackoverflow.com/questions/646737/map-of-boost-function-of-different-types) So I can only change tuple, which is also a library in boost, a bit like a fan pair, can accommodate more elements than pair.

With these definitions, it is easy to implement parser below. There is also a defect in program-option, that is, if an exception is thrown when the input is a defined option, this is often not what the user wants. A better way is to give a prompt, this is what line 21-27 does.

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

2 {

3 init_option_data ();

4

5 typedef vector <tuple <string, fPtr >:: 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 special_parser (argc, argv, style _);

19

20 variables_map vm;

21 BOOST_AUTO (pr, command_line_parser (argc, argv). options (opts). allow_unregistered (). run ());

22 vector <string> ur_opts = collect_unrecognized (pr. options, include_positional );

23 BOOST_FOREACH (string str, ur_opts)

24 {

25 if (str. find (style _ [1]) = std: string: npos)

26 std: cerr <"Unknown option:" <str <std: endl;

27}

28 store (pr, vm );

29 notify (vm );

30

31 if (vm. size () = 0 & argc = 1)

32 {

33 std: cout <opts <std: endl;

34 return;

35}

36

37 for (vci it = data _. begin (); it! = Data _. end (); ++ it)

38 {

39 const std: string & key = it-> get <0> ();

40 if (vm. count (key. c_str ()))

41 it-> get <3> () (key );

42}

43

44}

 

After inheriting this base class, you can add options, descriptions, and corresponding processing functions.

Wait, are you aware of the problem? Yes, you cannot implement functions like-L./xxx. so according to my writing. I did not provide a parameter followed by an input. The main reason is that such an example is not intuitive and I prefer L = xx. so, so I provide the special_parser function, and you can easily extend it to the style you want.

Of course, the current function is still very simple. For example, because my handler calls this function, if your options have dependencies, you should be very careful when adding them.

For the time being, there must be many things you cannot understand. Please give me more advice.

Xiangren caotang

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.