开发者

strstr and occurrences to match

I have several possible occurrences to test with strstr.

if ((a = strstr(string, "FOO")) != NULL || (a = strstr(string, "BAR")) != NULL ||
    (a = strstr(string, "FOO2")) != NULL ||(a = strstr(string, "BAR2")) != NULL ||
    (a = strstr(string, "FOO3")) != NULL ||(a = strstr(string, "BAR3")) != NULL) // do som开发者_StackOverflow社区ething

and then based on the occurrence found I need to do

 var = strlen("THE_ONE_MATCHED_ABOVE");

What would be a good way to do this without using lots of if statements?


Are you willing to use the comma operator:

if ((lookfor = "FOO", a = strstr(string, lookfor)) != NULL ||
    (lookfor = "BAR", a = strstr(string, lookfor)) != NULL ||
    ...)
{
    var = strlen(lookfor);
}

The comma operator will allow you to evaluate multiple expression in left to right order. The value of the expression as a whole is the value of the rightmost esub-expression.


I have a feeling that your example is oversimplified, but it's probably worth noting that it can be simplified. If the string "FOO" isn't found, then you know the string "FOO2" won't be found so you can eliminate all but the first two cases in your example.


int match_length( const char* string) {
/* return 0 if no match, otherwise strlen of match */

   static const char* const MATCHES[] = { "BAR2", "FOO2", "FOO3", "FOO", "BAR", "..." } ;
   // NB: MATCHES must be sorted in descending order of length (longest first).
   const char* r = 0;
   int i = 0 ;

   for( ; 
        i < sizeof(MATCHES) / sizeof(MATCHES[0]) 
        && ( r = strstr( string, MATCHES[i] ) ) == 0; 
        ++i );

   return r ? strlen( MATCHES[i] ) : 0 ;
}

Note: caf makes a very important point: "You need to arrange the MATCHES in descending length order - if strstr(x, "FOO2") is non-null, then so is strstr(x, "FOO"), so you need to find the former first." I've editted to reflect this. Depending on the use of this function, the sort might also be done at runtime.


If you have a lot of patterns to look for in subject string, the best choice is Aho-Corasick algorithm:


If you have a large varying set of strings you need to search for this way, you should probably use a regular expression library and compile a DFA to match (FOO|FOO2|FOO3|...). This is the optimal solution. You could also work out the tree structures to implement the same result yourself, especially if the strings to search for are constant and you can hard-code them efficiently.


If you use that pattern frequently within your code, you should write a small helper function like this:

int FindFirstMatch(const char* stringItem, const char** stringList)
{
    int index = -1;
    int itemLength = strlen(stringItem);

    if (stringList == NULL)
    {
        return index;
    }

    for (; stringList[index] != NULL; index++)
    {
            if (  (strlen(stringList[index]) == itemLength)
               && (strstr(stringList[index], stringItem) != NULL))
        {
            break;
        }
    }
    return index;
}

The function takes a string and a NULL terminated string array as arguments and returns the index of the first occurence of the string in the list. You can then use the index to check fo the string length.

To do a check as you did in your example you would instead write:

const char* itemList[] = {"FOO", "FOO2", "FOO3", "BAR", "BAR2", "BAR3", NULL};
int itemLength = 0;

int index = FindFirstMatch("BAR3", itemList);
if (index != -1)
{
    itemLength = strlen(itemList[index]);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