1. 程式人生 > >boost 字串處理(1)

boost 字串處理(1)

字串演算法
標頭檔案 include

一.從split開始

string str1("hello abc-*-ABC-*-aBc goodbye");
vector<string> SplitVec; //結果
split(SplitVec, str1, is_any_of("-*"), token_compress_on);

1.首先討論最簡單的一個引數token_compress_on,為一個列舉型別

namespace boost {
    namespace algorithm {

    //! Token compression mode 
    /*!
        Specifies token compression mode for the token_finder.
    */
enum token_compress_mode_type { token_compress_on, //!< Compress adjacent tokens token_compress_off //!< Do not compress adjacent tokens }; } // namespace algorithm // pull the names to the boost namespace using algorithm::token_compress_on; using algorithm::token_compress_off; } // namespace boost

token_compress_on 為壓縮方式,如果在str1中遇到連續的’-‘,’*’則壓縮成一個
該引數下結果如下:
+ &SplitVec 0x005dfa9c [3](“hello abc”,”ABC”,”aBc goodbye”)

token_compress_off 為非壓縮凡是,和上面的相反結果為:
+ &SplitVec 0x0059fc88 [7](“hello abc”,”“,”“,”ABC”,”“,”“,”aBc goodbye”)

當然這個不是重點,重點是以上的列舉型別寫法,通過using方式將algorithm空間中的變數提升到boost空間中,這種方法比較常用,可避免列舉型別的衝突。

2.is_any_of(“-*”)
該函式返回一個is_any_of的struct物件,該物件為仿函式。
這些類似的仿函式生成函式,還提供幾個

// pull names to the boost namespace
    using algorithm::is_classified;
    using algorithm::is_space;
    using algorithm::is_alnum;
    using algorithm::is_alpha;
    using algorithm::is_cntrl;
    using algorithm::is_digit;
    using algorithm::is_graph;
    using algorithm::is_lower;
    using algorithm::is_upper;
    using algorithm::is_print;
    using algorithm::is_punct;
    using algorithm::is_xdigit;
    using algorithm::is_any_of;
    using algorithm::is_from_range;

這樣就好理解了,在執行split過程中,呼叫is_any_of(),仿函式來判斷是否需要切割,如果返回true則切割,false則繼續查詢。
當然每一次的切割結果放入SplitVec容器中。理解這個之後,自己也可以寫這個仿函數了。

二.split拓展

先給一個大致的流程圖

這裡寫圖片描述

split
Split input into parts
iter_split
Use the finder to find matching substrings in the input and use them as separators to split the input into parts

template< typename SequenceSequenceT, typename RangeT, typename PredicateT >
inline SequenceSequenceT& split(
    SequenceSequenceT& Result,
    RangeT& Input,
    PredicateT Pred,
    token_compress_mode_type eCompress=token_compress_off )
{
    return ::boost::algorithm::iter_split(
        Result,
        Input,
        ::boost::algorithm::token_finder( Pred, eCompress ) );         
}

split的內部是呼叫iter_split,iter_split是使用迭代器方式的。下面來看下iter_split中的具體實現:

template< 
    typename SequenceSequenceT,
    typename RangeT,
    typename FinderT >
inline SequenceSequenceT&
iter_split(
    SequenceSequenceT& Result,
    RangeT& Input,
    FinderT Finder )
{
    BOOST_CONCEPT_ASSERT((
        FinderConcept<FinderT,
        BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
        ));

    iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));

    typedef BOOST_STRING_TYPENAME 
        range_iterator<RangeT>::type input_iterator_type;
    typedef split_iterator<input_iterator_type> find_iterator_type;
    typedef detail::copy_iterator_rangeF<
        BOOST_STRING_TYPENAME 
            range_value<SequenceSequenceT>::type,
        input_iterator_type> copy_range_type;

    input_iterator_type InputEnd=::boost::end(lit_input);

    typedef transform_iterator<copy_range_type, find_iterator_type>
        transform_iter_type;

    transform_iter_type itBegin=
        ::boost::make_transform_iterator( 
            find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
            copy_range_type() );

    transform_iter_type itEnd=
        ::boost::make_transform_iterator( 
            find_iterator_type(),
            copy_range_type() );

    SequenceSequenceT Tmp(itBegin, itEnd);

