0

这是我在 MFC 应用程序中用于检查正则表达式匹配的代码:

int CDouserApp::FindMatches(std::vector<std::wstring>& output, 
        const std::wstring& input, 
        const std::wstring& pattern)
{
    std::tr1::wregex rx(pattern);
    std::tr1::wsmatch results;

    output.clear();
    if (!(std::tr1::regex_search(input, results, rx)))
    {
        return 0;
    }

    for (auto& r : results)
    {
        output.push_back(r.str());
    }

    return output.size();
}

void CDouserView::OnClickedSearch()
{
    std::vector<std::wstring> ret;
    std::wstring pattern(this->regexList.GetWindowTextLength() + 1, 0);
    this->regexList.GetWindowText(&pattern[0], pattern.length());
    std::wstring input(this->inputEdit.GetWindowTextLength() + 1, 0);
    this->inputEdit.GetWindowText(&input[0], input.length());
    CDouserApp::FindMatches(ret, input, pattern);
    this->resultsList.DeleteAllItems();
    std::wstringstream resultsStatus;
    resultsStatus << ret.size() << " result(s)";
    static_cast<CMainFrame*>(::AfxGetMainWnd())->GetStatusBar()
        .SetWindowText(resultsStatus.str().c_str());
    for (auto& match : ret)
    {
        this->resultsList.InsertItem(LVIF_TEXT, match.c_str());  
    }
}

如果我使用<h(.)>([^<]+)and<h2>Egg prices</h2>作为输入,即使它应该匹配“2”和“鸡蛋价格”,我也会得到 0 个结果。如果我Hello用作正则表达式和Hello, world!输入字符串,即使它应该与“Hello”匹配,我也会得到 0 个结果。

我什至尝试将输入和模式转换为 ASCII 并使用非宽std::regex系列,但结果是相同的。迄今为止,唯一匹配任何内容的模式是.*匹配整个字符串。

我知道 gcc 的正则表达式库已损坏,但我之前在 MSVC 中使用过 std::regex 并且没有遇到问题。如果可以避免的话,我想避免使用 boost::regex 或 pcre。

更新/编辑:此代码出于某种原因有效:

static void RegexTest(void)
{
    std::tr1::wregex rx1(L"<h(.)>([^<]+)");
    std::wstring input1(L"<h2>Egg prices</h2>");
    std::tr1::wregex rx2(L"Hello");
    std::wstring input2(L"Hello, world!");
    std::tr1::wsmatch results;

    if (!(std::tr1::regex_search(input1, results, rx1)))
    {
        ::MessageBox(nullptr, L"No matches found", L"Done", MB_OK | MB_ICONASTERISK);
    }
    else
    {
        std::wstringstream s;
        s << results.size() << " match(es) found:" << std::endl;
        for (auto& m : results)
        {
            s << m.str() << std::endl;
        }

        ::MessageBox(nullptr, s.str().c_str(), L"Done", MB_OK | MB_ICONINFORMATION);
    }

    if (!(std::tr1::regex_search(input2, results, rx2)))
    {
        ::MessageBox(nullptr, L"No matches found", L"Done", MB_OK | MB_ICONASTERISK);
    }
    else
    {
        std::wstringstream s;
        s << results.size() << " match(es) found:" << std::endl;
        for (auto& m : results)
        {
            s << m.str();
        }

        ::MessageBox(nullptr, s.str().c_str(), L"Done", MB_OK | MB_ICONINFORMATION);
    }
}

最终更新(和解决方案):

经过大量分析和测试,我发现我必须从字符串中删除空终止符:

void CDouserView::OnClickedSearch()
{
    std::vector<std::wstring> ret;
    std::wstring pattern(this->regexList.GetWindowTextLength() + 1, 0);
    this->regexList.GetWindowText(&pattern[0], pattern.length());
    pattern.resize(pattern.length() - 1);
    std::wstring input(this->inputEdit.GetWindowTextLength() + 1, 0);
    this->inputEdit.GetWindowText(&input[0], input.length());
    input.resize(input.length() - 1);
    CDouserApp::FindMatches(ret, input, pattern);
    this->resultsList.DeleteAllItems();
    std::wstringstream resultsStatus;
    resultsStatus << ret.size() << " result(s)";
    static_cast<CMainFrame*>(::AfxGetMainWnd())->GetStatusBar()
        .SetWindowText(resultsStatus.str().c_str());
    for (auto& match : ret)
    {
        this->resultsList.InsertItem(LVIF_TEXT, match.c_str());  
    }
}

问题是 GetWindowText 在写入字符串的同时还添加了一个空终止符;STL 字符串认为这个空终止符实际上是数据的一部分。我不知道为什么 Dinkumware 在输入字符串末尾存在这个额外的 null 时会遇到这样的困难。我还没有用 Boost 测试它,看看它是否有同样的陷阱,但我怀疑它没有。

4

3 回答 3

0

正则表达式中的匹配函数不能那样工作。

当您使用正则表达式<h(.)>([^<]+)并检查匹配字符串<h2>Egg prices</h2>时,正则表达式将检查正则表达式是否匹配整个字符串,在这种情况下,这只匹配<h2>Egg prices不匹配<h2>Egg prices</h2>(请参见此处的示例)。如果要检测字符串内部是否包含一些正则表达式模式,则应在其前后添加通配符,例如.*<h(.)>([^<]+).*

于 2013-08-10T17:12:55.543 回答
0

str.resize(str.length() - 1);

从字符串中删除 C 风格的空终止符可以解决所有问题。它认为 null 是导致它每次都失败的实际表达式模式的一部分。

于 2013-08-11T16:48:37.373 回答
0

您认为正则表达式分组符号 () 将提供匹配是不正确的。用于反向引用。这将匹配类似“ <h2>dsdsd”的内容。您想要的是一个正则表达式,它实际上表示(完整地)标签内的文本。由于我不熟悉您使用的正则表达式风格......我无法为您提供。

一切顺利。

于 2013-08-10T16:22:52.523 回答