strstr и совпадения - PullRequest
       20

strstr и совпадения

1 голос
/ 28 апреля 2010

У меня есть несколько возможных случаев для тестирования с 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 something

и затем на основании найденного случая мне нужно сделать

 var = strlen("THE_ONE_MATCHED_ABOVE");

Что было бы хорошим способом сделать это без использования большого количества операторов if?

Ответы [ 6 ]

2 голосов
/ 28 апреля 2010

У меня такое ощущение, что ваш пример слишком упрощен, но, вероятно, стоит отметить, что его можно упростить. Если строка "FOO" не найдена, то вы знаете, что строка "FOO2" не будет найдена, поэтому вы можете исключить все, кроме первых двух случаев в вашем примере.

2 голосов
/ 28 апреля 2010
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 ;
}

Примечание: caf делает очень важный момент: «Вам нужно расположить МАТЧИ в порядке убывания длины - если strstr (x,« FOO2 ») не равен нулю, то и strstr (x,« FOO ») так что сначала нужно найти первое ». Я отредактировал, чтобы отразить это. В зависимости от использования этой функции сортировка может также выполняться во время выполнения.

2 голосов
/ 28 апреля 2010

Желаете ли вы использовать запятую:

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

Оператор запятой позволит вам оценить несколько выражений в порядке слева направо. Значение выражения в целом является значением самого правого выражения esub.

1 голос
/ 28 апреля 2010

Если у вас есть много шаблонов для поиска в строке темы, лучшим выбором будет алгоритм Aho-Corasick :

0 голосов
/ 20 сентября 2010

Если у вас большой изменяющийся набор строк, который необходимо найти таким образом, вам, вероятно, следует использовать библиотеку регулярных выражений и скомпилировать DFA для соответствия (FOO|FOO2|FOO3|...). Это оптимальное решение. Вы также можете разработать древовидные структуры, чтобы реализовать тот же результат самостоятельно, особенно если строки для поиска являются постоянными и вы можете жестко их кодировать.

0 голосов
/ 28 апреля 2010

Если вы часто используете этот шаблон в своем коде, вы должны написать небольшую вспомогательную функцию, например:

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;
}

Функция принимает строку и массив строк с окончанием NULL в качестве аргументов и возвращает индекс первого вхождения строки в списке. Затем вы можете использовать индекс для проверки длины строки.

Чтобы выполнить проверку, как вы делали в своем примере, вы должны написать:

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]);
}
...