    Result.swap(Tmp);
    return Result;
}

在iter_split將Input轉換為迭代器,也就是lit_input。然後使用make_transform_iterator轉換函式,轉換為split_iterator迭代器。這時候split_iterator的begin指向了字串的首地址。在split_iterator類中實現了
迭代器中的++操作。在match_type結構中有兩個指標,begin和end用來指向當前迭代器中的有效部分,每一次do_find就可以將兩個指標向後移動。

void increment()
{
     match_type FindMatch=this->do_find( m_Next, m_End );

     if(FindMatch.begin()==m_End && FindMatch.end()==m_End)
     {
         if(m_Match.end()==m_End)
         {
             // Mark iterator as eof
             m_bEof=true;
         }
     }

     m_Match=match_type( m_Next, FindMatch.begin() );
     m_Next=FindMatch.end();
 }

那麼do_find函式從何而來呢?
可以看一下,split_iterator 類的派生關係,可以看到這個類:detail::find_iterator_basedo_find就是來自這個類。

template<typename IteratorT>
        class split_iterator : 
            public iterator_facade<
                split_iterator<IteratorT>,
                const iterator_range<IteratorT>,
                forward_traversal_tag >,
            private detail::find_iterator_base<IteratorT>

現在來看下do_find函式,其中的m_Finder就是iter_split的最後一個引數FinderT Finder,也就最後用來傳遞給split_iterator的。m_Finder也就是::boost::algorithm::token_finder( Pred, eCompress )生成的仿函式物件。

// Find operation
match_type do_find( 
    input_iterator_type Begin,
    input_iterator_type End ) const
{
    if (!m_Finder.empty())
    {
        return m_Finder(Begin,End);
    }
    else
    {
        return match_type(End,End);
    }
}

在token_finder中又包含了一層,這樣來看的話token_finderF的才是仿函式的名字了。
template< typename PredicateT >
inline detail::token_finderF
token_finder(
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off )
{
return detail::token_finderF( Pred, eCompress );
}

看下token_finderF仿函式實現
ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
就是查詢的重點了,m_Pred 就是is_any_of(“-*”),
當遇到”-*”中的任意一個返回true的仿函式。
這樣的話就可以通過token_finderF的仿函式返回滿足m_Pred條件的區域了。

template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
    ForwardIteratorT Begin,
    ForwardIteratorT End ) const
{
    typedef iterator_range<ForwardIteratorT> result_type;

    ForwardIteratorT It=std::find_if( Begin, End, m_Pred );

    if( It==End )
    {
        return result_type( End, End );
    }
    else
    {
        ForwardIteratorT It2=It;

        if( m_eCompress==token_compress_on )
        {
            // Find first non-matching character
            while( It2!=End && m_Pred(*It2) ) ++It2;
        }
        else
        {
            // Advance by one position
            ++It2;
        }

        return result_type( It, It2 );
    }
}

三、split之外

在split中可見,boost中對字串的處理,幾乎是採用迭代器模式。
在boost::algorithm中,主要包括以下幾類演算法的實現,
演算法
1. to_upper to_lower 字串大小寫的轉換
2. trim_left trim_right trim 字串左右空白字元的裁剪
3. starts_with ends_with contains …等 字串包含關係
4. find 字串查詢
5. replace 字串替換
6. split 字串切割
7. join 字串拼接

相關推薦

boost 字串處理(1)

字串演算法 標頭檔案 include 一.從split開始 string str1("hello abc-*-ABC-*-aBc goodbye"); vector<string> SplitVec; //結果 split(SplitVe

字元和字串處理(1)

2.1 字符集及字元編碼(字符集——字元的集合,不同的字符集,收錄的字元可能不同) 2.1.1多位元組字符集及ANSI編碼標準 (1)單位元組編碼:ASCII字符集及擴充套件——滿足英語及西歐語言的需要 (2)雙位元組編碼:——滿足亞洲等國家語言文字的需要,如:

字串處理(1) : 首字母轉大寫/小寫

