Это правильный подход, чтобы написать код strstr через указатели в c? - PullRequest
0 голосов
/ 11 сентября 2010
char* fstrstr(char *s1,char *s2)
{
    int i=0,flag=0;
    char *s4,*s3;
//  s4 for retaining the value of s2
    s4 = s2;
    while(*s1 != '\0' && *s2 != '\0')
    {
        if(*s1 == *s2)
        {
            *(s3+i) = *s1;
            s2++;
            s1++;
            i++;
            flag = 1;
        }
        else
        {
            i = 0;
            s1++;
//          Initialize s2 again from its address
            s2 = s4;
            flag = 0;
        }
    }
    if(flag == 1)
    {
        while(*s1 != '\0')
        {
            *(s3+i) = *s1;
            i++;
            s1++;
        }
        *(s3+i) = '\0';
    }
    if(flag == 1)
        return (s3);

    if(flag==0)
    {
        *s3 = NULL;
        return (s3);
    }
}

Ответы [ 4 ]

4 голосов
/ 11 сентября 2010

Правильный подход заключается в создании ваших тестовых случаев (желательно сначала, на мой взгляд, но это не является абсолютно необходимым).Создайте модульные тесты для успешных и неуспешных случаев, включая любые сложные случаи.

И еще одно предложение - использовать достойные имена переменных.Многословие не делает ваш скомпилированный код медленнее, но делает намного более удобочитаемым и поддерживаемым.

Я бы, вероятно, также использовал индексы вместо указателей.Не потому, что я их не понимаю, просто потому, что я часто нахожу, что они способствуют удобочитаемости, и приличные компиляторы генерируют один и тот же код под обложками.

Предлагаемые тестовые примеры (для начала):

  • успешный поиск в начале строки.
  • успешный поиск в середине строки.
  • успешный поиск в конце строки.
  • строка не найдена.
  • большая часть найденной строки.
  • с передачей значения NULL в качестве любого аргумента.
  • пустых строк в качестве аргументов.

Судя по вашемукод, кажется, вы пытаетесь скопировать строку в другое место (возможно, завершается нулем), а затем вернуть адрес , что .Это не совсем то, как работает ISO strstr.Он просто возвращает местоположение первого байта в строке содержимого , которая соответствует строке поиска.

Таким образом, упрощенная реализация (минимальная оптимизация, даже если приличный компилятор, вероятно, все равно обработает большую часть этого)) может быть простым:

#include <stdio.h>
#include <string.h>

char * fstrstr (char *needle, char *haystack) {
    int nlen, npos, hlen, hpos, hpos2;

    // If length of needle is 0, it's defined as found at start.

    if (*needle == 0) {
        return haystack;
    }

    // Ensure strlen only calculated once.

    nlen = strlen (needle);
    hlen = strlen (haystack);

    // Check every possible position in haystack.

    for (hpos = 0; hpos < hlen - nlen+1; hpos++) {
        // Check each character, ensuring common subexpression elimination.

        for (npos = 0, hpos2 = hpos; npos < nlen; npos++, hpos2++) {
            // No match, break early.

            if (needle[npos] != haystack[hpos2]) {
                break;
            }
        }

        // No early break, we found a match.

        if (npos == nlen) {
            return &(haystack[hpos]);
        }
    }

    // No match anywhere, return NULL.

    return NULL;
}

static char *xlat(char *p) {
    if (p == NULL) return "NULL";
    return p;
}

int main (void) {
    printf ("%s\n", xlat(fstrstr ("hel","hello world")));
    printf ("%s\n", xlat(fstrstr ("el","hello world")));
    printf ("%s\n", xlat(fstrstr ("orl","hello world")));
    printf ("%s\n", xlat(fstrstr ("rld","hello world")));
    printf ("%s\n", xlat(fstrstr ("d","hello world")));
    printf ("%s\n", xlat(fstrstr ("","hello world")));
    printf ("%s\n", xlat(fstrstr ("xyz","hello world")));
    printf ("%s\n", xlat(fstrstr ("xyz","")));
    return 0;
}

, который выводит:

hello world
ello world
orld
rld
d
hello world
NULL
NULL

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

1 голос
/ 11 сентября 2010

Вы не инициализируете s3, поэтому результат *(s3+i) = *s1 не определен (читай: скорее всего, сбой).

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

Я бы сказал, нет, это не правильный путь.Он не только имеет серьезные ошибки (например, использование s3, о котором упоминали другие), но он также

  1. намного длиннее и сложнее, с более чем вдвое большим количеством переменных, необходимых дляреализация этого конкретного алгоритма поиска строки.
  2. очень очень неоптимальный алгоритм, O(nm), где n - длина строки, подлежащей поиску, а m - длина строки шаблона.

Вот хороший справочник по алгоритмам поиска строк:

http://www -igm.univ-mlv.fr / ~ lecroq / string / index.html

Если вы не собираетесь использовать один из высокопроизводительных, который особенно подходит для вашего набора данных, вероятно, будет ошибкой не просто использовать функцию strstr стандартной библиотеки.

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

Я попробовал эту функцию в коде, и она вылетает.

Одной из проблем является строка:

*(s3+i) = *s1;

Здесь вы присваиваете значение месту для мусора, так как s3 не былвыделил любую память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...