65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ATL 在 C++ 中实现的正则表达式包装器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (4投票s)

2008年12月10日

CPOL

1分钟阅读

viewsIcon

35580

downloadIcon

747

一篇关于易于使用的正则表达式封装的文章。

引言

正则表达式广泛应用于数据解析和分析。例如,可以使用正则表达式解析网页中的所有链接。

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);

我认为注释已经清楚地解释了用法,所以让我们来看一些例子。

  1. 从字符串 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());
}

很简单,对吧?

  1. 让我们看一个更复杂的例子。有时,我们需要解析网页中的 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。这真的很有帮助。

历史

初始版本。

© . All rights reserved.