/** * 首字母轉小寫 * * @param str * @return */ public static String toLowerCaseFirstOne(String str) { i

字串處理-1.1

-- charindex 尋找字串位置     CHARINDEX (@findStr, @baseStr [, @beginPoint ] ) @findStr   :想要找到的字串 @baseStr   :基礎字串,即被

Windows下的字串處理(1)

最近感覺Windows下的字串處理有點紊亂,準備系統學習下。在此做點筆記。 Unicode或者寬字元都沒有改變char資料型態在C中的含義。char繼續表示1個位元組的儲存空間,sizeof (char)繼續返回1。 理論上,C中1個位元組可比8位長,但對我們大多數人來說,1個位元組(也就是

boost字串處理(下)

四、正則表示式庫 Boost.Regex 可以應用正則表示式於C++。正則表示式大大減輕了搜尋特定模式字串的負擔,在很多語言中都是強大的功能。雖然現在C++仍然需要以 Boost C++庫的形式提供這一功能,但是在將來正則表示式將進入C++標準庫。 Boost Rege

Java(一) -Core Java-(1)-字串處理

任何對String字串的操作均不改變原串 Java中將字串作為String型別物件來處理。當建立一個String物件時,被建立的字串是不能被改變的。每次需要改變字串時都要建立一個新的String物件來

Boost(五)——字串處理(一):字串操作

由於這一章內容過多,我將採用三個小章,精簡原文三個小部分內容。 區域設定: setlocale(LC_ALL,“”) locale::global(std::locale("German")); //設定全域性區域德語環境 字串操作: 一、將字串所有字元轉成大寫

Boost(五)——字串處理(二):正則表示式操作

正則表示式: 一些簡單的描述符: . 匹配除換行符以外的任意字元 \w 匹配字母或數字或下劃線或漢字 等價於 '[^A-Za-z0-9_]'。 \s 匹配任意的空白符 \d 匹配數字 \b 匹配單詞的開始或結束 ^ 匹配字串的開始 $ 匹配字串的結束 一、字

Boost(五)——字串處理(三):詞彙分割操作

講解 詞彙分割器庫 -> Boost.Tokenizer 可以在指定某個字元為分隔符後,遍歷字串的部分表示式。 字元分割: boost::char_separator<char(或者wchar_t)> #include <iostream&g

boost常用字串處理方法學習

工作中經常要用到boost中關於字串處理的方法,這裡做個簡單的介紹: 分割字串:split string test1("Hello world, hello programmer"); vector<string> vec1; boost::split(

boost——字串與文字處理tokenizer

#include <iostream> #include <string> #include <vector> #include <set> #include <map> #include <al

boost 字串和文字處理庫概述

conversion/lexical_cast - lexical_cast 類模板,來自 Kevlin Henney. format - 型別安全的 '類printf' 的格式化操作,來自 Samuel Krempp. iostreams - 一個框架,用於定義流、流緩衝和i/o過濾器,來自 Jonatha

boost字串處理函式——format

boost::format的格式一般為:     boost::format( "format-string ") % arg1 % arg2 % ... % argN ;     注意這裡沒有示例物件,format-string代表需要格式化的字串,後面用過載過的%跟

<數字圖像處理1> 數字圖像定義(Definition) 類型(Type) 采樣 (Sampling) 量化 (Quantisation)

nali rom pixel diff 類型 out 4.3 this ecif Continuous Greyscale Image 1 mapping f from a rectangular domain Ω =(0,a1) X (0,a2) to a co-do

中文維基數據處理 - 1. 下載與清洗

下載 open shell title -m 實體 code 選擇 html 1. 數據下載 一些重要的鏈接: 最新轉儲 需要 zhwiki-latest-pages-articles.xml.bz2 這個文件 中文維基的頁面統計信息 目前內容頁面數大約是 978K 2

Python自然語言處理1

cmd 輸入 函數調用 down load src 選擇 分享 cnblogs 首先,進入cmd 輸入pip install的路徑 隨後開始下載nltk的包 一、準備工作 1、下載nltk 我的之前因為是已經下載好了 ,我現在用的參考書是Python自然語言處理這本書,最

老王Python-進階篇4-異常處理1.3(周末習題)

調用 page eve sage urn put not name bject 一 編寫with操作類Fileinfo(),定義__enter__和__exit__方法。完成功能: 1.1 在__enter__方法裏打開Fileinfo(filename),並且返回file

字串處理演算法(六)求2個字串最長公共部分

基礎演算法連結快速通道,不斷更新中: 整型陣列處理演算法部分: 整型陣列處理演算法(一)按照正態分佈來排列整型陣列元素 整型陣列處理演算法(二)檔案中有一組整數,要求排序後輸出到另一個檔案中 整型陣列處理演算法(三)把一個數組裡的所有元素,插入到另一個數組的指定位置 整型陣列

mysql進行字串處理

mysql進行字串的處理 MySQL 字串擷取函式:left(), right(), substring(), substring_index()。還有 mid(), substr()。其中,mid(), substr() 等價於 substring() 函式,substring()