ATL正则表达式库使用收藏

来源:互联网 发布:网络推广职位 编辑:程序博客网 时间:2024/06/08 11:43
ATL正则表达式库使用收藏

新一篇: 浅谈粮情测控系统的硬件集成及软件开发 | 旧一篇: 关于文档安全工具

ATL中,由于ATL Server的需要,需要对Client发送过来的地址、命令等复杂文字字段信息解码,而正则表达式是公认的最强大的文字解析工具,所以,ATL提供了一些用于正则表达式的库方便了我们的工作。

1 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]

匹配:
调用CATLRegExpMatch()方法,就可以用该类来进行匹配了,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的方法和成员就可以得到匹配的结果。


2 CAtlREMatchContext

声明:

template <class CharTraits=CAtlRECharTraits>

class CAtlREMatchContext

使用:

CAtlREMatchContext通过m_uNumGroups成员以及GetMatch()方法向调用者提供匹配的结果信息。m_uNumGroups代表匹配上的Group有多少组,GetMatch()则根据传递给它的Group
Index值,返回匹配上的字符串的pStartpEnd指针,调用者有了这两个指针,自然可以很方便的得到匹配结果。

3 一个小示例

下面这个例子来源于MSDN,演示了CATLRegExpCAtlREMatchContext类的典型使用方法:

#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"

例子中所用的正则表达式为:

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

以()为分界标志,共分成5组,第一组是{[^:/?#]+}:^后面成员的意思,那么也就是说第一组从开头开始,一直到:/?#其中任何一个结束。联系后面的待匹配字符串就可以得出所匹配的结果是http

4 自定义匹配字符串的缩写形式

为了方便,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 FALSEmatch fail

}

只要在构造ATL::CAtlRegExp ATL::CAtlREMatchContext类时,传递过去我们的 MyRegTraits类作为Traits的参数,就可以直接使用自己定义的简略符号了。

5 结尾

虽然现在C++的社区里已经拥有了Boost::regexGRETA等非常著名的正则表达式库,可是 作为VC++自带的模板库,ATL中的正则表达式库仍然给我们的工作提供了极大的便利。由于 ATL是微软官方发布的Library,所以它拥有良好的文档说明、严格的测试以及微软官方的 技术支持。另外在用ATL开发COM组件的时候,更可以方便地利用正则库的巨大威力。

由于本人学识所限,文章内容错在所难免,如有批评指正之词,请mail firingme@sina.com

 

发表于 @ 2006年07月17日 17:56:00|评论(0)|编辑

新一篇: 浅谈粮情测控系统的硬件集成及软件开发 | 旧一篇: 关于文档安全工具

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 现役军人回家探亲和人打架怎么办 对四六不懂的人怎么办 赌球小2.5进3球怎么办 皮肤旧伤黑色斑怎么办 小米5c网络不好怎么办 小米去5c卡怎么办 戴尔游匣5577开机黑屏怎么办 三星s6的通知栏拉不下来怎么办 电脑记住密码打不开了怎么办 联想手机升级系统失败了怎么办 日本语言学校申请研究生签证怎么办 在埃塞俄比亚签证过期了怎么办 看完的小说想要卖掉该怎么办 在俄罗斯脸干了痛怎么办 苹果手表电池放亏了怎么办 平板电脑电池不耐用怎么办 计算机电池放入后没反应怎么办 笔记本电脑玩游戏花屏怎么办 笔记本玩游戏花屏怎么办 笔记本电脑充电插口坏了怎么办 车蓄电池没电了怎么办 汤浅q85电瓶亏电怎么办 富士康自离行李怎么办 微店红酒食品认证怎么办 yy频道提示禁止游客进入怎么办 口红颜色太艳了怎么办 我在菲律宾想走怎么办 当国家流通货币不够用怎么办 苹果5s账号密码忘记怎么办 钢铁雄心3补给不足怎么办 灯外观颜色太难看了怎么办 被移民公司骗了怎么办 文明5大包锁区怎么办 鸭子被黄鼠狼叼走了怎么办 黄鼠狼再店了拉屎怎么办 我只有信用卡但是又想去嫖怎么办 瑞士退税单掉了怎么办 装了新风噪音大怎么办 意大利 护照被偷了怎么办 请问去意大利要怎么办护照 在意大利护照丢了怎么办