博客日历
2025年08月 | ||||||
一 | 二 | 三 | 四 | 五 | 六 | 七 |
28 | 29 | 30 | 31 | 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
存档
2025年03月 2024年
03月 04月 05月 2021年
01月 02月 11月 12月 2020年
02月 03月 04月 05月 06月 07月
09月 2018年
09月 2017年
01月 02月 07月 2016年
01月 04月 07月 08月 11月 12月
2015年
01月 02月 03月 05月 09月 10月
11月 2014年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2013年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2012年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2011年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2010年
01月 02月 03月 04月 05月 06月
07月 08月 09月 10月 11月 12月
2009年
03月 04月 05月 06月 07月 08月
09月 10月 11月 12月
ATL正则表达式库与CAtlRegExp的使用
正则表达式是最强大的文本解析工具之一,
在ATL中也提供了一些用于正则表达式的类库(CATLRegExp等),本文将简要说明这些类库的使用方法。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]。
匹配:
调用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的方法和成员就可以得到匹配的结果。
2.CAtlREMatchContext类
声明:
template <class CharTraits=CAtlRECharTraits>
class CAtlREMatchContext
使用:
CAtlREMatchContext通过m_uNumGroups成员以及GetMatch()方法向调用者提供匹配的结果信息。m_uNumGroups代表匹配上的Group有多少组,GetMatch()则根据传递给它的Group的Index值,返回匹配上的字符串的pStart和pEnd指针,调用者有了这两个指针,自然可以很方便的得到匹配结果。
3.一个小示例
下面这个例子来源于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);
}
}
输出:
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 FALSE:match fail
}
只要在构造ATL::CAtlRegExp和 ATL::CAtlREMatchContext类时,传递过去我们的MyRegTraits类作为Traits的参数,就可以直接使用自己定义的简略符号了。
5.CAtlRegExp对中文的支持
在CAtlRegExp中,默认使用CAtlRECharTraits,实际上是CAtlRECharTraitsA
要支持ANSI模式下的中文,必须使用CAtlRECharTraitsMB,见如下代码:
注意要包含#include <atlrx.h>。
要支持ANSI模式下的中文,必须使用CAtlRECharTraitsMB,见如下代码:
注意要包含#include <atlrx.h>。
char* szText="测试一下地址dgx_lsyd3@163.com看看\r\n";
//匹配电子邮件地址的正则表达式
char* szRegExpEmail="({[a-zA-Z0-9_\.]+@[a-zA-Z0-9]+[\.][a-zA-Z0-9]+[\.]?[a-zA-Z0-9]+})";
CAtlRegExp<CAtlRECharTraitsMB> reEmail;
REParseError reError=reEmail.Parse((const ATL::CAtlRegExp<CAtlRECharTraitsMB>::RECHAR *)szRegExpEmail);
if (REPARSE_ERROR_OK != reError)
return;
CAtlREMatchContext<CAtlRECharTraitsMB> mcEmail;
if (!reEmail.Match((const ATL::CAtlRegExp<CAtlRECharTraitsMB>::RECHAR *)szText,&mcEmail))
{
return;
}
char szBuf[260];
for (UINT nGroupIndex = 0; nGroupIndex < mcEmail.m_uNumGroups;++nGroupIndex)
{
const CAtlREMatchContext<CAtlRECharTraitsMB>::RECHAR* szStart = 0;
const CAtlREMatchContext<CAtlRECharTraitsMB>::RECHAR* szEnd = 0;
mcEmail.GetMatch(nGroupIndex, &szStart, &szEnd);
memcpy(szBuf,szStart,szEnd-szStart);
szBuf[szEnd-szStart]=0;
printf("%s\n",szBuf);
}
输出:
dgx_lsyd3@163.com
dgx_lsyd3@163.com
6.结尾
虽然现在C++的社区里已经拥有了Boost::regex,GRETA等非常著名的正则表达式库,可是作为VC++自带的模板库,ATL中的正则表达式库仍然给我们的工作提供了极大的便利。由于ATL是微软官方发布的Library,所以它拥有良好的文档说明、严格的测试以及微软官方的技术支持。另外在用ATL开发COM组件的时候,更可以方便地利用正则库的巨大威力。
7.备注
7.备注
在Visual Studio 2008中,ATL被单独提出来了,可以去如下地址下载:
原文:
1.http://blog.donews.com/crackme/archive/2006/04/26/847531.aspx
2.http://www.vckbase.com/document/viewdoc/?id=1256
在MSDN中:ms-help://MS.MSDNQTR.2003FEB.2052/vclib/html/vclrfCAtlRegExp.htm
其他参考:http://www.codeproject.com/KB/string/mfcregex.aspx?df=100&forumid=276265&exp=0&select=1541164
上一篇: 用ATL的W2A和A2W宏转换Unicode与ANSI字符串
下一篇: 版本控制软件Subversion(SVN)资料
分类:Win32/C++ 查看次数:9932 发布时间:2009/5/26 12:15:28