1. 程式人生 > >Boost 學習筆記--->字串&文字處理

Boost 學習筆記--->字串&文字處理

編譯環境:win10 Vs2015 Boost version:1.65.0 概解:      lexical_cast、string_algo、format這幾個方面是boost處理字串與文字的核心功能,涵蓋了以下方面:      a、將數值與字串互做轉換      b、將輸出做精確的格式化處理      c、字串的具體表示形式 lexical_cast:      此函式功能類似於c語言中的atoi函式,可以將string、int、flaot之間的字面值進行轉換,下面是這個函式一個簡單的示例: 示例一: #include <iostream> #include <boost/lexical_cast.hpp>          //to use lexical_cast using namespace std; using namespace boost; template<typename T>                       //將類的過載<<操作符作為模版類 struct outable {     friend ostream& operator<<(ostream& os,const T& x)     {         os << typeid(T).name();         return os;     } }; class DemoClass : public outable<DemoClass> { }; void case1() {     cout << lexical_cast<string>(DemoClass()) << endl;     //輸出類的id並且列印類名 } int main() {     case1(); } 簡單的運用示例:
示例二: #include <boost/lexical_cast.hpp> using namespace boost; int main() {      int x = lexical_cast<int>("100");               //string ---> int      long y = lexical_cast<long>("20000");           //string ---> long      float z = lexical_cast<float>("3.14159e5");     //string ---> float      double j = lexical_cast<double>("2.1767675");   //string ---> double      std::cout << x << y << z << j << std::endl;      /*      *輸出結果:100 20000 314159 2.1767675      */      /////////////////////////////////////      string str = lexical_cast<string>(456);          //int ---> string      std::cout << str << std::endl;      std::cout << lexical_cast<string>(0.618) << std::endl;     //float ---> string      std::cout << lexical_cast<string>(0x10) << std::endl;      //16進位制整數 ---> string      /*      *輸出結果:456 0.61799999999999999 16      */ } 注意點:
     lexical_cast函式在將字串轉換成數字顯示時,字串中只能有數字和小數點,不能出現字母(用作指數表示的e/E除外)或者其它數字字元。      lexical_cast不能轉換如:"123L"、"0x100"這種格式的C++語法許可的數字字面量字串,而且lexical_cast不支援高階的格式控制,不能把數字轉換成指定格式的字串,如果需要更高階的格式控制,可使用 std::stringsream boost::format 異常bad_lexical_cast:      當lexical_cast執行轉換出錯時會丟擲異常:bad_lexical_cast,它是std::bad_cast的派生類,為了使程式更加健壯,需要使用try/catch塊來保護轉換程式碼,如下: 示例三:
