C++ Boost全庫簡介

本文章大量參考了《Boost程序庫徹底開發指南》(羅劍鋒),若是但願更深刻地瞭解,請參考該書。 html

本篇只是對Boost庫的簡單介紹,只是一些淺顯的內容,但願各位見諒。 ios

目前進度 40% 左右, 努力填坑中。 c++

因爲OSC的Markdown不支持Github Flavored Markdown的```成塊代碼形式,代碼在這裏顯示效果很是糟糕。 git

最新版本請移步 http://192.3.168.141/wordpress/wp-content/uploads/2014/12/boost%E5%BA%93%E5%AD%A6%E4%B9%A0.html 算法

CC-BY-SA
本做品採用知識共享署名-相同方式共享 3.0 未本地化版本許可協議進行許可。 bootstrap

爲何要用boost

  • boost給開發帶來了極大的語法簡潔
  • boost讓C++更像C++
  • boost讓程序更加安全

安裝

  1. 訪問http://www.boost.org/users/download/#live,而後點擊current release的download,我通常下載.tar.bz2
  2. 將你下載下來的東西解包,執行./bootstrap.sh
  3. 運行./b2 threading=multi
  4. 運行sudo ./b2 install
  5. 在你的gcc編譯選項增長:-Lboost
  6. 接下來試驗一小段代碼看看是否成功:
#include <boost/date_time/gregorian/gregorian.hpp> using namespace boost::gregorian; using namespace std; int main()
{
 date d1(2014,12,18);
 cout<<d1<<endl;
 return 0;
}

初涉Boost庫

如你所見,boost庫在使用時要#include在boost目錄下的不一樣頭文件,每一個文件有着相應的功能。 數組

大多數庫#include相應頭文件便可使用,然而例如date_time庫若是沒有-Lboost的話是無法正常運行的。 安全

boost庫中內容是在boost:命名空間下的,使用時要注意。 less

下面我會介紹一些實用的庫/類,更多內容須要後續的學習。 dom

timer:簡易計時

#include <boost/timer.hpp> #include <iostream>  using namespace boost; using namespace std; int main()
{
    timer a; //聲明時計時   double s=0.0;
    for(long long i=0;i< 1LL<<32;i++)
        s+=i*2+i; cout<<a.elapsed()<<endl;
    cout<<s<<endl; 
    return 0;
}

progrss_timer:析構時自動輸出時間

#include <boost/progress.hpp> #include <iostream> using namespace boost; using namespace std; int main()
{
    progress_timer a; double s=0.0;
    for(long long i=0;i< 1LL<<32;i++)
        s+=i*2+i;
    cout<<s<<endl;
    return 0;
}

progress_display:控制檯進度條

#include <boost/progress.hpp> #include <iostream> using namespace boost; using namespace std; int main()
{
    progress_display a(1LL<<32); double s=0.0; for(long long i=0;i< 1LL<<32;i++)
    {
        ++a; //注意!boost庫中大多數只實現了前自增,後自增是不行的  s+=i*2+i;
    } cout<<s<<endl;
    return 0;
}

date_time:強大的日期時間庫

gregorian:格里高利曆

使用這個庫須要引用:

#include <boost/date_time/gregorian/gregorian.hpp> using namespace boost::gregorian;

可使用多種方式建立date對象:

date t1(2014,12,19);
date t2(2014,Dec,19);
date d3(t2);
date t4=from_string("2014/12/19")

date能夠比較大小。

然而,它沒法處理1400年以前或9999年以後的日期。

day_clock::local_day返回本地時間

.year.month.day返回日月天

.day_of_week().day_of_year返回當天在一週或一年中的關係

date類型之間不可加,因此有了date_duration這個描述日期間隔的類型:

months m(5);
years y(2);
weeks w(3);

date_duration和自身與date類型都可加

gre_cal::is_leap_year(y)能夠簡單判斷y是不是閏年

posix_time:精確的計時系統

須要引用

#include <boost/date_time/posix_time/posix_time.hpp> using namespace boost::posix_time;

構造時間間隔

time_duration td(1,10,67,230); //時,分,秒,毫秒 前三者會自動進位 time_duration td2=duration_from_string("1:30:27:002");
hours h(1);
minutes m(10);
seconds s(3);
millisec ms(23);

上述對象都可加減

若是要建立一個時間點ptime類型時間點對象,最簡單的方法就是:

ptime p(date(2014,12,19),time_duration(21,03,17,002));

記得要包含posix_time和gregorian的兩部分頭文件和namespace

經過.date()和.time_of_day()來得到當前的日期和時間

microsec_clock::local_time()能夠得到微秒精度的本地時間

to_simple_string(t)能夠返回一個time_duration或ptime的字符串形式

typeof:自動推斷類型

#include <boost/typeof/typeof.hpp> #include <iostream> using namespace std; int main()
{
    BOOST_TYPEOF(3) a=2*6;
    BOOST_AUTO(s,"12312"); cout<<a<<" "<<s<<endl; return 0;
}

默認它只支持內置類,爲了支持本身的類:

#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() BOOST_TYPEOF_REGISTER_TYPE( 你的類的徹底名稱 )

optional:可選條件下空指針

optional模板是一個指針,若是某值知足選定的條件,它就是空指針,不然返回指向該值的指針。

#include <boost/optional.hpp>  #include <iostream>  using namespace std;  using namespace boost;  int main()
{
    int x=-6; int y=3;
    optional<double> d(x>=0,sqrt(x));
    cout<<d.get_value_or(-1)<<endl;  if (!d) cout<<"no result"<<endl;
    optional<double> d2(y>=0,sqrt(y));
    cout<<*d2<<endl;
    return 0;
}

assign:STL批量增長元素

引用:

#include <boost/assign.hpp>  using namespace boost::assign;

assign重載了+=運算符,能夠加入任意多個逗號隔開的元素,然而這些只能用於標準STL:

vector<int> v;
v+= 2,4,2*2+6; set<string> s;
s+="asdsdf","12"; map<int,string> m;
m+=make_pair(123,"123132"),make_pair(1233,"324235");

對於這些STL,有一些更簡潔的語法可供使用:

push_back(v)(345)(675);
insert(m)(45,"515")(98,"151sda");

list_of(...)和map_list_of(...)能夠返回匿名列表,可被用於任何容器

yourowncont<int> d= (list_of(5)(7)(4),9,10);
yourownmap<int,int> m= map_list_of(6,7)(8,9);

swap:高效的交換

若是有內建函數會調用內建的swap,不然會退化到常見的swap

#include <boost/swap.hpp> using namespace boost;

能夠交換數組

int a1[5]={0,2,4,3,2};  int a2[5]={3,7,2,5,1};
swap(a1,a2);

tribool:擁有不肯定值的布爾量

引用:

#include <boost/logic/tribool.hpp>  using namespace boost;

tribool類除了有常見的true和false以外,還有一種取值indeterminate(不肯定),它的邏輯運算規則請參考原書。可是if (indeterminate)和if (!indeterminate)後的代碼都不會執行,可使用indeterminate(tribool)來判斷其是不是不肯定。
還可使用

BOOST_TRIBOOL_THIRD_STATE(unknown)

來把第三態的名字改爲unknown

BOOST_TRIBOOL_THIRD_STATE(unknown)  int main()
{
    tribool a(unknown);  if (a) cout<<"true"<<endl;  if (!a) cout<<"false"<<endl;  if (indeterminate(a)) cout<<"indeterminate"<<endl; // 本條纔會被執行  return 0;
}

operators:自動生成操做符

引用:

#include <boost/operators.hpp>  using namespace boost;

這個庫提供了只寫<運算符就能自動生成>>=<=等功能。

對於一個類,「繼承」(實際上並非真正的繼承)
操做符類名1<自身這個類的全稱, 操做符類名2<自身這個類的全稱> >
就能實現上述方便的功能。

操做符類名見下:

類名 做用
equality_comparable 提供==,生成!=
less_than_comparable 提供<,生成<=>>=
addable 提供+=,生成+
subtractable 提供-=,生成-
multipliable 提供*=,生成*
dividable 提供/=,生成/
incrementable 提供前置++,生成後置++
decrementable 提供前置--,生成後置--
totally_ordered equality_comparable+less_than_comparable
additive addable+subtractable
multiplicative multipliable+dividable
arithmetic additive+multiplicative

另外它還提供了deferenceable解引用自動生成->和indexable生成下標[]操做符的功能,方式不如上所說,請有須要的讀者查閱書籍。

class Point:
less_than_comparable<Point>
{ public: int x,y,z;
  explicit Point(int a,int b,int c): x(a),y(b),z(c){};
  void print() const {cout<<x<<" "<<y<<" "<<z<<endl;}
  friend bool operator <(const Point& a, const Point& b)
    {
     return (a.x*a.x+a.y*a.y+a.z*a.z<b.x*b.x+b.y*b.y+b.z*b.z);
    }
}; int main()
{
    Point a(3,4,4), b(5,0,0); cout<< (a>=b) <<endl; return 0;
}

這個庫至關強大,但應用時也很是複雜,須要仔細使用。

exception:強化的異常類

引用:

#include <boost/exception/all.hpp> using namespace boost;

其精華在於exception類,它能夠用<<運算符傳入error_info對象的信息,信息能夠用get_error_info<...>(...)再取出來,若不存在會返回空指針。

在你定義本身的異常類時,首先虛繼承boost::exception,而後爲了方便期間typedef一下常見的error_info:

typedef boost::error_info<struct tag_err_no, int>    err_no;

模板前者是一個標記類,僅是爲了標記信息類型,沒有什麼太大的做用,第二個是其中實際存在的信息。

其中已經預約義了一些有用的error_info,詳情請翻閱。

對於已經有異常類的場合,能夠用enable_error_info(&e)來包裝一個異常類型,擁有boost::exception的所有好處。

uuid:簡單標識符

uuid是一個16字節的標識符,它在標記一個實體時頗有用。

#include <boost/uuid/uuid.hpp>  #include <boost/uuid/uuid_generators.hpp>  #include <boost/uuid/uuid_io.hpp>  #include <iostream>  using namespace std; using namespace boost::uuids;  int main()
{
    uuid u; //它默認是沒有構造函數的  cout<<u.size()<<endl; //老是16 vector<unsigned char> v(16,7);
    copy(v.begin(),v.end(),u.begin()); //提供了.begin() iterator cout<<u<<endl; //07070707-0707-0707-0707-070707070707 u.data[15]=8; //能夠用data訪問裏面各位的內容  cout<<u<<endl; //07070707-0707-0707-0707-070707070708 u=nil_generator() (); //先從nil_generator類構造臨時對象,再執行  cout<<u.is_nil()<<endl; //1 u=string_generator() ("07070707-0707-cdef-0707-070707070708"); //中間沒有-也行  cout<<u<<endl;

    uuid baseuuid = string_generator() ("070707070707cdef0707070707070708");
    u=name_generator(baseuuid) ("bob"); //先要指定一個基uuid,而後以其和名字構造出新的uuid cout<<u<<endl; //9bc6794a-bb5e-547a-9ae6-f295ee8feb4d  cout<<(u<baseuuid)<<endl; //uuid可比較 u=random_generator() (); cout<<u<<endl; //隨機uuid  return 0;
}

SHA1:重要的摘要算法

引用

#include <boost/uuid/sha1.hpp>  using namespace boost::uuid::detail;

sha1類提供了

  • .process_byte(abyte)
  • .process_bytes(char*, strlen(char*))
  • .process_block(char*from, char*end)

函數輸入數據,而後運行.get_digest(ans)返回unsigned int[5]一個sha值。

utility:小功能聚集

BOOST_BINARY:簡單二進制常量表示

#include <boost/utility.hpp> // 或直接 boost/utility/binary.hpp cout<< BOOST_BINARY(1100 100010 0011) <<endl; //每一個空格分的段不能超過8個二進制數字 // 一樣能夠用 BOOST_BINARY_標準整數後綴 來得到不一樣格式的數字

BOOST_CURRENT_FUNCTION:返回當前函數聲明字符串

#include <boost/current_function.hpp>

具體返回取決於編譯器。

lexical_cast:字面量轉換

這個恐怕是cpp中最須要的功能之一了,以前數值轉換最快的方法還是atoi之類,如今終於有了Cpp的實現了。能夠輕鬆在字符串和數值間轉換,很是方便。

引用

#include <boost/lexical_cast.hpp>  using namespace boost;

使用

cout<< lexical_cast<string>(6.256) <<endl; cout<< lexical_cast<double>("56.54")<<endl; cout<< lexical_cast<bool>("1") <<endl; //只能轉換0 1 ...

實際上,只要

  • 轉換起點可流輸出
  • 終點能夠流輸入,並可缺省和拷貝構造

就能利用這個語法轉換。

format:字符串格式化

引用

#include <boost/format.hpp> using namespace boost;

用法

先構造一個format對象,以後其重載了%運算符用來向內傳參。

format f("%s:%d+%d=%d\n");
f%"sum"; //參數能夠分批傳入 cout<< f% 1 % 2 % (1+2) <<endl; //sum:1+2=3 cout<<f.str()<<endl; //指定參數位置也能夠... cout<< format("two %1% is %1%%1%") % "sdfsd"<<endl; //two sdfsd is sdfsdsdfsd

語法

  • %05d寬度爲5整數,不足補0
  • %-8.3f左對齊,總寬8,小數位3浮點數
  • % 10s10位字符串,不足補
  • %05X寬5大寫16進制整數,不足補0

然而,其比printf慢2~5倍,由於其作了不少安全檢查。

string_algo:字符串專用算法

引用、頭部分

#include <boost/algorithm/string.hpp>  #include <boost/typeof/typeof.hpp> #include <boost/assign.hpp> #include <iostream> #include <string> using namespace std; using namespace boost; using namespace boost::assign; void printiter(const string::iterator &a,const string::iterator &b)
{ for (BOOST_AUTO(c,a);c!=b;c++) cout<<*c; cout<<endl;
}

經常使用判斷函數

int main()
{ string s("Readme.txt"); //注意:i前綴表明無視大小寫 _copy後綴表明複製後返回結果(不然原地處理) cout<<to_upper_copy(s)<<endl; //README.TXT cout<<to_lower_copy(s)<<endl; //readme.txt cout<<istarts_with(s,"read")<<endl; //1 cout<<ends_with(s,"tXt")<<endl; //0 cout<<contains(s,"Me")<<endl; //0 cout<<iequals(s,to_upper_copy(s))<<endl; //1 cout<<ilexicographical_compare(s,"rFad")<<endl; //1 字典序比較前者是否小於後者 cout<<all(s,is_lower()) <<endl; //0 s中每個元素是否都知足後面的函數 /* 下列函數能夠用於all (實際上,他們並非真正執行,只是返回了真正的函數對象) * is_space * is_alnum 是不是字母或數字 * is_alpha 是不是字母 * is_cntrl 是否爲控制字符 * is_digit 是不是數字 * is_lower * is_upper * is_print * is_punct 是不是標點 * is_xdigit 是不是十六進制數字 * is_any_of * if_from_range */

比較

cout<< is_less() ("read","REED") <<endl; //1 cout<< is_not_greater() ("read","REED") <<endl; //1

修剪空格

cout<<trim_copy( string(" abcd ") )<<endl; //abcd cout<<trim_right_copy( string(" abcd ") )<<endl; // abcd

查找

//返回一個range對象,其.begin .end能夠像迭代器同樣訪問 iterator_range<string::iterator> r;
    r=find_first(s,"ea");
    printiter(r.begin(),r.end()); //ea r=ifind_nth(s,"E",1);
    printiter(r.begin(),s.end()); //e.txt r=find_tail(s,6);
    printiter(r.begin(),r.end()); //me.txt //還有find_regex等

替換、刪除

// replace/erase_{first|last|nth|all|head|tail} // 語法同上基本相同,在此再也不贅述,replace最後加上一個字符串就好了

分割

list<BOOST_TYPEOF(r)> l;
    split(l,s,is_any_of(".")); for (BOOST_AUTO(c,l.begin());c!=l.end();++c) cout<<*c<<endl; //Readme //txt vector<BOOST_TYPEOF(r)> v;
    find_all(v,s,"."); for (BOOST_AUTO(c,v.begin());c!=v.end();++c) cout<<*c<<endl; //.

合併

vector<string> vs =(list_of("abc")("def")("hij")); cout<<join(vs,"|||")<<endl; //abc|||def|||hij //join_if也可用 }
相關文章
相關標籤/搜索