I just had to write this for one of my projects, matches a pattern where * matches 0 to many characters and ? matches exactly 1.
//Matches string against a pattern and returns
//true if the string matches. Returns false if
//the length of the pattern is > 1024.
bool AccessDatabase::wcMatch(const char *pattern, const char *string) {
char *p;
char *pString;
char buffer[1024];
memset(buffer, 0, 1024);
if (!strcmp(pattern, "*"))
return true;
if (strlen(pattern) > 1024)
return false;
//filter out repeat '*' from the pattern
p = buffer + 1;
buffer[0] = *pattern;
for (char *pTmp = (char *)(pattern + 1); *pTmp; ++pTmp) {
if (!(*pTmp == '*' && *(pTmp - 1) == '*'))
(*p++) = *pTmp;
}
p = buffer;
pString = (char *)string;
for (p = buffer; *p; ++p) {
if (*p == '?') {
if (!*pString) return false;
++pString;
}else if (*p == '*') {
char next = *(p + 1);
if (!next) {
return true;
}else if (next == '?') {
next = *(p + 2);
if (!next) return false;
}
while (*pString != next && *pString)
++pString;
if (!pString)
return false;
}else if (*p == *pString) {
++pString;
}else {
return false;
}
}
return true;
}
The whole 1024 thing is because I can safely assume that length due to the source of my patterns for this function. If you wish to use this elsewhere id probably recommend allocating a properly sized buffer based on strlen() of the pattern.
Tell me if you see any bugs ;)
It's buggy. :) You check for a NULL pointer instead of a pointer to a null, in the handler for *. Also, it looks like it always returns false if you specfiy a pattern ending in "*?". For example, input: "abcdef", pattern: "a*?". Typical matchers would return true, letting a=a, *=bcde, ?=f. From a cursory reading, yours appears to return false.