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]。
BOOL Match(const RECHAR *szIn, CAtlREMatchContext<CharTraits> *pContext, const RECHAR **ppszEnd=NULL)參數的含義很明顯,不過須要注意到第一個參數的型別是:const RECHAR * szIN,是一個 const指針,這代表咱們能夠方便得使用std::string類的c_str()方法給其傳遞參數。
聲明:測試
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的參數,就能夠直接使用本身定義的簡略符號了。