Introduction
Simple wild card matching with ? and * is something that we use in our every day work just when opening a command prompt and using DIR and DEL.
But how can this be done correctly in your program?
OK, you can use regular expressions, and I recommend this when you already use a bunch of Boost, tr1 or STL stuff in your code. But sometimes, I like it easy and simple without tons of library code in the background. And because I saw a lot of wrong and in complex queries "wrong/failing" code, I just offer this small algorithm here.
Background
This wildcard matching function works just the same way as you expect and know it from the CMD.EXE DIR command.
Using the Code
The function just takes the string to check as a first argument and the mask with or without any wildcard characters as a second argument.
It returns true
if the strings match and false
if not. It isn't spectacular.
The characters ? and * are treated as wildcards.
A ? character matches exactly one character and doesn't match an empty string.
A * character matches any sequence of characters and an empty string too.
Other characters are compared caseless. I use CharUpper
and convert them to uppercase to perform this task. Feel free to use your own favorite way.
Because * matches any character sequence and an empty string WildcardMatch(_T(""),_T("*"))
returns true
.
The function itself and the documentation is easy and straight forward:
bool WildcardMatch(const TCHAR *pszString, const TCHAR *pszMatch)
{
while (*pszMatch)
{
if (*pszMatch==_T('?'))
{
if (!*pszString)
return false;
++pszString;
++pszMatch;
}
else if (*pszMatch==_T('*'))
{
if (WildcardMatch(pszString,pszMatch+1))
return true;
if (*pszString && WildcardMatch(pszString+1,pszMatch))
return true;
return false;
}
else
{
if (::CharUpper(MAKEINTRESOURCE(MAKELONG(*pszString++,0)))
!=::CharUpper(MAKEINTRESOURCE(MAKELONG(*pszMatch++,0))))
return false;
}
}
return !*pszString && !*pszMatch;
}
History
- 28 April, 2011 -- Version 1.0