程式執行參數處理函式庫:Boost Program Options(1/N)

一般程式寫得大一點、或是需要比較有彈性,通常都需要在程式執行的時候,從外部讀取一些參數,來做為內部的設定值。一般來說,比較常見的方法,大概就是直接透過命令提示字元(command line)來下參數,或是透過讀取設定檔(例如 ini 檔)來讀取設定值。

以前者來說,雖然 C++ 的主函式、main() 本來就有 argc 和 argv 兩個參數,可以用來處理命令提示字元輸入的參數,但是實際上要去自己根據需求,一個一個來處理,其實當參數多的時候,還是滿麻的。而 Boost C++ Libraries 所提供的 program options 這個函式庫(官方文件),基本上就是一個可以用更結構化、更有系統地來處理這些參數的函式庫。

要使用 Boost Program Options 時,需要 include 他的 header 檔:

#include <boost/program_options.hpp>

而所有的相關函式、物件,也都在 boost::program_options 這個 namespace 下。他基本的使用,大致上就是:

#include <iostream>
#include <string>
using namespace std;
#include <boost/program_options.hpp> namespace BPO = boost::program_options;
int main( int argc, char** argv )
{
int iValInt;
// setup program options description BPO::options_description bOptions( "Test Options" ); bOptions.add_options() ( "help", "Produce help message" ) ( "vint", BPO::value<int>(), "int value" );
// parse program options BPO::variables_map mVMap; BPO::store( BPO::parse_command_line( argc, argv, bOptions ), mVMap ); BPO::notify( mVMap );
// output help message if required if( mVMap.count( "help" ) ) { cout << bOptions << endl; return 1; } // process other option if( mVMap.count( "vint" ) ) { iValInt = mVMap["vint"].as<int>(); cout << "Int: " << iValInt << endl; }
}

在這個範例程式,執行時可以接受「--help」、「--vint」這兩個參數,其中,「--vint」後面需要給一個整數值;下面就是一個執行的範例:

C:\test.exe --vint 10
Int: 10

而「--help」則會把 Boost Program Options 產生的參數說明列印出來,下面就是執行 test.exe --help後所輸出的說明:

Test Options:
--help Produce help message
--vint arg int value

接下來,來看程式碼的部分。

在上面的程式碼裡,可以看到有四個區段有加上底色強化。其中最前面的黃底的部分,算是使用 Boost Program Options 的前置步驟,基本上就是 include 必要的 header 檔、boost/program_options.hpp 這個檔案。

不過,由於他的相關功能都在 boost::program_options 這個很長的 namespace 下,所以為了簡化之後的程式,所以這邊是透過 namespace alias 的方法(MSDN),把它簡化成 BPO;如果完全不想加 namespace 的話,也可以使用「using namespace boost::program_options;」來做處理。

而接下來三個區段,則是 Boost Program Options 在使用上的三個主要步驟:

  1. 設定選項的描述(options decription)、定義有哪些參數
  2. 根據來源(這邊是根據 command line 的參數,argc 和 argv)來做分析,並把分析結果儲存在 map 裡
  3. 處理分析完成、儲存在 map 裡的資料

下面就大概來說明一下這幾的部分:


設定選項的描述

Boost Program Options 用來定義有哪些參數,主要是 options_description 這個類別(官方文件)。

options_description 的物件可以透過 ostream 做輸出,他會把設定好的選項描述、做適當的排版後輸出,這也是使用 Boost Program Options 的一大好處!也因此,在建立 options_description 的物件的時候(這邊是 bOptions),有需要的話可以加上一個字串,作為這個選項描述的最基本的說明,在這邊 Heresy 是給他「Test Options」。

而要加入新的選項定義的時候,基本上是使用 add_options() 這個函式、產生一個options_description_easy_init 的 callable object(官方文件),它的目的就是用來快速地設定參數的描述用的;透過這個物件,可以透過類似呼叫函式的方法(operator()),來做快速的處理。

在這邊的範例裡,Heresy 是在呼叫 add_options() 後,用了兩行、以兩種不同的設定方法,加入了兩個選項定義,分別是 help 以及 vint;不過要注意的是,這其實算是同一行指令,中間都沒有結束的分號(;),是等到所有參數定義都設定完,才算完成整的指令的。

bOptions.add_options()
( "help", "Produce help message" )
( "vint", BPO::value<int>(), "int value" );

