C++ 带有通配符*与?的字符串匹配

题目:两个字符串,一个是普通字符串,另一个含有*和?通配符,*代表零个到多个任意字符,?代表一个任意字符,通配符可能多次出现。写一个算法,比较两个字符串是否相等。

发现许多公司笔试面试都有这道题目,于是自己搜了一下,从redis源码util.c源文件中可以找到这么一个函数,实际上glib中也有类似的实现

int stringmatch(const char *pattern, const char *string, int nocase) {
    return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase)

}

stringmatch可以满足上述题目的要求

 

#include <iostream>  
#include <string.h>
using namespace std;  

int stringmatchlen(const char *pattern, int patternLen,
        const char *string, int stringLen, int nocase)
{
    while(patternLen) {
        switch(pattern[0]) {
        case '*':
            while (pattern[1] == '*') {
                pattern++;
                patternLen--;
            }
            if (patternLen == 1)
                return 1; /** match */
            while(stringLen) {
                if (stringmatchlen(pattern+1, patternLen-1,
                            string, stringLen, nocase))
                    return 1; /** match */
                string++;
                stringLen--;
            }
            return 0; /** no match */
            break;
        case '?':
            if (stringLen == 0)
                return 0; /** no match */
            string++;
            stringLen--;
            break;
        case '[':
        {
            int inot, match;

            pattern++;
            patternLen--;
            inot = pattern[0] == '^';
            if (inot) {
                pattern++;
                patternLen--;
            }
            match = 0;
            while(1) {
                if (pattern[0] == '\\') {
                    pattern++;
                    patternLen--;
                    if (pattern[0] == string[0])
                        match = 1;
                } else if (pattern[0] == ']') {
                    break;
                } else if (patternLen == 0) {
                    pattern--;
                    patternLen++;
                    break;
                } else if (pattern[1] == '-' && patternLen >= 3) {
                    int start = pattern[0];
                    int end = pattern[2];
                    int c = string[0];
                    if (start > end) {
                        int t = start;
                        start = end;
                        end = t;
                    }
                    if (nocase) {
                        start = tolower(start);
                        end = tolower(end);
                        c = tolower(c);
                    }
                    pattern += 2;
                    patternLen -= 2;
                    if (c >= start && c <= end)
                        match = 1;
                } else {
                    if (!nocase) {
                        if (pattern[0] == string[0])
                            match = 1;
                    } else {
                        if (tolower((int)pattern[0]) == tolower((int)string[0]))
                            match = 1;
                    }
                }
                pattern++;
                patternLen--;
            }
            if (inot)
                match = !match;
            if (!match)
                return 0; /** no match */
            string++;
            stringLen--;
            break;
        }
        case '\\':
            if (patternLen >= 2) {
                pattern++;
                patternLen--;
            }
            /** fall through */
        default:
            if (!nocase) {
                if (pattern[0] != string[0])
                    return 0; /** no match */
            } else {
                if (tolower((int)pattern[0]) != tolower((int)string[0]))
                    return 0; /** no match */
            }
            string++;
            stringLen--;
            break;
        }
        pattern++;
        patternLen--;
        if (stringLen == 0) {
            while(*pattern == '*') {
                pattern++;
                patternLen--;
            }
            break;
        }
    }
    if (patternLen == 0 && stringLen == 0)
        return 1;
    return 0;
}

int stringmatch(const char *pattern, const char *string, int nocase) {
    return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);
}
int main(int argc, const char *argv[])
{
    char s1[100],s2[100];
    while ( cin>>s1>>s2) {
        if(stringmatch(s1,s2,true){
            std::cout << "yes" << std::endl;
        }else{
            std::cout << "no" << std::endl;
        }

    }
    return 0;
}  

 

测试截图



posted @ 2013-10-18 19:48  godjob  Views(5632)  Comments(0Edit  收藏  举报