ATL正則表達式庫使用

ATL中,因爲ATL Server的須要,須要對Client發送過來的地址、命令等複雜文字字段信息解碼,而正則表達式是公認的最強大的文字解析工具,因此,ATL提供了一些用於正則表達式的庫方便了咱們的工做。git

一、 CATLRegExp類正則表達式

聲明:函數

template <class CharTraits=CAtlRECharTraits>
class CAtlRegExp;

初始化:工具

與微軟的GRETA類庫(微軟研究院推出的另外一個正則表達式類庫)不一樣,CATLRegExp並沒 有在構造函數中提供初始化匹配字符串的方法,而是讓使用者經過調用它的Parse()方法, 使用正則表達式字符串做爲參數,就能夠構造出一個咱們所須要的用於匹配的類,例如咱們 須要匹配一種時間格式,能夠是h:mm、也能夠是hh:mm,那麼咱們能夠這樣構造咱們的CAtlRegExp類:
CAtlRegExp <> re;
re.Parse( "{[0-9]?[0-9]}:{[0-9][0-9]}" );
ATL的正則表達式語法和Perl的正則表達式語法大同小異,不過有一個值得注意的地方就 是ATL中用大括號({ })表示其匹配字符串中的Group,咱們上面的表達式中,就聲明瞭2 個Group,一個是[0-9]?[0-9],另外一個是[0-9][0-9]。

匹配: 
調用CATLRegExp的Match()方法,就能夠用該類來進行匹配了,Match方法的原型以下:
BOOL Match(const RECHAR *szIn, CAtlREMatchContext<CharTraits> *pContext, const RECHAR **ppszEnd=NULL)
參數的含義很明顯,不過須要注意到第一個參數的型別是:const RECHAR * szIN,是一個 const指針,這代表咱們能夠方便得使用std::string類的c_str()方法給其傳遞參數。 

Match的結果經過第二個參數pContext所指向的CAtlREMatchContext<>類來返回,Match 的結果及其相關信息都被存放在CAtlREMatchContext類中,咱們只要訪問CAtlREMatchContext的方法和成員就能夠獲得匹配的結果。 

二、 CAtlREMatchContext類

聲明:測試

template <class CharTraits=CAtlRECharTraits>
class CAtlREMatchContext
使用:

CAtlREMatchContext經過m_uNumGroups成員以及GetMatch()方法向調用者提供匹配的結果信息。m_uNumGroups表明匹配上的Group有多少組,GetMatch()則根據傳遞給它的Group
的Index值,返回匹配上的字符串的pStart和pEnd指針,調用者有了這兩個指針,天然能夠很方便的獲得匹配結果。spa

三、 一個小示例

下面這個例子來源於MSDN,演示了CATLRegExp和CAtlREMatchContext類的典型使用方法:指針

#include "stdafx.h"
#include <atlrx.h>

int main(int argc, char* argv[])
{
   CAtlRegExp<> reUrl;

   // five match groups: scheme, authority, path, query, fragment
   REParseError status = reUrl.Parse(
        "({[^:/?#]+}:)?(//{[^/?#]*})?{[^?#]*}(?{[^#]*})?(#{.*})?" );
   if (REPARSE_ERROR_OK != status)
   {
      // Unexpected error.
      return 0;
   }

   CAtlREMatchContext<> mcUrl;
   if (!reUrl.Match( "http://search.microsoft.com/us/Search.asp?qu=atl&boolean=ALL#results",
      &mcUrl))
   {
      // Unexpected error.
      return 0;
   }

   for (UINT nGroupIndex = 0; nGroupIndex < mcUrl.m_uNumGroups;
        ++nGroupIndex)
   {
      const CAtlREMatchContext<>::RECHAR* szStart = 0;
      const CAtlREMatchContext<>::RECHAR* szEnd = 0;
      mcUrl.GetMatch(nGroupIndex, &szStart, &szEnd);

      ptrdiff_t nLength = szEnd - szStart;
      printf("%d: \"%.*s\"\n", nGroupIndex, nLength, szStart);
   }
}
Output

0: "http"
1: "search.microsoft.com"
2: "/us/Search.asp"
3: "qu=atl&boolean=ALL"
4: "results"code