try {      cout << lexical_cast<int>("0x100");      cout << lexical_cast<double>("HelloWorld");      cout << lexical_cast<long>("1000L");      cout << lexical_cast<bool>("flase") << endl; } catch(bad_lexical_cast& e) {      cout << "error: " << e.what() << endl; } 上述程式碼執行後結果如下: error: bad lexical cast: source type value could not be interpreted as target 同時可以使用異常來驗證數字字串的合法性,可以將這個實現為一個模版類: 示例四: template<typename T> bool Num_valid(const char *str) try {    lexical_cast<T>(str);          //進行嘗試轉換動作       return true;  } catch(bad_lexical_cast &e) {      return false; } /* *函式Num_valid使用了一個funtion_try塊捕獲ban_lexical_cast異常 *如果對字串呼叫lexical_cast成功則返回true,失敗返回false; */ int main() {      assert(Num_valid<double>("3.14"));      assert(!Num_valid<int>("3.14"));      assert(Num_valid<int>("65535")); } 對準換物件的要求:      lexical_cast僅僅只是模仿了轉型操作符,實際上是一個模版類,lexical_cast內部使用了標準庫的流操作符,因此,對於物件的轉換有如下要求:      a、轉換七點物件是可用作流輸出的,即過載了"<<"操作符,operator<<;      b、轉換終點物件是可用作流輸入的,即過載了">>"操作符,operator>>;      c、轉換重點物件必須是可預設構造和拷貝構造的;      對於C++中的內建型別:int、double、std::string等都滿足以上三個條件,這三個也是最常與lexical_cast搭配使用的型別;      但是對於STL中的容器和其它使用者自定義的型別,這些條件一般都不滿足,不能使用lexical_cast函式進行轉換; 應用於自己的類:      如果要講lexical_cast應用與自己的類,只要實現了對於操作符"<<"的過載即可,就像示例一中所作一樣; Format: boost.format實現了類似於printf()的格式化物件,可以把引數格式化到一個字串,相比較C語言裡的printf而且是完全型別安全的格式化;      format元件位於名字空間 boost,為了使用Format,需要包含標頭檔案: #include <boost/format.hpp> using namespace boost; 對於boost庫中的format一個簡單的執行例項: 示例五: #include <boost/format.hpp> using namespace boost; void case1() {      cout << format("%s:%d + %d = %d\n")%"Sum" % 1 % 2 % (1 + 2);      format fmt("(%1% + %2%)" * %2% = %3%\n);      fmt % 2 % 5;      fmt % ((2 + 5) * 5);      cout << fmt.str(); } int main() {      case1(); } 以上程式執行結果如下: sum:1 + 2 = 3 (2 + 5) * 5 = 35 例項概解:      程式的第一條語句演示了format的最簡單的用法,使用format(...)構造了一個format臨時(匿名物件),建構函式的引數是格式化字串,其語義是標準printf()語法,使用%x來制定引數格式;      因為要被格式化的引數個數是不確定的,printf()使用了C語言裡的可變引數(即引數生命中的省略號),但它是不安全的,format模仿了流操作符<<,過載了二元操作符operator%作為引數輸入符,它同樣可以串聯任意數量的引數,因此: format(...)% a % b % c     //可以理解成下面這樣的 format(...) << a << b << c;      操作符把引數逐個餵給format物件,完成對引數的格式化,最後format物件支援流輸出,可以直接向輸出流cout輸出內部儲存的已格式化好的字串;      第一條format語句的等價printf()呼叫是: printf("%s: %d + %d = %d\n","sum",1,2,(1 + 2));      程式後面三行程式碼演示了format的另一種用法,預先建立一個format格式化物件,這個物件是可以被後面的程式碼多次用於格式化操作,format物件仍然用操作符%來接受被格式化的引數,可以分多次輸入,(不必一次給全),但引數的數量必須滿足格式化字串的要求,最後,使用format物件的str()成員函式獲得已格式化好的字串想cout輸出;      第二個format用了略不同於printf()格式化的語法:"(%1% + %2%) * %2% = %3%",有點類似於C#語言,%X%可以指示引數的位置,減少引數輸入的工作,是對printf()語法的一個改進;      第二個format物件的等價printf()呼叫是: printf("(%d + %d) * %d = %d\n",2,5,5,(2+5) * 5); 類摘要:      format並不是一個真正的類,而是一個typedef,真正的實現是basic_format,宣告如下: template<class charT,class Traits=std::char_traits<charT>> class basic_format; typedef basic_format<char> format; //basic_format類摘要如下: template<class charT,class Traitd=std::char_traits<charT>> class basic_format {      public:           explicit basic_format(const charT *str);           explicit basic_format(const string &s);           basic_format& operator=(const basic_format& x);           string_t str() const;           size_type size() const;           void clear();           basic_format& parse(const string_t&);           //pass arguments through those operator:           template<class T>basic_format& operator%(T& x);           friend std::basic_ostream& operator<<(...) };//basic_format typedef basic_format<char >        format; typedef basic_format<wchar_t >     wformat; string str(const format& ); 成員概解:      a、basic_format建構函式可以接受C字串(以0結尾的字元陣列)、std::string作為格式化字串,格式化字串使用類printf的格式規則,建構函式都被宣告為explicit,因此必須要顯式呼叫構造;      b、str()返回format物件內部已經格式化好的字串(不清空),如果沒有得到所有格式化字串要求的引數則會丟擲異常,format庫還同時提供一個同名的自由函式str(),它位於boost名字空間,返回format物件內部已格式化好的字串;      c、size()函式可以獲得已格式化好的字串長度,相當於str().size(),同樣,如果沒有得到所有格式化字串要求的引數則會丟擲異常;      d、parse()清空format物件內部快取,並改用一個新的格式化字串,如果僅僅想清空快取,可以使用clear(),它把format物件回覆到初始狀態,這兩個函式執行後呼叫str()、size()都會丟擲異常;      e、format過載了operator%,可以接受待格式化的任意引數,%輸入的引數個數必須恰好等於格式化字串要求的數量,過多或過少在format物件輸出時都會導致丟擲異常,當呼叫str()輸出字串活clear()清空緩衝區之後,則可以繼續再次使用%;      f、format還過載了流輸出操作符,因此可以直接向IO流輸出已格式化好的字串,相當於向流輸出str(); 格式化語法: format基本繼承了printf的格式化語法,它僅對printf語法有少量的不相容,一般情況下我們很難遇到;      每個printf格式化選項以%開始,後面是格式規則,規定了輸出的對齊、寬度、精度、字元型別,如下所示: %05d     :輸出寬度為5的整數,不足位用0填充 %-8.3f   :輸出左對齊,總寬度為8,小數位3位的浮點數 % 10s    :輸出10位的字串,不足位用空格填充 %05X     :輸出寬度為5的大寫16進位制整數,不足位用0填充 程式碼示例: format fmt("%05d\n%-8.3f\n% 10s\n%05X\n"); cout << fmt %62 %2.236 % "123456789" %48; 執行結果如下: 00062 2.236  123456789 00030      在經典的printf式格式化外,format還增加了新的格式:      a、%|spec|:與printf格式選項功能相同,但兩邊增加了豎線分割,可以更好的區分格式化選項與普通字元;      b、%N%:標記第N個引數,相當於佔位符,不帶任何其他的格式化選項;      使用%|spec|%的形式可以將上面的例子寫成如下格式: format fmt("%|05d|\n%|-8.3f|\n%| 10s|\n%|05X|\n");
format的效能:  printf()不進行型別安全檢查,直接向stdout輸出,因此速度上非常塊,而format較printf()做了很多安全檢查工作,因此效能略差,速度上要慢很多,總得來說要比printf()至少慢2倒5倍;      如果在意format的效能,那麼可以先簡歷const format物件,然後拷貝這個物件進行格式化操作,這樣比直接使用fromat物件能夠提高一些速度,如下: const format fmt("%10d %020.8f %010X %10.5e\n"); cout << format(fmt)%62 % 2.236 % 255 % 0.618; 高階用法:  format提供了類似於printf的功能,但它並不等同於printf函式,這就是面向物件好處,在通常的格式化字串之外,format類還擁有幾個高階功能,可以在執行時修改格式化選項、繫結輸入引數;      a、basic_format& bind_arg(int argN,const T& val)           把格式化字串第argN位置輸入引數固定為val,即使呼叫clear()也保持不變,除非呼叫clear_bind()或clear_binds();      b、basic_format& clear_bind(int argN)           取消格式化字串第argN位置的引數繫結;      c、basic_format& clear_binds()           取消格式化字串所有位置的引數繫結,並呼叫clear()方法;      d、basic_format& modify_item(int itemN,T manipulator)           設定格式化字串第itemN位置的格式化選項,manipulator是一個boost::io::group()返回的物件;      e、boost::io::group(T1 al, ..., Var const& var)           它是一個模版函式,最多支援10個引數(10個過載形式),可是設定IO流操縱器以指定格式或輸入引數值,IO流操縱器位於標頭檔案<iomanip> 以上用法如下示例: 示例六: #include <boost/format.hpp> #include <iomanip> using namespace boost; using boost::io::group void case1() {      //宣告format物件,有三個輸入引數,五個格式化選項      format fmt("%1% %2% %3% %2% %1% \n");      cout << fmt %1 % 2 % 3;      fmt.bind_arg(2,10);          //將第二個引數固定為數字10      cout << fmt %1 %3;           //輸出其餘兩個引數      fmt.clear();                 //清空緩衝,但是版定的引數不變      //在%操作符中使用group(),指定IO流操縱符第一個引數顯示為八進位制      cout << fmt % group(showbase,oct, 111) % 333;      fmt.clear_binds();          //清除所有繫結引數      //設定第一個格式化項,十六進位制,寬度為8,右對齊,不足位用*填充      fmt.modify_item(1,group(hex,right,showbase,setw(8),setfill('*')));      cout << fmt % 49 % 20 % 100; } int main() {      case1(); } /* * 輸出結果: * 1 2 3 2 1 * 1 10 3 10 1 * 0157 10 333 10 0157 * ****0x31 20 100 20 49 */ string_algo: 是一個非常全面的字串演算法庫,提供了大量的字串操作函式,如大小寫無關比較、修剪、特定模式的子串查詢等,可以在不實用正則表示式的情況下處理大多數字符串相關問題;      string_algo庫位於名字空間boost::algorithm,但被using語句引入到名字空間boost,為了使用string_algo需要包含等宣告如下: #include <boost/algorithm/string.hpp> using namespace boost; 示例程式碼如下: #include <iostream> #include <vector> #include <boost/smart_ptr.hpp> #include <boost/make_shared.hpp> #include <boost/algorithm/string.hpp>           //for use string_algo library using namespace std; using namespace boost; void case1() {        //shared_ptr、make_shared的使用,避免使用new、delete造成的記憶體問題        boost::shared_ptr<std::string> ps = boost::make_shared<std::string>(", I made a stupid decision to leave the world forever");        std::cout << "The ps content is: " << *ps << std::endl; } void case2() {        std::string str("ReadMe.txt");        if (boost::ends_with(str, "txt"))                                            //判斷後綴        {               std::cout << boost::to_upper_copy(str) + " UPPER" << std::endl;               assert(boost::ends_with(str, "txt"));        }        boost::replace_first(str, "ReadMe", "followme");                            //替換原字串內容        cout << "The replace_first str content: " << str << endl;        vector<char> v(str.begin(), str.end());                                     //一個字元大小的vector        vector<char> v2 = to_upper_copy(erase_first_copy(v, "txt"));                //to_upper_copy大寫,然後刪除字串        /*        for (int i = 0; i < v2.size(); ++i)        {               cout << v2[i];        }*/        for (auto tmp : v2)                                                         //此種方式雖較為方便,但是比起前++的常規for迴圈來說,開銷較大        {               cout << tmp;        }        cout << endl; } int main() {        case1();        case2();        system("pause"); }      這個例子示範了string_algo庫中:ends_with()、to_upper_copy()、replace_first()、erase_first_copy()等函式的基本用法,它們的名稱含義都是自說明,可以直接理會其字面意思; string_algo效能概述:      string_algo被設計用於處理字串,然而它的處理物件並不一定是string或者basic_string<T>,可以是任何符合boost.range要求的容器,容器內的元素也不一定是char或者wchar_t,任何可拷貝構造和賦值的型別均可,但如果型別的拷貝賦值代價很高,則string_algo的效能會下降;      string_algo庫中的演算法命名遵循了標準庫的慣例,演算法名均為小寫形式,並使用不同的字首或者字尾來區分不同的版本,命名規則如下:           a、字首i:有這個字首表明演算法是大小寫不敏感的,否則是大小寫敏感的;           b、字尾_copy:有這個字尾表明演算法不變動輸入,返回處理結果的拷貝,否則演算法原地處理,輸入即輸出;           c、字尾_if:有這個字尾表明演算法需要一個判斷式的謂詞函式物件,否則使用預設的判斷準則;      string_algo庫提供的演算法共分為五大類:           a、大小寫轉換           b、判斷式與分類           c、修剪           d、查詢與替換           e、分割與合併      A、大小寫轉換:           string_algo庫可以高效的實現字串的大小寫轉換,包括兩組演算法:to_upper()、to_lower();           兩個演算法宣告如下:           template<typename T>     void to_upper(T &Input);           template<typename T>     void to_lower(T &Input);           Usage: #include <boost/algorithm/string.hpp> using namespace boost; void case1() {      string str("I Don't Know.\n");      cout << "to_upper_copy: " << to_upper_copy(str);//返回大寫拷貝      cout << "str content: " << str;                 //原字串不改變      to_lower(str);                                  //字串小寫      cout << "to_lower: " << str;                    //原字串被改變 } 執行結果: to_upper_copy: I DON'T KNOW. str Content: I Don't Know. After lower str content: i don't know.      B、判斷式演算法:           判斷式演算法可以檢測兩個字串之間的關係,包括:                1)、starts_with                    :檢測一個字串是否是另一個的字首                2)、ends_with                     :檢測一個字串是否是另一個的字尾                3)、contains                        :檢測一個字串是否被另一個包含                4)、equals                           :檢測兩個字串是否相等                5)、lexicographical_compare:根據字典順序檢測一個字串是否小於另一個                6)、all                                  :檢測一個字串中的所有元素是否滿足指定的判斷式           除了all,這些演算法都有一個i字首版本,由於這些操作函式都不會改變原字串內容,所有不會有copy版本; 以上演算法示例如下: #include <iostream> #include <vector> #include <boost/smart_ptr.hpp> #include <boost/make_shared.hpp> #include <boost/algorithm/string.hpp>           //for use string_algo library using namespace std; using namespace boost; void case4() {        //starts_with() & ends_with() & contains() & equals() & lexicographical_compare() & all()        string str("Power Bomb");        assert(iends_with(str, "bomb"));                //大小寫無關檢測字尾        assert(!ends_with(str, "bomb"));                //大小寫敏感檢測字尾        assert(starts_with(str, "Pow"));                //檢測字首        assert(contains(str, "er"));                    //測試包含關係        string str2 = to_lower_copy(str);               //轉換小寫並返回一個拷貝        assert(iequals(str, str2));                     //大小寫無關判斷相等        string str3 = "power suit";        assert(lexicographical_compare(str, str3));     //大小寫無關比較        assert(all(str2.substr(0, 5), is_lower()));     //檢測子串均小寫 } int main() {        /*        case1();        case2();        case3();        */        case4();        system("pause"); }      C、判斷式演算法(函式物件):           string_algo增強了標準庫中的equal_to<>和less<>函式物件,允許對不同型別的引數進行比較,並提供大小寫無關的形式,這些函式物件包括:                1)、is_equal          :類似equals演算法,比較兩個物件是否相等                2)、is_less             :比較兩個物件是否具有小於關係                3)、is_not_greater :比較兩個物件是否具有不大於關係      具體使用例項如下: void case5() {        cout << "In case5() functions" << endl;        //is_equal() & is_less() & is_not_greater()        string str1 = "Samus", str2 = "samus";        assert(!is_equal()(str1, str2));        assert(is_less()(str1, str2)); }                注意函式物件名稱後的兩個括號,第一個括號呼叫了函式物件的建構函式,產生一個臨時物件,第二個擴後才是真正的函式呼叫操作符operator();      D、分類:           string_algo提供一組分類函式,可以用於檢測一個字元是否許賀某種特性,主要用於搭配其它演算法,如下所示:                  1)、is_space          :字元是否為空格                  2)、is_alnum         :字元是否為字母和數字字元                  3)、is_alpha          :字元是否為字母                  4)、is_cntrl            :字元是否為控制字元                  5)、is_digit            :字元是否為十進位制數字                  6)、is_graph          :字元是否為圓形字元                  7)、is_print            :字元是否為可列印字元                  8)、is_lower           :字元是否為小寫字元                  9)、is_punct           :字元是否為標點符號字元                10)、is_upper           :字元是否為大寫字元                11)、is_xdigit            :字元是否為十六進位制數字                 12)、is_any_of          :字元是否是引數字元序列中的任意字元                13)、if_from_range   :字元是否位於制定區間內,即from <= ch <= to;      在使用過程中需要注意,這些方法並不去檢測字元,只是返回一個型別為details::is_classifiedF的函式物件,這個物件的operator()才是真正的分類檢查函式(這些函式都是工廠函式);      E、修剪:           string_algo提供3個修剪演算法:trim_left、trim_right、trim           修剪演算法可以刪除字串開頭或結尾部分的空格,它有_if和_copy兩種字尾,因此每個演算法都有四個版本,_if版本接受判斷式IsSpace,將所有被判定為空格(IsSpace(c) == true)的字元刪除; 以上D、E的演算法示例如下: void case7() {        format fmt("|%s|\n");        string str = "   samus aran   ";        cout << "Delete Both Spaces: " << fmt % trim_copy(str) << endl;      //刪除兩端的空格        cout << "Delete Left Space : " << fmt % trim_left_copy(str) << endl;//刪除左邊的空格        cout << "Delete Right Space: " << fmt % trim_right_copy(str) << endl;//刪除右邊的空格        trim_right(str);                                                     //原地刪除右邊的空格        cout << "In Situ Delete: " << fmt % str << endl;        string str1 = "2017 is a year of egg pain;";        cout << "Delete Left Nums: " << fmt % trim_left_copy_if(str1, is_digit());   //刪除左端的數字        cout << "Delete Right put: " << fmt % trim_right_copy_if(str1, is_punct());  //刪除有段的標點        cout << "Delete Both Nums & Punct & Spaces: " << fmt % trim_copy_if(str1, is_punct() || is_digit() || is_space()); } int main() {        case7();        system("pause"); }      F、查詢:           string_algo與標準庫提供的search()功能類似,但介面不一樣,它不是返回一個迭代器(查詢到的位置),而使用了boost.range庫的iterator_range返回查詢到的整個區間,獲得了更多的資訊;           string_algo提供的查詢演算法如下:                1)、find_first     :查詢字串在輸入中第一次出現的位置                2)、find_last      :查詢字串在輸入中最後一次出現的位置                3)、find_nth      :查詢字串在輸入中的第n次(從0開始計數)出現的位置                4)、find_head    :取一個字串開頭N個字元的子串,相當於substr(0,n);                5)、find_tail       :取一個字串末尾N個字元的子串           以上演算法因為不變動字串原來內容,所有沒有_copy版本,其中前三個演算法有字首i版本,示例如下: void case8() {     //find_first & find_last & find_nth & find_head & find_tail     format fmt("|%s| .Pos value is: %d\n");     string str = "Long Long Ago,There Have A King;";     iterator_range<string::iterator> rge;        //Explain the iterator interval     rge = find_first(str, "Long");               //Find the location of the first occurrence with case     cout << "Find First: " << setw(5) <<  fmt % rge % (rge.begin() - str.begin());     rge = ifind_first(str, "Long");              //Case independent search for the first place to appear     cout << "Ifind first: " << setw(5) << fmt % rge % (rge.begin() - str.begin());     rge = find_nth(str, "ng", 2);                //Look for ng's third place in STR     cout << "Find nth: " << setw(5) << fmt % rge % (rge.begin() - str.begin());     rge = find_head(str, 4);                     //Take the first four characters     cout << "Find Head: " << setw(5) << fmt % rge % (rge.begin() - str.begin());     rge = find_tail(str, 5);                     //Take the last five characters     cout << "Find Tail: " << setw(5) << fmt % rge % (rge.begin() - str.begin());     rge = find_first(str, "samus");              //Not Find     assert(rge.empty() && !rge); } int main() {     case8();     system("pause"); }      G、替換與刪除:           替換、刪除操作與查詢演算法非常接近,是在查詢到結果後再對字串進行處理,因此它們命名很相似,如下所示:                1)、replace/erase_first    :替換/刪除一個字串在輸入中的第一次出現                2)、replace/erase_last     :替換/刪除一個字串在輸入中的最後一次出現                3)、replace/erase_nth     :替換/刪除一個字串在輸入中第n次的出現(從0開始計數)                4)、replace/erase_all       :替換/刪除一個字串在輸入中的所有出現                5)、replace/erase_head   :替換/刪除輸入的開頭                6)、replace/erase_tail      :替換/刪除輸入的末尾           這些演算法是一個大集合,前八個每個都有字首"i"、字尾"_copy"組合,有四個版本,後四個則只有"_copy"兩個版本,示例如下: void case9() {        //replace_*** & erase_***        string str = "Samus beat the monster.\n";        cout << "replace_first_copy: " << replace_first_copy(str, "Samus", "samus") << endl;;        replace_last(str, "beat", "kill");        cout << "replace_last: " << str << endl;        cout << "ierase_all_copy: " << ierase_all_copy(str, "samus") << endl;        cout << "replace_nth_copy: " << replace_nth_copy(str, "1", 1, "L") << endl;        cout << "erase_tail_copy: " << erase_tail_copy(str, 8) << endl; } int main() {        case9();        system("pause"); }      H、分割:           string_algo提供了兩個字串分割演算法:find_all和split,可以使用某種策略把字串分割成若干部分,並將分割後的字串拷貝存入指定的容器,應用示例如下; void case10() {        string str = "Samus,Link.Zelda::Mario-Luigi+zelda";        deque<string> d;        ifind_all(d, str, "zELDA");       //Case-insensitive segmentation strings are not distinguishable        assert(d.size() == 2);        cout << "deque size: " << d.size() << endl;        for (BOOST_AUTO(pos, d.begin());pos != d.end();++pos)        {               cout << "Pos:[ " << *pos << " ]";        }        cout << endl;        list <iterator_range<string::iterator>> ls;        split(ls, str, is_any_of(",.:-+"));      //Use punctuation marks        for (auto tmp:ls)        {               cout << "Pos: [ " << tmp << " ]";        }        cout << endl;        ls.clear();        split(ls, str, is_any_of(".:-"), token_compress_on);        for (auto tmp : ls)        {               cout << "Pos:[ " << tmp << " ];";        }        cout << endl; } int main() {        case10();        system("pause"); }      I、合併:           合併演算法join是分割演算法的逆運算,把儲存在容器中的字串連線成一個新的字串,並且可以指定連線的分隔符,示例如下: #include <iostream> #include <vector> #include <iomanip> #include <string> #include <list> #include <boost/assign.hpp>                    //for use list_of() #include <boost/format.hpp> #include <boost/smart_ptr.hpp> #include <boost/make_shared.hpp> #include <boost/typeof/typeof.hpp> #include <boost/algorithm/string.hpp>           //for use string_algo() library using namespace std; using namespace boost; using namespace boost::assign; void case11() {        vector<string> str = list_of("Samus")("Link")("Zelda")("Mario");        cout << "Vector str size is: " << str.size() << endl;        cout << "Vector str Content: " << join(str, "+") << endl;                   //coalescing        struct is_contains_a
       {               bool operator()(const string &st)               {                      return contains(st, "a");               }        };        cout << "After Operator() str Content: " << join_if(str, "**", is_contains_a()) << endl;  //coalescing } int main() {        case11();        system("pause"); }      J、查詢分割迭代器:           通用的find_all以及split之外,string_algo庫中還提供兩個查詢迭代器find_iterator、split_iterator,它們可以在字串中像迭代器那樣遍歷匹配,進行查詢或者分割,不用容器容納,示例如下: #include <iostream> #include <vector> #include <iomanip> #include <string> #include <list> #include <boost/assign.hpp>                      //for use list_of() function #include <boost/format.hpp> #include <boost/smart_ptr.hpp> #include <boost/make_shared.hpp> #include <boost/typeof/typeof.hpp> #include <boost/algorithm/string.hpp>           //for use string_algo library void case12() {        string str("Samus||samus||mario||||Link");        typedef find_iterator<string::iterator> string_find_iterator; //查詢迭代器型別定義        string_find_iterator pos, end;                                                            //宣告查詢迭代器變數        for (pos = make_find_iterator(str,first_finder("samus",is_iequal()));pos != end;++pos)        {               cout << "Pos Content is: " << *pos << ";";        }        cout << endl;        typedef split_iterator<string::iterator> string_split_iterator;                          //分割迭代器型別定義        string_split_iterator p, endp;                                                            //宣告分割迭代器變數        for (p = make_split_iterator(str,first_finder("||",is_iequal()));p != endp;++p)          //is_iequal()判斷是否相等        {               cout << "P Content is: " << *p << ";";        }        cout << endl; } int main() {        case12();        system("pause"); }      過程概解:           使用查詢迭代器首先要宣告迭代器物件find_iterator或者split_iterator,它們的模版型別引數是一個迭代器型別a,如:string::iterator或者char*;           為了獲得迭代器的起始位置,需要呼叫first_finder()函式,用於判斷匹配物件,再用make_find_iterator或make_split_iterator來真正建立迭代器,同族的查詢函式還有last_finder、nth_finder、token_finder等,它們的含義與查詢演算法類似,從不同的位置開始查詢返回迭代器;           初始化工作完成後,就可以像使用標準迭代器或者指標那樣,不斷的遍歷迭代器物件,使用解引用操作符獲取查詢的內容,知道找不到匹配的物件;           特別注意分割器的運用,它可以以任意長度的字串作為分隔符進行分割,而普通的split演算法則只能以字元作為分隔符; tokenizer:      tokeizer庫是有一個專門用於分詞(token)的字串處理庫,可以使用簡單易用的方法把一個字串分解成若干個單詞,它與string_algo庫的分割演算法類似,但不同之處也有很多;      tokenizer位於名字空間boost,為了使用tokenizer元件,需要在檔案中包含並宣告如下: #include <boost/tokenizer.hpp> using namespace boost; /* * tokenizer類原型 */ template<typename TokenizerFunc = char_delimtiers_separator<char>,           typename Iterator = std::string::const_iterator,           typename Type = std::string> class {      tokenizer(Iterator first,Iterator last,const TokenizerFunc& f);      tokenizer(const Container& c,const TokenizerFunc& f);      void assign(Iterator first,Iterator last);      void assign(const Container& c);      void assign(const Container& c,const TokenizerFunc& f);      iterator begin() const;      iterator end() const; };      引數說明:           A、TokenizerFunc     : tokenizer庫專門的分詞函式物件,預設是使用空格、標點符號分詞           B、Iterator               :字元序列的迭代器型別           C、Type                    : 儲存分詞結果的型別      這三個模版型別都提供了預設值,但通常只有前兩個模版引數可以變化,第三個型別一般只能選擇std::string或者std::wstring,這也是它位於模版引數列表最後的原因;      tokenizer的建構函式接受要進行分詞的字串,可以以迭代器的區間形式給出,也可以是一個有begin()和end()成員函式的容器;      assign()函式可以重新指定要分詞的字串,用於再利用tokenizer;      tokenizer具有類似標準容器的介面,begin()函式使tokenizer開始執行分詞功能,返回第一個分詞迭代器,end()函式表明迭代器已經到達分詞序列的末尾,分詞結束;      用法:      tokenizer的用法很像string_algo的分割迭代器,但要簡單一些,可以向使用一個容器用,向tokenizer傳入一個欲分詞的字串構造,然後用begin()獲得迭代器反覆迭代;      詳細用法示例如下: #include <iostream> #include <vector> #include <iomanip> #include <string> #include <list>                                 //for use lits<std::string> str #include <boost/assign.hpp>                     //for use list_of() function #include <boost/format.hpp>                     //for use format fmt("***") #include <boost/tokenizer.hpp>                  //for use tokenizer<> tok(std:;string) #include <boost/smart_ptr.hpp>                  //for use shared_ptr() #include <boost/make_shared.hpp>                //for use make_shared() #include <boost/typeof/typeof.hpp>              //for use BOOST_AUTO #include <boost/algorithm/string.hpp>           //for use string_algo library void case13() {        //tokenizer<> tok(std::string);        string str = "Link raise the master-sword.";        tokenizer<> tok(str);                    //使用預設模版引數建立分詞物件                                                 //此時是預設使用空格、標點符號進行字元分詞        for (BOOST_AUTO(pos,tok.begin());pos != tok.end();++pos)        {               cout << " Pos Content: " << *pos << endl;        } } int main() {        case13();        system("pause"); }      分詞函式物件:           tokenizer的構造引數中,只要滿足且具有合適的operator()、reset(0語言的函式物件就可以用於分詞,tokenizer庫提供四個預定義好的分詞物件:           a、char_delimiters_separaptor:使用標點符號分詞,已經被宣告廢棄,不推薦使用;           b、char_separator:支援一個字元集合作為分隔符,預設的行為與char_delimiters_separator類似;           c、escaped_list_separator:用於csv格式(逗號分隔)的分詞;           d、offsert_separator:使用偏移量來分詞,在分解平檔案格式的字串時很有用;      以下為上面主要三個物件的使用介紹:           a、char_separator:使用一個字元集合作為分詞依據,行為很類似split演算法,它的構造如下所示: char_separator(const char* dropped_delims,const char* kept_delims = 0,empty_token_policy empty_tokens = drop_empty_tokens);           建構函式中的引數釋義如下:                1)、dropped_delims:分隔符集合,這個集合中的字元不會作為分詞的結果出現;                2)、kept_delims      :分隔符集合,但其中的字元會保留在分詞結果中;                3)、empty_tokens   :類似split演算法的eCompress引數,處理兩個連續出現的分隔符,如keep_empty_tokens則表示連續出現的分隔符表示了一個空字串,相當於split演算法的token_compress_off值,如為drop_empty_tokens,則空白單次不會作為分詞的結果;           如果使用預設構造,不傳入任何引數的話,則等同於char_separator(" ",標點符號字元,drop_empty_tokens),以空格和標點符號分詞,保留標點符號,不輸出空白單次,示例如下: #include <iostream> #include <vector> #include <iomanip> #include <string> #include <list>                                                      //for use lits<std::string> str #include <boost/assign.hpp>                            //for use list_of() function #include <boost/format.hpp>                            //for use format fmt("***") #include <boost/tokenizer.hpp>                         //for use tokenizer<> tok(std:;string) #include <boost/smart_ptr.hpp>                         //for use shared_ptr() #include <boost/make_shared.hpp>                //for use make_shared() #include <boost/typeof/typeof.hpp>              //for use BOOST_AUTO #include <boost/algorithm/string.hpp>           //for use string_algo library using namespace std; using namespace boost; using namespace boost::assign; template<typename T> void print(T &tok) {        for (BOOST_AUTO(pos,tok.begin()); pos != tok.end(); ++pos)        {               cout << " Pos Cotent: " << *pos << endl;        } } void case14() {        //char_separator()        char *str = "Link ;; <master-sword> zelda";        char_separator<char> seq;                              //一個char_separator物件        tokenizer < char_separator<char>, char*> tok(str, str + strlen(str), seq); //傳入char_separator構造分詞物件        cout << "tokenizer: " << endl;        print(tok);                                            //分詞並輸出        tok.assign(str, str + strlen(str), char_separator<char>(" ;-","<>"));       //重新分詞        cout << "tok.assign: " << endl;        print(tok);        tok.assign(str, str + strlen(str), char_separator<char>(" ;-<>", "", drop_empty_tokens));        cout << "Twocie Assign: " << endl;        print(tok); } int main() {        case14();        system("pause"); }           b、escaped_list_separator:這個是專門處理CSV格式(Comma Split Value,逗號分割值)的分詞物件,它的建構函式宣告如下: escaped_list_separator(char e = '\\',char c = ',',char q = '\"');           這個函式的引數一般都取預設值,其釋義如下:                1)、引數"e":指定了字串中的轉義字元,預設是‘\';                2)、引數"c":分隔符,預設是‘,’;                3)、引數"q":引號字元,預設是”           具體示例如下: #include <iostream> #include <vector> #include <iomanip> #include <string> #include <list>                                                      //for use lits<std::string> str #include <boost/assign.hpp>                            //for use list_of() function #include <boost/format.hpp>                            //for use format fmt("***") #include <boost/tokenizer.hpp>                         //for use tokenizer<> tok(std:;string) #include <boost/smart_ptr.hpp>                         //for use shared_ptr() #include <boost/make_shared.hpp>                //for use make_shared() #include <boost/typeof/typeof.hpp>              //for use BOOST_AUTO #include <boost/algorithm/string.hpp>           //for use string_algo library using namespace std; using namespace boost; using namespace boost::assign; template<typename T> void print(T &tok) {        for (BOOST_AUTO(pos,tok.begin()); pos != tok.end(); ++pos)        {               cout << " Pos Cotent: " << *pos << endl;        } } void case15() {        //escaped_list_separator()        string str = "id,100,name,\"mario\"";        escaped_list_separator<char> seq;        tokenizer<escaped_list_separator<char>> tok(str, seq);        print(tok); } int main() {        case15();        system("pause"); } /************************************************************************/ /* 輸出結果: /* Pos Cotent : id /* Pos Cotent : 100 /* Pos Cotent : name /* Pos Cotent : mario /* 請按任意鍵繼續. . . /************************************************************************/      c、offset_separator:與前兩種分詞函式不同,這個分詞功能不基於查詢分隔符,而是使用偏移量的概念,在處理某些不實用分隔符而使用固定欄位寬度的文字時非常有用,建構函式如下: template<typename Iter> offset_separator(Iter begin,Iter end,bool wrap_offsets = true,bool return_partial_last = true);      offset_separator的建構函式接受兩個迭代器引數(也可以是陣列指標)begin、end,指定分詞用的整數偏移量序列,整數序列的每個元素分詞欄位的寬度;      bool引數bwrapoffsets,決定是否在偏移量用完後繼續分詞,bool引數return_partial_last決定在偏移量學列最後是個否返回分詞不足的部分,這兩個附加引數的預設值都是true,示例如下: #include <iostream> #include <vector> #include <iomanip> #include <string> #include <list>                                                      //for use lits<std::string> str #include <boost/assign.hpp>                            //for use list_of() function #include <boost/format.hpp>                            //for use format fmt("***") #include <boost/tokenizer.hpp>                         //for use tokenizer<> tok(std:;string) #include <boost/smart_ptr.hpp>                         //for use shared_ptr() #include <boost/make_shared.hpp>                //for use make_shared() #include <boost/typeof/typeof.hpp>              //for use BOOST_AUTO #include <boost/algorithm/string.hpp>           //for use string_algo library using namespace std; using namespace boost; using namespace boost::assign; template<typename T> void print(T &tok) {        for (BOOST_AUTO(pos,tok.begin()); pos != tok.end(); ++pos)        {               cout << " Pos Cotent: " << *pos;        }        cout << endl; } void case16() {        //offset_separator        string str = "2233344445";        i