为什么std :: regex_search与我的文本不匹配? (VS2012)

时间:2013-08-10 16:17:22

标签: c++ regex visual-c++ c++11

以下是我在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(.)>([^<]+)<h2>Egg prices</h2>作为输入,即使它与“2”和“鸡蛋价格”相匹配,我也会获得0结果。如果我使用Hello作为正则表达式并使用Hello, world!作为输入字符串,我得到0结果,即使它应该匹配“Hello”。

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

我知道gcc的正则表达式文件库坏了,但我之前使用过std :: regex和MSVC并没有出现问题。我想避免使用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字符串认为此null终止符实际上是数据的一部分。我不知道为什么Dinkumware在输入字符串的末尾存在这个额外的null这么困难。我还没有用Boost测试它,看看它是否有相同的陷阱,但我怀疑它没有。

3 个答案:

答案 0 :(得分:0)

您认为正则表达式分组符号()将提供匹配是错误的。这用于反向引用。这将匹配“<h2>dsdsd”之类的内容。你想要的是一个正则表达式,它实际上代表了标签内部(完整的)文本。因为我不熟悉你正在使用的正则表达式...我不能为你提供它。

一切顺利。

答案 1 :(得分:0)

正则表达式中的

匹配函数不能像那样工作。

当您使用正则表达式<h(.)>([^<]+)并检查匹配字符串<h2>Egg prices</h2>时,正则表达式将检查正则表达式是否与整个字符串匹配,在这种情况下,这只会匹配<h2>Egg prices而不是{{ 1}}(参见example here)。如果你想在字符串包含内部检测一些正则表达式,你应该在{I}之前和之后添加野性字符<h2>Egg prices</h2>

答案 2 :(得分:0)

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

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