Click here to Skip to main content
15,896,606 members
Articles / Programming Languages / C++

A Simple Wildcard Matching Function

Rate me:
Please Sign up or sign in to vote.
4.83/5 (17 votes)
28 Apr 2011CPOL1 min read 69.7K   596   26  
A Simple Wildcard Matching Function
// WildcardMatch.cpp : Defines the entry point for the console application.
//

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

//////////////////////////////////////////////////////////////////////////
//	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 were 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 than 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;
}

//////////////////////////////////////////////////////////////////////////
// Test function

void Test(const TCHAR *pszDesc, const TCHAR *pszText, const TCHAR *pszMask)
{
	_tprintf(_T("%-15sWildcardMatch(\"%s\",\"%s\") \treturns %d\n"),pszDesc,pszText,pszMask,WildcardMatch(pszText,pszMask));
}

int _tmain(int argc, _TCHAR* argv[])
{
	Test(_T("Empty string 1"),_T(""),_T("*"));
	Test(_T("Empty string 2"),_T(""),_T(""));
	Test(_T("Simple 1"),_T("MyName.doc"),_T("*.DOC"));
	Test(_T("Simple 2"),_T("MyName.docx"),_T("*.DOC"));
	Test(_T("Complex 1"),_T("MyNamName.docx"),_T("My*Name.*x"));
	Test(_T("Complex 2"),_T("MyNamName.docx"),_T("My*Name.*oc"));
	return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Germany Germany
MVP for C++ in Germany from 2000 up to 2015.
Developer since 1979, working with C/C++ since 1982
Started with Windows development in 1990

Love my bicycles (specially my recumbent) and geocaching
http://blog.m-ri.de/index.php/category/real-life/fahrrad/

Comments and Discussions