Boost 库Program Options--第二篇
程式執行參數處理函式庫:Boost Program Options(2/N)
前一篇已經大致解釋了 Boost Program Options 基本上的使用方法。而這一篇,則來細講一下選項描述(options_description)的進一步設定方法吧~ 在上一篇裡,基本上是示範了兩種最簡單的方法: bOptions.add_options() 其中,help 這個選項的設定,就是最單純、沒有任何對應值的選項,只需要加上說明文字就可以了。而如果像 vint 一樣,需要指定型別等進一步的資料的話,則就需要透過 value<>() 這個 template 函式,來產生一個型別為 typed_value<> 的物件,透過他來指定這個選項對應的值的性質。 最簡單的使用方法,就如同上面 vint 的範例一樣,只要指定型別就可以了。不過如果有需要的話,value<>() 這個函式(文件),和他產生的 typed_value<> 這個型別的物件(文件),都還有許多可以做進一步控制的功能~ 直接將值寫入變數像是以目前 vint 的設定來說,我們還需要自己去把他的值讀出來才行,其實算是有點麻煩的。實際上,Boost Program Options 是可以讓他自動把值寫到我們指定的變數裡的~要這樣做的方法也非常簡單,只要把要拿來儲存這個選項的值的變數的指標,當作 value<>() 這個函式的參數傳進去就可以了~ 下面就是一個簡單的範例(註 1): int main( int argc, char** argv ) 如此一來,當分析完輸入的資料後,如果有指定 vint 的值的話,他的值就會直接被寫到 iValInt裡,可以直接拿來用、而不需要再從 mVMap 裡面拿了~對於要使用的選項很多的時候,這樣是可以有效簡化程式碼的~ 相同選項的多個值像上面這樣的設定方法,基本上在命令提示字元時,只能指定一次 --vint 的值,如果超過一次的話,是會產生 exception 的。但是,如果希望可以指定複數個 vint 的值的話,應該要怎麼辦呢?Boost Program Options 也有針對這樣的需求,做額外的設計;最簡單的改法,就是把值的型別,從 int 改成 vector<int> 就可以了~下面就是一個簡單的範例: int main( int argc, char** argv ) 其中,value(&vValInt) 是 value< vector<int> >(&vValInt) 的簡化寫法。 而這樣的程式,就可以接受有多個 --vint 了~下面就是一個簡單的使用範例: C:\>text.exe --vint 1 --vint 2 但是,如果希望可以接受「-vint 1 2」這樣的指令的時候,該怎麼辦呢?這時候,可以透過typed_value<> 的函式、multitoken() 來做設定;他的設定方法如下: bOptions.add_options() 這樣的話,執行「text.exe --vint 1 2」的結果就會和「text.exe --vint 1 --vint 2」一樣了~(註 2) 簡化輸入(縮寫)在上面,選項的名稱在命令提示字元輸入的時候,都必須要加上「--」,而且要把完整的名稱打出來,在要輸入許多參數的時候,還滿麻煩的。而 Boost Program Options 為了可以簡化輸入,也有提供可以簡化的方法。 像上面的範例,可以在選項名稱「vint」後面加上逗號,然後再加上一個字元「I」,變成下面這樣: bOptions.add_options() 如此一來,在命令提示字元指定參數的時候,除了可以使用本來的「--vint」,也可以使用更短的「-I」來做輸入~這樣,就可以簡化輸入時要打的字了;這在要輸入的參數很多的時候,是很好用的。 下面就是一個簡單的使用範例: C:\>test.exe --vint 1 -I 2 -I 3 選項的預設值有的時候,我們會希望某些選項,在使用者沒有指定值的情況下,會有一個預設值,這點在 Boost Program Options 裡面也是可以很簡單做到的~只需要使用 typed_value<> 提供的 default_value()這個函式,來指定預設值就可以了;下面就是簡單的使用範例: int main( int argc, char** argv ) 如此一來,在沒有透過 --vint 指定的值時候,iValInt 就會是 -1 了~ 而另外一種狀況,則是有可能我們會希望可以只給選項、而不給值,這時候,則可以透過implicit_value() 這個函示來做設定。它的使用方法如下: bOptions.add_options() 如此一來,除了可以透過「--vint 10」這樣的參數,把 iValInt 的值設定為 10 之外,也可以只給「--vint」這樣的參數,讓 iValInt 的值變成 1。 而當然,default_value() 和 implicit_value() 也是可以合併使用的!比如說,如果設定成: bOptions.add_options() 在不做特別指定的情況下,iValInt 的值會就會預設值的 0,而如果只有給「--vint」的話,則會是 implicit value 的 1。下面就是這樣的使用範例: C:\>test.exe 在很多時候,這樣的設定方法是相當方便的~ 必要選項如果某個選項,是要求使用者一定要指定的,也可以透過 typed_value<> 的 required() 這個函式,來要求在分析的時候,一定要有這個選項;而如果指定成必要的選項在分析的時候沒有被找到的話,則是會在執行階段丟出一個 exception,沒有特別處理的話,程式是會直接結束的。 下面就是一個簡單的範例: int main( int argc, char** argv ) 這樣一來,在沒有給「--vint」的情況下執行這個程式,就會因為接到 error_with_option_name 這個 exception(註 3),而讓程式結束了~ C:\>test.exe 不過由於個人在使用上是習慣透過「--help」來讓程式輸出選項的描述,所以和這邊這種 required()的使用方法算是有衝突的,所以大概不會用吧… 自訂型別大部分時候,會拿來當作選項的值,所使用的型別都是相對簡單的,一般來說都會 C++ 內建的型別。不過,如果有需要使用自己定義的型別當作選項的值的型別的話,也是沒問題的~唯一的需求,就是必須要針對這個字定義的型別,定義好他的「extraction operator」,也就是 input stream 的 operator>>。(參考) 下面就是一個字定義的 2D 向量結構、SVector 的範例。 struct SVector { int x; int y; };
istream& operator>> (istream& in, SVector& vec ) { in >> skipws >> vec.x >> vec.y; return in; }
int main( int argc, char** argv ) 在這邊,Boost Program Options 在偵測到 --vec 的選項的時候,會透過 input stream 的形式,把輸入的值轉換成指定的型別、也就是 SVector。而下面則是一個簡單的使用範例: C:\>test.exe --vec "3 2" 在這邊給了 --vec "3 2" 這個執行參數後,Boost Program Options 就會自動把 vec 的 x 和 y 的值填進去了~這也算是 C++ iostream 可擴充性的一個很好的利用範例了~ 不過要注意的是,由於 C++ 會用空格把命令提示字元的參數做切割,所以像這邊「"3 2"」因為中間有空白,所以就需要使用「"」來把他包起來,不然是會被視為兩個項目、而造成程式的錯誤的。 Nofitier在 Boost Program Options 的架構裡,在根據 options_description 分析完輸入的來源、把資料寫到 variables_map 後,還需要呼叫 notify() 這個函式、執行「通知」這個動作。而這個通知的動作要做那些事呢?實際上是可以自己定義的;透過 typed_value<> 的 notifier() 這個函式,我們可以指定再呼叫 notify() 的時候,如果這個選項存在、要做那些事。 而使用的方法也很簡單,只要丟一個函式給他就可以了~下面就是一個簡單的範例: void test( const int& rVal ) { cout << "Notified: " << rVal << endl; }
int main( int argc, char** argv ) 這邊就是很簡單,把 test() 這個函式當作參數,傳給 notifier() 就可以了。在這樣設定後,當呼叫BPO::notify( mVMap ) 的時候,如果有偵測到 vint 這個選項的話,他就會呼叫 test() 這個函式,並且把偵測到的值傳進去。 實際上,notifier() 接受的參數是 Boost 裡、型別是 function1<void, const T&> 的 function object(註 4),所以只要是符合形式(沒有回傳值、接受一個 const reference 的值)、可以呼叫的物件,都可以傳進來;像是 C++11 的 lambda expression(參考),也是可以拿來用的~ 如果在程式裡面,針對格別選項的處理流程很複雜的話,使用 Boost Program Options 的 notify 機制,應該也是一個把程式模組成一塊一塊的好方法。 變數名稱實際上,typed_value<> 還有提供一些其他的功能,可以使用。不過有的 Heresy 是先跳過了。而在這篇,最後來講一個主要影響是顯示上的功能,那就是「變數名稱」。 Boost Program Options 在 Heresy 來看,其中一個最重要的好處,就是在完成options_description 的設定的同時,也就把給使用者看得使用說明的資料完成了!比如像下面的設定了一個 options_description: BPO::options_description bOptions( "Test Options" ); 如果我們透過 output stream 把 bOptions 輸出,就可以得到下面的說明: Test Options: 這真的是相當方便的~因為如此一來,就可以避免使用說明和實際參數的不一致了!(分開寫常常會忘了改 :p) 但是,不知道有沒有發現,在上面的說明裡,提示要輸入的變數,都是「arg」,看不出來是怎樣類型的資料,其實算是比較美中不足的地方。 不過實際上,Boost Program Options 也是有針對這個問題做處理的!只要透過 typed_value<> 的value_name() 這個函式,就可以把「arg」這個通用性的字串改掉,改成我們自己要的內容了~比如說,把上面的程式碼改成下面的: bOptions.add_options() 那在輸出的時候,就會變成: Test Options: 可以看到,本來的 arg 就已經變成上面指定的值了~如此一來,在說明的部分,就可以更有效地說明如何使用了。 附註:
|
Boost 库Program Options--第二篇的更多相关文章
- boost库的配置——Linux篇
Boost库分为两个部分来使用,一是直接使用对应的头文件,二是需要编译安装相应的库才可以使用. 下面是boost在Linux上安装和使用过程(整个boost库全部安装): (1)在www.boost. ...
- duilib库分析4.第二篇UIBase
DUiLib 源码分析 ——以UiLib 1.01版为分析目标 ——colin3dmax 分析于2011-6-16 19:44------------------------------------- ...
- boost:库program_options--第一篇
程式執行參數處理函式庫:Boost Program Options(1/N) 一般程式寫得大一點.或是需要比較有彈性,通常都需要在程式執行的時候,從外部讀取一些參數,來做為內部的設定值.一般來說,比較 ...
- [转]Android开源项目第二篇——工具库篇
本文为那些不错的Android开源项目第二篇--开发工具库篇,主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多 ...
- Android开源项目第二篇——工具库篇
本文为那些不错的Android开源项目第二篇——开发工具库篇,**主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容 ...
- [置顶] android利用jni调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so
0:前言 1:本文主要作为丙方android公司的身份来写 2:作者有不对的地方,请指出,谢谢 [第一篇:android利用jni调用第三方库——编写库libhello.so] [第二篇:androi ...
- how to use boost program options
From: http://www.radmangames.com/programming/how-to-use-boost-program_options If it so happens that ...
- android调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so (转载)
转自:http://blog.csdn.net/jiuyueguang/article/details/9449737 版权声明:本文为博主原创文章,未经博主允许不得转载. 0:前言 1:本文主要作为 ...
- Boost库学习之旅入门篇
学习及使用Boost库已经有一段时间了,Boost为我的日常开发中带来了极大的方便,也使得我越来越依赖于boost库了.但boost功能太多,每次使用还是得翻看以前的 资料,所以为了以后可以更方便的使 ...
随机推荐
- 使用OFFSET-FETCH进行数据过滤
TOP的工业标准版 OFFSET-FETCH OFFSET 用来设置跳过行的数量 FETCH 用来设置检索多少行,必须要排序才能用,SQL Server 2012的新语法 从语意的角度来讲如果要跳开几 ...
- STL之map和multimap(关联容器)
map是一类关联式容器.它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响.自动建立Key - value的对应,对于迭代器来说,可以修改实值,而不能修改key. ...
- MongoDB shell常用命令
Shell操作数据库: 1. 超级用户相关: 1. #进入数据库admin use admin 2. #增加或修改用户密码 db.addUser('name','pwd') 3. #查看用户列表 d ...
- linux shell awk 流程控制语句(if,for,while,do)详细介绍
在linux awk的 while.do-while和for语句中允许使用break,continue语句来控制流程走向,也允许使用exit这样的语句来退出.break中断当前正在执行的循环并跳到循环 ...
- 转: seajs手册与文档之 -- require规则
require 规则 正确拼写 不要修改 使用直接量 动态依赖的小提示 书写规则 使用 SeaJS 书写模块代码时,需要遵循一些简单规则: 1. 正确拼写 在模块代码中,第一个参数 必须 命名为 re ...
- hibernate 缓存 4.3
缓存在hibernate中是天生就有的,是一级缓存,当session关闭时一级缓存就失效了 一级缓存是内置的,生效范围是在同一个session中才行.二级缓存是需要配置才有 判断当前项在不在一级缓存中 ...
- (step6.3.5)hdu 1281(棋盘游戏——二分图的完美匹配)
题目大意:本体是中文题.读者可以直接在OJ上看 解题思路: 1)完美匹配:所有的端点都是匹配点 2)对于二分图的完美匹配,我们需要用一个数组来存储匹配点.(而二分图的其他问题(我们则可以直接使用变量来 ...
- 【Cocos2d-X开发学习笔记】第03期:渲染框架之导演类(CCDirector)的使用
本系列学习教程使用的是cocos2d-x-2.1.4版本(截至目前为止最新稳定版) ,PC开发环境Windows7,C++开发环境VS2010 提到“导演”一词,想必读者最先联想到的是电影.作为娱乐产 ...
- eclipse config 3 构造pydev
什么是不是说生命是短暂的.我用python 准备工作 sudo apt-get install python3-dev 例如以下操作 依次点击菜单 Help->Install New Softw ...
- BZOJ 2654: tree( 二分 + MST )
我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下. 不过这道题有点小坑... ------------------------------------------------- ...