C, аналог strstr и кол-во вхождений подстроки в строку

Программа получает 1 аргументом подстроку, а последующими строки. Если в последующих строках есть подстрока(подстроки), то нужно вывести на экран эту строку и кол-во вхождений в неё подстроки:

#include <stdio.h>

char *sub_string(const char *str, const char *s_str); /*str - строка, s_str - подстрока*/

int main(int argc, char **argv)
{
        int i, count, ssl;
        char *str;
        argv++;
        if(argc < 2){
                fprintf(stderr, "Incorrect args\n");
                return 1;
        }
        for(ssl = 0; (*argv)[ssl]; ssl++); /*ssl = (длина подстроки с '\0' символом) - 1*/
        puts("Args with substring:");
        for(i = 1; argv[i]; i++){
                count = 0;
                str = argv[i];
                while(sub_string(str, *argv)){
                        count++;
                        str += ssl;
                }
                if(count > 0)
                        printf("%s, substring's count: %d\n", argv[i], count);
        }
        return 0;
}

char *sub_string(const char *str, const char *s_str)
{
        char *str_ptr, *s_str_ptr;
        int trigger;
        while(*str){
                if(*str == *s_str){
                        trigger = 1;
                        str_ptr = str;
                        s_str_ptr = s_str;
                        while(*str_ptr && *s_str_ptr){
                                trigger &= (*str_ptr == *s_str_ptr);
                                str_ptr++;
                                s_str_ptr++;
                        }
                        if(trigger && !(*str_ptr) && *s_str_ptr)
                                return NULL;
                        if(trigger)
                                return str;
                }
                str++;
        }
        return NULL;
}

Вопрос:

При вызове программы с такими аргументами: ./prog "asd" "1asd2asd3asd" мне выдает 1asd2asd3asd, substring's count: 4. Почему???

Если в цикл

                    while(sub_string(str, *argv)){
                            printf("%s\n", sub_string(str, *argv));
                            count++;
                            str += ssl;
                    }

добавить printf("%s\n", sub_string(str, *argv));

то будет вывод:

asd2asd3asdd
asd3asdd
asdd
asdd

Почему там asdd дважды??? После 3 итерации должно остаться d и функция должна вернуть NULL, но она снова будто asdd принимает...

А при вызове ./prog "asd" "1asd2asdd" мне выдает 1asd2asdd, substring's count: 2. В чем дело? Не могу понять что не так с предыдущим (и подобными примерами) примером... Здесь тот же Printf в цикле выдаст

asd2asdd
asdd

то есть всё как надо. Запарился уже, что за бред )))


Ответы (1 шт):

Автор решения: KoVadim

Отвечу на первый вопрос - почему находит 4 строки. Все очень просто, предельно просто. На самом деле Ваш код ищет, а есть ли вхождение строки начиная с начала строки. Если нашло, то добавляет длину подстроки и снова проверяет. Возьмем исходную строку "1asd2asd3asd". Очевидно, что от начала строки подстрока asd есть. Теперь сдвигаемся на 3 символа (длина asd) и имеем строку "d2asd3asd" (тут также есть). Потом дальше двигаемся и имеем "sd3asd" (опять нашли) и последняя итерация дает "asd" и о чудо - снова нашло. Вот оно как. Что делать? Есть пара вариантов, но самое простое - просто проверять позицию найденной подспроки и её тоже приплюсовывать. Вот где то так

            str = argv[i];
            char * f = NULL; // инициализируем
            while((f = sub_string(str, *argv))){
                    count++;
                    // f хранит указатель, где нашли подстроку
                    str = f + ssl;
                    printf("str = %s\n", str);
            }

Но возможно, если подстрока для поиска такая adad, а строка, где идем, adadad, то тут ещё нужно хорошо подумать, какой должен быть правильный ответ. У меня пока получается 1, хотя кто то может сказать, что тут должно быть два. Но это легко исправляется заменой строки

str = f + ssl;

на строку

str = f + 1;

как правильно - решать Вам.

Я попытался исправить код минимальными правками. В целом, в функции поиска есть код с душком - к примеру, вот эта строка str_ptr = str; - слева - char*, справа - const char*.

→ Ссылка