<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      閑人草堂

        博客園  :: 首頁  :: 新隨筆  :: 聯系 :: 訂閱 訂閱  :: 管理

      解析命令行參數,這個看起來很簡單,但是其中有不少小問題,在這里我先記錄下這幾天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 <long term, short term>, <description, handler>
      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<void(const std::string&)> fPtr;
      30 vector<tuple<string,string,string,fPtr> > data_;
      31 static const char * style_[];
      32 options_description opts;
      33 };



        parser是對外的接口,負責解析命令行參數,init_option_dataspecial_parser 留給用戶實現,主要是用來初始化一些內建的選項,和對特定形式的表達式進行解析。往往得針對每個選項,都會有些特定的操作,所以我在此使用了boost::function庫,它可以很方便的綁定函數,傳遞變量。但是有利也有弊端,使用boost::function帶來的一個問題是,我無法在map中建立<key,function>這樣的有序對,因為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<tuple<string,string,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 }


      用戶可以繼承這個基類后,添加選項,描述,想對應的處理函數等等。

      等等,你是不是發現啥問題了,對,按照我這樣的寫法,你是無法實現 -L./xxx.so這樣的功能的。我并沒有提供一個參數后跟一個輸入的形式,主要原因是我覺得這樣的例子并不直觀,我更傾向于L=xx.so這樣的表達式,所以我提供了special_parser這個函數,你可以很方便的擴展成你想要的style。

      當然現在的這個功能還是很單一的,比如因為我的handler是以此調用,所以假如你的選項之間有依賴關系的話,在添加時就得格外小心了。

      暫時就這些,肯定還有很多理解不到的地方,請大家多多指教阿。

      posted on 2011-10-22 00:24  閑人草堂  閱讀(3302)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 精品免费看国产一区二区| 18岁日韩内射颜射午夜久久成人 | 日本三级香港三级三级人妇久| 好硬好湿好爽再深一点动态图视频| 中文丰满岳乱妇在线观看| 国产女人18毛片水真多1| 亚洲天堂精品一区二区| 亚洲国产一区二区三区亚瑟| 黄色免费在线网址| 国产午夜免费高清久久影院| 国产精品国产三级国产a| 国产毛片精品av一区二区| 少妇办公室好紧好爽再浪一点| 日韩国产成人精品视频| 日韩在线观看 一区二区| 久久er99热精品一区二区| 久久国产乱子精品免费女| 国产视色精品亚洲一区二区| 国产在线观看免费观看| 亚洲av日韩av综合在线观看| 国产精品天天看天天狠| 久久国产乱子精品免费女| 免费观看一级欧美大| 免费国产一区二区不卡| 精品国产成人一区二区| 中文字幕乱妇无码AV在线| 国产女人喷潮视频在线观看| 五月丁香六月综合缴清无码| 亚洲国产欧美在线看片一国产| 欧美白妞大战非洲大炮| 久久久久国产一区二区| 久久婷婷成人综合色综合| 亚洲日韩一区二区| 国产精品福利自产拍久久| 挺进粗大尤物人妻中文字幕| 国产欧美精品一区二区三区-老狼 真实单亲乱l仑对白视频 | 人妻无码中文专区久久app| 成人激情视频一区二区三区| 国产精品国产高清国产av| 国产成人精品区一区二区| 久久人人97超碰爱香蕉|