对话框模板 RegexTest
2006-07-19 11:31:19 来源:WEB开发网CRegex re(/* regex */);
re.SetInput(/* input */);
while (re.NextMatch()) {
int offset=0;
CString match = re.GetMatch(&offset);
...
}
CRegex 构造函数自动调用 Parse(你应该检查 m_err 看看是否出错),如果你想要单独分组匹配,可以调用 CRegex::GetNumGroups 来获取当前匹配的分组总数,调用 CRegex::GetGroup 获得每个分组匹配。具体细节如 Figure 7 所示。CRegex 在内部有其自己的 CAtlRegExp 和 CAtlREMatchContext 对象,并对其在输入串中位置进行跟踪——不必自己去做!
Figure 6 RegexTest 运行画面
我还添加了几个有用的特性,ATL 没有 regex Replace 函数,但添加一个并不难。有了框架的 regex 类,CRegex::Replace 得来全不费功夫,函数静态,这样你用不用 CRegex 对象调用都可以。例如,RegexTest 的主对话框使用静态版本来将新行(\n)转换为回车换行 CRLF(\r\n):
static CString LF2CRLF(LPCTSTR lpsz)
{
return CRegex::Replace(lpsz,_T("\n"),_T("\r\n"),TRUE);
}
就这么简单,如果没有 CRegex,直接用 CAtlRegExp 要数行代码才能做到。当你在微软的基本构件块上花点时间来做高层次的抽象,你就会出效率。这就是分层设计的本质所在。我甚至添加了一个与 .NET 框架类似的动态 Replace 函数,以便能用回调函数来实现动态替换算法,就像我四月份文章中 WordMess 程序所做的那样。最后,我添加了 Split,以便你能用正则表达式作为分隔符将某个字符串剥离到一个子串数组中。例如:
vector<CString> strs = CRegex::Split("one,two,three",",");
它返回有三个子串的向量数组:“one”,“two”,“three”。Split 的实现主要是字符串处理功夫,不过一旦你写就了代码,它就是你的并且永远受用。具体细节去参考源代码吧。
如果你决定使用 ATL 正则表达式或我封装的 CRegex,请谨慎:ATL 版本的正则比表达式是一个简化的,非标准的实现。我已经提到过它使用花括弧而不是圆括弧。ATL 还使用非标准的元字符(例如,用 \b 而不是 \s 表示空格),并且你无法在表示范围时([\a\d]不工作)使用元字符。特殊字符清单参见 Figure 8。请仔细阅读文档,提防 bug。复杂的正则表达式并不是总能凑效,你需要 #pragma 来抑制两个四级编译器警告(具体细节参见代码)。但如果你只需要一些基本的模式匹配来对用户输入进行有效性检查,ATL 是可以胜任的。
结束本文之前,我想告诉 C++ fans 们正则表达式不日将肯定成为标准模板库的一部分。其实现很可能是基于 boost 的实现,你可以从 boost.org 得到它。
更多精彩
赞助商链接