Boost命令行解釋器的簡單使用:Boost.Program_options


簡介

如果使用比較多的命令行程序的話,對於命令行參數的輸入肯定不會陌生,大部分的程序都是通過類似下面的形式進行輸入的,比如熟悉的ls

ls --all -l --color=auto

這里面包含了三種不同的命令行輸入--all-l--color=auto。如果使用一般的解決方法的話,是使用getopt.h文件中的getopt函數。其具體的教程可以看Linux下getopt()函數的簡單使用,其使用方法比較麻煩。而且只支持一個字符的選項,如果要像--color=auto一樣支持長選項,必須再使用getopt_long函數,而且由於其是對C進行支持的,所以在C++中使用起來也比較麻煩。

而Boost提供的Program_options庫可以很好的解決這一問題。Program_options提供了一個成熟的C++庫來解析命令行參數,幾行簡單清晰的代碼就可以描繪出一個完整的命令行解析器。

而其的使用方法也是非常的簡單,大致可以分為三個部分,構建解析器對象,解析命令行參數,使用結果。

使用的時候需要鏈接boost_program_options庫

沒有參數的選項

一個非常簡單的例子,只定義了一個選項help,運行時會直接先打印獲取到的var_mapname,然后檢查是否存在help選項,如果存在則打印命令行幫助,如果不存在,就直接推出。

#include <boost/program_options.hpp>
#include <iostream>
#include <string>
#include <vector>

int main(int argc, char *argv[]) {
    boost::program_options::options_description desc("測試程序");

    desc.add_options()("help,h", "打印幫助文檔");

    boost::program_options::variables_map var_map;
    boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), var_map);
    boost::program_options::notify(var_map);

    for (auto iter : var_map) {
        std::cout << iter.first << std::endl;
    }


    if (var_map.count("help") > 0) std::cout << desc << std::endl;
    return 0;
}

編譯以后運行./main_simple -h或者./main_simple --help可以得到:

help
測試程序:
  -h [ --help ]         打印幫助文檔

首先是定義了一個boost::program_options::options_description對象,它可以選項列表的描述。它的構造函數可以傳入一個字符串,作為打印時候的抬頭。

然后是向選項列表里面添加選項,最簡單的方法就是使用desc對象里面的add_options方法,它可以返回一個函數對象,借此向選項列表描述添加選項。

目前在這里的選項列表只有簡單的兩個參數,第一個是表明選項的name,你可以通過用分號將長選項和縮寫分割開來,而最終的結果還是以長選項作為name的;第二個是對選項的描述。

然后定義了一個boost::program_options::variables_map對象,它是一個map,key元素為選項的name,value元素為Boost::any對象。

然后開始對命令行輸入進行解析,首先使用boost::program_options::parse_command_line進行解析,然后使用boost::program_options::store將結果保存在var_map變量里面。

boost::program_options::notify將在后面提到。

接下來,就是對map的操作了。而如果想輸出說明的話,也可以很直接的直接對desc進行cout

帶參數的選項

上面我們介紹了不帶參數的簡單使用,但是在很多的時候,我們需要通過命令行輸入一些參數。就如同最上面例子中的--color=auto一樣。Boost提供了非常簡單的方法來實現這一操作。

#include <vector>
#include <string>
#include <iostream>

#include <boost/program_options.hpp>

int main(int argc, char *argv[]) {
    boost::program_options::options_description desc("測試程序");

    desc.add_options()("help,h", "打印幫助文檔");
    desc.add_options()("input,i", boost::program_options::value<std::string>()->default_value("Test")->value_name("string"), "輸入");

    boost::program_options::variables_map var_map;
    boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), var_map);
    boost::program_options::notify(var_map);


    if (var_map.count("help") > 0) std::cout << desc << std::endl;
    if (var_map.count("input") > 0) std::cout << var_map["input"].as<std::string>() << std::endl;
    return 0;
}

在這個程序中,增加了一行

desc.add_options()("input,i", boost::program_options::value<std::string>()->default_value("Test")->value_name("string"), "輸入");

和之前的help選項類似,在這里我們增加了一個input選項,在這個添加過程中,我們向函數對象添加了3個參數,第一個和第三個參數和之前表述的一樣。而第二個參數可以看作是對輸入的描述。

首先我們通過boost::program_options::value構造了一個對象,在構造的過程中,需要向模板傳入一個類型參數,表表明輸入值的類型。然后其會構造出一個boost::program_options::type_value類型,可以通過一些方法對其進行設置。

在這一示例中,用戶可以在input后面輸入一個字符串,同時如果沒有輸入的話,會主動出現一個默認值Test,這個默認值會在沒有輸入的時候作為input項的默認值。

然后可以通過對var_map進行簡單的操作,來獲取輸入的值。

輸入數組

如果一個選項我們需要多次輸入需要如何處理呢?比如exec.bin -i test -i test1

這一個的處理比較簡單,和上面的程序相比,我們只需要將input選項的值修改為std::vector就可以了,即:

C++ desc.add_options()("input,i", boost::program_options::value<std::vector<std::string>>()->value_name("string"), "輸入");

相應的,我們的輸出改為

auto input_s = var_map["input"].as<std::vector<std::string>>();
for (auto inputm : input_s) {
    std::cout << inputm << std::endl;
}

如果想不用重復鍵入-i,而是直接在同一個輸入用空格隔開不同的值,如exec.bin -i test test1,那么可以考慮為屬性增加multitoken

desc.add_options()("input,i", boost::program_options::value<std::vector<std::string>>()->multitoken(), "輸入");

其他雜項

很明顯,Boost.Program_options的操作肯定還不止這一些,但是以上的簡單操作,基本上可以覆蓋大部分的使用場景了。然后還有一些使用的小細節。

報錯

如果輸入的選項中存在描述中沒有的選項的話,就會在解析的時候產生一個異常,可以通過捕捉這一個異常,給程序一個更加合理的表現。

隱藏項

如果想給程序增加一個“后門”,只有你知道的選項,應該如何操作呢?

其實很簡單,建立兩個options_description就好了,一個用來顯示,一個用來解析。這樣就不會在顯示的時候,顯示需要隱藏的項了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM