使用 ATL 在 C++ 中实现的正则表达式包装器
一篇关于易于使用的正则表达式封装的文章。
引言
正则表达式广泛应用于数据解析和分析。例如,可以使用正则表达式解析网页中的所有链接。
C++ 中有很多正则表达式库。我使用的是 Microsoft Visual Studio 2005 提供的 CAtlRegExp。
注意:CAtlRegExp 定义在 atlrx.h 中,该文件仅包含在 Visual Studio 2005 中。但是,您也可以通过将 atlrx.h 复制到 C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\ 或项目文件夹中,在 Visual Studio 2008 中使用它。
背景
STL vector 被用作输出,因为它在这种情况下易于使用且速度很快。您可能需要先了解一下 STL vector。
Using the Code
您可以从 CAtlRegExp 类 获取正则表达式语法。我的代码中只有一个函数。该函数解析源并将其结果推送到一个 vector 中。
/*
* Parameters
* [in] regExp: Value of type string which is the input regular expression.
* [in] caseSensitive: Value of type bool which indicate whether the parse is case
* sensitive.
* [in] groupCount: Value of type int which is the group count of the regular expression.
* [in] source: Value of type string reference which is the source to parse.
* [out] result: Value of type vecotr of strings which is the output of the parse.
* [in] allowDuplicate: Value of type bool which indicates whether duplicate items
* are added to the output result.
*
* Return Value
* Returns true if the function succeeds, or false otherwise.
*
* Remarks
* The output result is devided into groups. User should get the groups according
* to the group count. For example:
* 1. RegExp = L"{ab}", source = L"abcabe", then result = L"ab", L"ab".
* 2. RegExp = L"{ab}{cd}", source = L"abcdeabecd", then result = L"ab", L"cd", L"ab",
* L"cd".
*/
bool ParseRegExp(const wstring ®Exp,
bool caseSensitive,
int groupCount,
const wstring &source,
vector<wstring> &result,
bool allowDuplicate = false);
我认为注释已经清楚地解释了用法,所以让我们来看一些例子。
- 从字符串 product: Bowling ball; price: $199; 中获取产品名称。
wstring source = L"product: Bowling ball; price: $199; ";
wstring regExp = L"product: {.*?};";
vector<wstring> result;
if (ParseRegExp(regExp, false, 1, source, result)
&& result.size() > 0)
{
wprintf(L"products name: %s\n", result[0].c_str());
}
很简单,对吧?
- 让我们看一个更复杂的例子。有时,我们需要解析网页中的 select 元素。HTML 代码如下所示。
<select name="imagesize" style="margin:2px 0" onchange="_isr_load(this)">
<option value="/images?q=test&imgsz=" selected>All image sizes</option>
<option value="/images?q=test&imgsz=huge" >Extra Large images</option>
<option value="/images?q=test&imgsz=xxlarge" >Large images</option>
<option value="/images?q=test&imgsz=small|medium|large|xlarge" >
Medium images</option>
<option value="/images?q=test&imgsz=icon" >Small images</option>
</select>
源代码如下所示。
wstring source = ¡;
wstring regExp = L"<select.*?>{.*?}</select>";
vector<wstring> optionsAllResult;
if (ParseRegExp(regExp, false, 1, source, optionsAllResult, false)
&& optionsAllResult.size() == 1)
{
regExp = L"<option value=\"{.*?}\".*?>[\r\t\n ]*{.*?}[\r\t\n ]*</option>";
vector<wstring> optionsResult;
if (ParseRegExp(regExp, false, 2, optionsAllResult[0], optionsResult)
&& optionsResult.size() > 0
&& optionsResult.size() % 2 == 0)
{
for (vector<wstring>::size_type index = 0; index < optionsResult.size(); index += 2)
{
wprintf(L"Option: %s\n", optionsResult[index + 1].c_str());
wprintf(L"Value: %s\n", optionsResult[index].c_str());
wprintf(L"\n");
}
}
}
The output is:
Option: All image sizes
Value: /images?q=test&imgsz=
Option: Extra Large images
Value: /images?q=test&imgsz=huge
Option: Large images
Value: /images?q=test&imgsz=xxlarge
Option: Medium images
Value: /images?q=test&imgsz=small|medium|large|xlarge
Option: Small images
Value: /images?q=test&imgsz=icon
关注点
我将编译器的警告级别设置为 Level 4,并在选项“将警告视为错误”上设置为 true。这真的很有帮助。
历史
初始版本。