首先,help 這個選項的部分,可以看到很簡單,就是兩個字串;第一個字串就是選項的名字、也就是下命令的時候,要給的字串(前面要加上「--」);而第二個字串,則就是這個參數的說明,他會在把 options_description 輸出時,作為選項的說明文字來顯示,所以如果要讓使用者了解這個參數的意義、使用方法的話,就需要在這邊做說明。

而第二個 vint 的選設定項,可以看到和 help 相比,中間多了一個「BPO::value<int>()」,value<>() 這個 template function 是用來指定 --vint 這個選項所需要的值的型別,在這邊是指定為 int,也就是說 --vint 後面要跟著指定一個整數的值。而指定的方法,可以空一個空白後,直接給值,也可以用「=」來做指定;也就是下面兩種方法,都是可以的:

--vint 10
--vint=10

不過要注意的是,如果給的值的形式不對(例如給他一個字串)、或是沒有給值的話,Boost Program Options 是會丟出 exception,在沒有特別處理的情況下,是會讓程式執行錯誤的。

這邊基本上算是寫了兩種不同的選項的設定方法。而實際上,如果有使用 value<> 來做型別的指定的話,其實是還有更多、更方便的功能的!不過這部分就等下一篇文章再寫吧~


分析、儲存選項

在設定完所有的選項的描述後,接下來就是要根據參數的來源,來進行分析了~這段程式碼如下:

BPO::variables_map mVMap;
BPO::store( BPO::parse_command_line( argc, argv, bOptions ), mVMap );
BPO::notify( mVMap );

Boost Program Options 有提供幾種不同的解析器(parser),可以根據不同的資料來源,進行分析;而在這邊 Heresy 所使用的,是 command line 的參數,所以就先使用最簡單的,parse_command_line() 這個函式了。它的使用方法很簡單,只要把 main() 的 argc 和 argv,以及前面所定義好的選項描述、bOptions 當作引數傳給這個函式就可以了~而分析完成後,他會回傳一個型別是 basic_parsed_options 的物件,裡面就是分析完後的結果。

不過在這邊,並不是要直接去使用這個物件,而是要先透過 store() 這個函式,把分析完的結果,儲存到型別為 variables_map 的物件(mVMap),然後再來做操作。

最後,則要記得再透過 notify() 這個函式,來讓 mVMap 裡的選項做最後的處理。


處理分析完成資料

當分析完成後,解下來就是要處理這些分析好的結果了。而這邊用來存取的,都是前面處理好的、型別為 variables_map 的物件(mVMap)(官方文件)。他基本上是繼承自 STL map 的一個類別,所以架構上就是一個 key、對應到一個 value 的形式,而本來 std::map 有的功能,他也都可以使用。

而一般的使用的話,基本上都是先透過 count() 這個函式,來確認這個選項的值是否存在;以上面的範例裡的 help 來說,就是下面的寫法:

if( mVMap.count( "help" ) )
{
cout << bOptions << endl;
return 1;
}

這樣的寫法,實際上就是去判斷,當 mVMap 裡面 help 這個 key 的數量不等於 0 的時候(也就是至少有一個),就去把 bOptions 透過 cout 輸出,顯示使用說明給使用者看。

而如果是要取得值呢?則可以看 vint 的部分:

if( mVMap.count( "vint" ) )
{
iValInt = mVMap["vint"].as<int>();
cout << "Int: " << iValInt << endl;
}

一樣,先透過 count() 來確認有指定 vint 這個選項的值,然後再透過 operator[] 來把它拿出來;不過取出來的物件是一種型別是 variable_value 的物件(官方文件),所以還需要透過 as<> 這個 template 函式,來把它做轉換成我們需要的型別來使用,像這邊因為是整數,所以就是 as<int>()了~


Boost Program Options 的基本使用大概就先到這裡了。實際上,他還有很多更方便的功能可以用的!像是每個選項實際上都可以設定成允許多次設定、甚至有預設值,而選項的描述也可以用分類來處理…不過礙於篇幅問題,就拆到之後再寫吧~

原帖:http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=361

