HiveBrain v1.2.0
Get Started
← Back to all entries
principlecsharpMinor

Compare string with wildcard string

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withcomparestringwildcard

Problem

I have the following function to compare a string with a wildcard string (containing ? and *), as C# doesn't seem to have a builtin function to do it.

```
///
/// Compares wildcard to string
///
/// String to compare
/// Wildcard mask (ex: *.jpg)
/// True if match found
public static bool CompareWildcard(string WildString, string Mask, bool IgnoreCase = true)
{
int i = 0, k = 0;

// Cannot continue with Mask empty
if (string.IsNullOrEmpty(Mask))
return false;

// If WildString is null -> make it an empty string
if (WildString == null)
WildString = string.Empty;

// If Mask is * and WildString isn't empty -> return true
if (string.Compare(Mask, "*") == 0 && !string.IsNullOrEmpty(WildString))
return true;

// If Mask is ? and WildString length is 1 -> return true
if (string.Compare(Mask, "?") == 0 && WildString.Length == 1)
return true;

// If WildString and Mask match -> no need to go any further
if (string.Compare(WildString, Mask, IgnoreCase) == 0)
return true;

while (k != WildString.Length)
{
switch (Mask[i])
{
case '*':

if ((i + 1) == Mask.Length)
return true;

while (k != WildString.Length)
{
if (CompareWildcard(WildString.Substring(k + 1), Mask.Substring(i + 1), IgnoreCase))
return true;

k += 1;
}

return false;

case '?':

break;

default:

if (IgnoreCase == false && WildString[k] != Mask[i])
return false;

if (IgnoreCase && Char.ToLower(WildString[k]) != Char.ToLower(Mask[i]))
return false;

Solution

What you want to do is called "globbing". It's actually quite easy to do with a Regex.

There are a few code smells here. The recursion is the obvious one. The other is the special-cases. When you special-case the single-character wildcard, it suggests that you're thinking about the problem wrong. There's no reason why they would need to -- or even should -- be specialcased.

If you really want to reinvent the wheel, the "right way" is to build a state machine and backtrack. I combined @NotPro's answer and @svick's hint to get http://ideone.com/VUDFIw but that uses backtracking. Check out http://swtch.com/~rsc/regexp/regexp1.html to see why backtracking is a bad idea, and how we can get an O(n) state machine.

Context

StackExchange Code Review Q#55379, answer score: 7

Revisions (0)

No revisions yet.