Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A Simple Wildcard Matching Function

, 28 Apr 2011 CPOL
A Simple Wildcard Matching Function
WildcardMatch.zip
WildcardMatch.vcxproj.filters
WildcardMatch.vcxproj.user
// 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)

Share

About the Author

Martin Richter [MVP C++]
Software Developer (Senior)
Germany Germany
MVP for C++ in Germany since 2000
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/

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150414.1 | Last Updated 28 Apr 2011
Article Copyright 2011 by Martin Richter [MVP C++]
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid