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 шт):
Отвечу на первый вопрос - почему находит 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*.