home *** CD-ROM | disk | FTP | other *** search
- /* Wildcard.c by Frank J. Perricone
- Matches (recursively) wildcards * and ? (arbitrary number of them)
-
- This program was written solely to test my algorithm for wildcard matching.
- It is of no use in and of itself, so I release it as source code only to
- the public domain, unless someone has copyrighted this code before, in
- which case, my apologies, no offense intended.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
-
- #define TRUE 1
- #define FALSE 0
-
- /* Prototypes */
- int wildcardmatch(char *, char *);
- int wcm(char *,char *);
-
- int main(int argc, char *argv[]) {
- if (argc!=3) { /* we need two params to compare */
- fprintf(stderr,"Usage: WILDCARD pattern string\n");
- return 20;
- }
- if (wildcardmatch(argv[1],argv[2]))
- printf("%s matches %s.\n",argv[1],argv[2]);
- else
- printf("%s does not match %s.\n",argv[1],argv[2]);
- return 0;
- }
-
- int wildcardmatch(char *pattern, char *string) {
- /* Strip doubled asterisks, then call wcm which is recursive
- ---- That is, this routine simply runs a preparation phase on the pattern,
- ---- stripping out double (or more) asterisks (which are really meaningless
- ---- and can be reduced to one asterisk) and then calls wcm, which does the
- ---- real work.
- */
- char newpat[256]; /* build the new stripped pattern in the buffer */
- int i=0; /* counter in pattern */
- int j=0; /* counter in newpat */
- while (pattern[i]!='\0') { /* until we reach the end of the pattern */
- newpat[j]=pattern[i]; /* copy a character */
- if (pattern[i]=='*') { /* if it was an asterisk, */
- i++; /* starting with the next character, */
- while (pattern[i]=='*') /* scan past all ensuing asterisks */
- i++;
- }
- else
- i++; /* else just go to the next character */
- j++;
- }
- newpat[j]='\0'; /* put end-string marker on newpat */
- return wcm(newpat,string); /* now call wcm to do the real work */
- }
-
- int wcm(char *pattern, char *string) {
- /* Actually does matching; very recursive, especially if pattern[0]=='*'
- ---- The parameters are a pattern, which can contain an arbitrary number of
- ---- characters including wildcards, excepting that it has no doubled
- ---- asterisks. The asterisk matches 0 or more characters. The question mark
- ---- matches exactly one character. wcm just returns TRUE or FALSE.
- ---- It does this by breaking up all possibilities into cases described below.
- ---- The order they are shown is important, as many of them assume (and
- ---- therefore don't test for) the fact that previous cases didn't apply.
- */
- if (pattern[0]=='\0' && string[0]=='\0') /* both are null */
- return TRUE;
- if (pattern[0]=='\0') /* pattern null but string isn't */
- return FALSE;
- if (pattern[0]=='*' && pattern[1]=='\0') /* pattern just an asterisk */
- return TRUE; /* (this is an optimization) */
- if (string[0]=='\0') /* string null but pattern isn't */
- return FALSE;
- if (pattern[0]=='?') /* pattern starts with ? */
- return wcm(&(pattern[1]),&(string[1])); /* matches if the rest matches.. */
- if (pattern[0]=='*') { /* the biggie: pattern begins with
- an asterisk but has more, and
- string isn't null... */
- while (string[0]!='\0') { /* does it match if * matches 0 */
- if (wcm(&(pattern[1]),string)) /* chars of string? If not, how */
- return TRUE; /* about one? Or two? Keep */
- else /* trying until it does, or */
- string++; /* you run out of string... */
- } /* if we get out, we tried all possibilities without success... */
- return FALSE;
- }
- if (pattern[0]==string[0]) /* normal, matching characters */
- return wcm(&(pattern[1]),&(string[1]));
- /* if we got this far -- normal, nonmatching characters */
- return FALSE;
- }
-