boost:库program_options--第一篇的更多相关文章

  1. boost库中的 program_options

    1.阅读rviz中的源码时在rviz/visualizer_app.cpp中遇到如下代码: po::options_description options; options.add_options() ...

  2. android调用第三方库——第一篇 (转载)

    转自:http://blog.csdn.net/jiuyueguang/article/details/9447245 版权声明:本文为博主原创文章,未经博主允许不得转载. 0:前言: 这两天一直在研 ...

  3. Boost库学习之旅入门篇

    学习及使用Boost库已经有一段时间了,Boost为我的日常开发中带来了极大的方便,也使得我越来越依赖于boost库了.但boost功能太多,每次使用还是得翻看以前的 资料,所以为了以后可以更方便的使 ...

  4. boost库的配置——Linux篇

    Boost库分为两个部分来使用,一是直接使用对应的头文件,二是需要编译安装相应的库才可以使用. 下面是boost在Linux上安装和使用过程(整个boost库全部安装): (1)在www.boost. ...

  5. C++ | boost库 类的序列化

    是的,这是今年的情人节,一篇还在研究怎么用的文章,文结的时候应该就用成功了. 恩,要有信心 神奇的分割线 不知何时装过boost库的header-only库, 所以ratslam中的boost是可以编 ...

  6. boost库在windows下的编译和使用

    因为跨平台的原因,现在要使用到boost库,boost库非常大,现在处于摸索阶段. 首先来说boost库在window下的安装和使用. 一.下载 首先从boost官方主页http://www.boos ...

  7. windows下编译和安装boost库

    boost是一个功能强大.构造精巧.跨平台.开源并且完全免费的C++程序库. 获取方式 boost提供源码形式的安装包,可以从boost官方网站下载,目前最新版本是1.59.0. 本机上正好有boos ...

  8. Boost库安装理解

    Boost安装的安装,以及在VS2013下的使用 1. 为什么要安装? boost是一个开源库,因为开源库可以跨平台,可以通过在不同的“硬件”平台上.所以需要安装的操作. 安装,然后编译生成“静态链接 ...

  9. C++ Boost库的编译及使用

    https://www.jianshu.com/p/de1fda741beb https://www.cnblogs.com/weizhixiang/p/5804778.html Windows编译 ...

随机推荐

  1. MBProgressHUD简单使用

    使用HUD最多的情形用于请求等待提示 例如做登录的时候在确认登陆的时候可以用HUD提示正在登陆. 最基本的使用 初始化 //self.view代表在哪个view中显示hud MBProgressHUD ...

  2. Error D8016 '/ZI' and '/Gy-' command-line options are incompatible

    使用vs运行工程时出现错误: Severity Code Description Project File Line Suppression StateError D8016 '/ZI' and '/ ...

  3. scanf 与 cin 的区别

    在论坛上看到有人提出一个如下的问题,在此总结一下. 原问题: http://topic.csdn.net/u/20110414/22/90d0606c-9876-48e4-9b69-bd8bd8a41 ...

  4. 解读Google分布式锁服务

    解读Google分布式锁服务  背景介绍 在2010年4月,Google的网页索引更新实现了实时更新,在今年的OSDI大会上,Google首次公布了有关这一技术的论文. 在此之前,Google的索引更 ...

  5. 深入探究VC —— 编译器cl.exe(2)

    这一章节介绍的全是VC编译器选项,option参数是cl.exe的编译选项,是cl.exe命令行参数中最复杂.也是最常用的.下面介绍一些常用的编译选项: 1.代码生成有关 这些选项将影响编译完成后生成 ...

  6. notify()、notifyAll()和wait()

    看到一道面试题,写一个多线程程序,交替输出1.2.1.2…… 先写下程序: /** * Created by Andrew on 2015/10/28. */ public class OutputT ...

  7. 解题报告 HDU1159 Common Subsequence

    Common Subsequence Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  8. 键盘过滤第一个例子ctrl2cap(4.1~4.4)汇总,测试

    键盘过滤第一个例子ctrl2cap(4.1~4.4)汇总,测试 完整源代码 /// /// @file ctrl2cap.c /// @author wowocock /// @date 2009-1 ...

  9. php 学习笔记 数组3

    15.使用数组 1).并集(union)  array_merge(array1,array2,array3..) 函数把两个或多个数组合并为一个数组,后面覆盖前面 2). 交集(intersecti ...

  10. ZOJ 2968 Difference Game 【贪心 + 二分】

    题意: 有Ga.Gb两堆数字,初始时两堆数量相同.从一一堆中移一一个数字到另一一堆的花费定义为两堆之间数 量差的绝对值,初始时共有钱C.求移动后Ga的最小小值减Gb的最大大值可能的最大大值. 思路: ...