例子中所用的正則表達式爲:繼承

({[^:/?#]+}:)?(//{[^/?#]*})?{[^?#]*}(?{[^#]*})?(#{.*})?ci

以()爲分界標誌,共分紅5組,第一組是{[^:/?#]+}:,^是「非」後面成員的意思,那麼也就是說第一組從開頭開始,一直到:、/、?、#其中任何一個結束。聯繫後面的待匹配字符串就能夠得出所匹配的結果是http。

四、 自定義匹配字符串的縮寫形式

爲了方便,ATL已經幫咱們定義了一些常常用到的正則表達式的簡略形式。例如:\d表明([0-9])、\n表明(\r|(\r?\n))等。這些縮寫形式都體如今CAtlRECharTraitsA/CAtlRECharTraitsW等類中,把這些類做爲模板參數傳遞給CATLRegExp和 CAtlREMatchContext,咱們就能夠定義本身的匹配字符串縮寫了。

class CAtlRECharTraitsA
{
    static const RECHARTYPE** GetAbbrevs()
    {
        static const RECHARTYPE *s_szAbbrevs[] = 
        {
            "a([a-zA-Z0-9])",   // alpha numeric
            "b([ \\t])",        // white space (blank)
            "c([a-zA-Z])",  // alpha
            "d([0-9])",     // digit
            "h([0-9a-fA-F])",   // hex digit
            "n(\r|(\r?\n))",    // newline
            "q(\"[^\"]*\")|(\''''[^\'''']*\'''')",   // quoted string
            "w([a-zA-Z]+)", // simple word
            "z([0-9]+)",        // integer
            NULL
        };

        return s_szAbbrevs;
    }
};
以上是atlrx.h摘錄下來的代碼,能夠很清楚地看到ATL是經過一個GetAbbrevs()函數 來定義字符串縮寫的。要定義新的縮寫形式,咱們只須要這樣:
class   MyRegTraits : public ATL::CAtlRECharTraitsA
{
public:
    static const RECHARTYPE** GetAbbrevs()
    {
        static const RECHARTYPE *s_szAbbrevs[] = 
        {
            "a([a-zA-Z0-9])",   // alpha numeric
            "b([ \\t])",        // white space (blank)
            "c([a-zA-Z])",  // alpha
            "d([0-9])",     // digit
            "h([0-9a-fA-F])",   // hex digit
            "n(\r|(\r?\n))",    // newline
            "q(\"[^\"]*\")|(\''''[^\'''']*\'''')",   // quoted string
            "w([a-zA-Z]+)", // simple word
            "z([0-9]+)",        // integer
            "e([0-8]+)",        //本身添加
            NULL
        };
        return s_szAbbrevs;
    }

};
讓咱們本身定義的Trait類繼承自CAtlRECharTraitsA,而後改寫GetAbbrevs()函數,增長 一些須要的簡寫就能夠被使用了。下面的代碼示例了使用了咱們本身的類中定義的「\e」簡 略表達:
int main ( )
{
    ATL::CAtlRegExp < MyRegTraits > re ;
    re.Parse( "\\e+" ); 
    ATL::CAtlREMatchContext < MyRegTraits > mc ;

    BOOL res1 = re.Match( "678", &mc );  // returns TRUE: successful match
    res1 = re.Match ( "999" , &mc ) ;    //  returns FALSE:match fail
}

只要在構造ATL::CAtlRegExp和 ATL::CAtlREMatchContext類時,傳遞過去咱們的 MyRegTraits類做爲Traits的參數,就能夠直接使用本身定義的簡略符號了。

五、 結尾

雖然如今C++的社區裏已經擁有了Boost::regex,GRETA等很是著名的正則表達式庫,但是 做爲VC++自帶的模板庫,ATL中的正則表達式庫仍然給咱們的工做提供了極大的便利。因爲 ATL是微軟官方發佈的Library,因此它擁有良好的文檔說明、嚴格的測試以及微軟官方的 技術支持。另外在用ATL開發COM組件的時候,更能夠方便地利用正則庫的巨大威力。 
相關文章
相關標籤/搜索