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

简单的通配符匹配函数

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (17投票s)

2011年4月28日

CPOL

1分钟阅读

viewsIcon

74066

downloadIcon

614

简单的通配符匹配函数

引言

使用 ? 和 * 进行简单的通配符匹配是我们日常工作中经常会做的事情,比如在打开命令提示符并使用 DIR 和 DEL 命令时。

但是如何在你的程序中正确地实现这个功能呢?

当然,你可以使用正则表达式,如果你的代码中已经使用了大量的 Boost、tr1 或 STL 组件,我推荐这样做。 但有时候,我喜欢简单易懂,避免在后台使用大量的库代码。 而且由于我看到很多错误且复杂的查询代码,所以我在这里提供这个小算法。

背景

这个通配符匹配函数的工作方式与你从 CMD.EXE DIR 命令中预期的完全一样。

Using the Code

该函数将要检查的字符串作为第一个参数,将包含或不包含任何通配符的掩码作为第二个参数。
如果字符串匹配,则返回 true,如果不匹配,则返回 false。 它并不特别复杂。

字符 ? 和 * 被视为通配符。
? 字符匹配正好一个字符,并且不匹配空字符串。
* 字符匹配任何字符序列,也匹配空字符串。
其他字符进行不区分大小写的比较。 我使用 CharUpper 并将它们转换为大写来执行此任务。 随意使用你自己的方法。

因为 * 匹配任何字符序列和空字符串,所以 WildcardMatch(_T(""),_T("*")) 返回 true

该函数本身和文档都很简单直观。

//////////////////////////////////////////////////////////////////////////
//    WildcardMatch
//        pszString    - Input string to match
//        pszMatch    - Match mask that may contain wildcards like ? and *
//    
//        A ? sign matches any character, except an empty string.
//        A * sign matches any string inclusive an empty string.
//        Characters are compared caseless.

bool WildcardMatch(const TCHAR *pszString, const TCHAR *pszMatch)
{
    // We have a special case where string is empty ("") and the mask is "*".
    // We need to handle this too. So we can't test on !*pszString here.
    // The loop breaks when the match string is exhausted.
    while (*pszMatch)
    {
        // Single wildcard character
        if (*pszMatch==_T('?'))
        {
            // Matches any character except empty string
            if (!*pszString)
                return false;

            // OK next
            ++pszString;
            ++pszMatch;
        }
        else if (*pszMatch==_T('*'))
        {
            // Need to do some tricks.

            // 1. The wildcard * is ignored. 
            //    So just an empty string matches. This is done by recursion.
            //      Because we eat one character from the match string, the
            //      recursion will stop.
            if (WildcardMatch(pszString,pszMatch+1))
                // we have a match and the * replaces no other character
                return true;

            // 2. Chance we eat the next character and try it again, with a
            //    wildcard * match. This is done by recursion. Because we eat
            //      one character from the string, the recursion will stop.
            if (*pszString && WildcardMatch(pszString+1,pszMatch))
                return true;

            // Nothing worked with this wildcard.
            return false;
        }
        else
        {
            // Standard compare of 2 chars. Note that *pszSring might be 0
            // here, but then we never get a match on *pszMask that has always
            // a value while inside this loop.
            if (::CharUpper(MAKEINTRESOURCE(MAKELONG(*pszString++,0)))
		!=::CharUpper(MAKEINTRESOURCE(MAKELONG(*pszMatch++,0))))
                return false;
        }
    }

    // Have a match? Only if both are at the end...
    return !*pszString && !*pszMatch;
}

历史

  • 2011 年 4 月 28 日 -- 版本 1.0
© . All rights reserved.