2015-11-22 3 views
0

Хорошо, я не уверен, что это я или что-то еще, но я действительно смущен.C strcmp ведет себя странно

Im пытается найти первое появление строки внутри другой строки (как и InString() из C++), но из C и делает это с помощью strcmp().

У меня есть два массива символов, строка [] и toFind [], и im проходят через них в двух циклах for(), сравнивающих каждый символ с strcmp().

Вот код:

int inString(char string[], char toFind[]){ 

int i_toFind, i_string, check = 0, start = -1; 

for(i_toFind = 0; i_toFind < getLength(toFind)-1; i_toFind++){ 

    for(i_string = 0; i_string < getLength(string)-1; i_string++){ 

     if(strcmp(&string[i_string], &toFind[i_toFind])==0){ 

      printf("%i & %i == %i\n", string[i_string], toFind[i_toFind], strcmp(&string[i_string], &toFind[i_toFind])); 

      if(start == -1){ 
       start = i_string; 
      } 

      check++; 
      i_toFind++; 

      if(check == getLength(toFind)-1){ 
       return start; 
      } 

     } 
     else{ 

      printf("%i & %i == %i\n", string[i_string], toFind[i_toFind], strcmp(&string[i_string], &toFind[i_toFind])); 

      check = 0; 
      start = -1; 

     } 

    } 

} 

return -1; 

} 

Теперь это работает, например, для этого значения:

string[] = "hello my friend" 
toFind[] = "friend" 

result: 

104 & 102 == 2 
101 & 102 == -1 
108 & 102 == 6 
108 & 102 == 6 
111 & 102 == 9 
32 & 102 == -70 
109 & 102 == 7 
121 & 102 == 19 
32 & 102 == -70 
102 & 102 == 0 
114 & 114 == 0 
105 & 105 == 0 
101 & 101 == 0 
110 & 110 == 0 
100 & 100 == 0 

Но это не работает:

string[] = "friday friend comes" 
toFind[] = "friend" 

result: 

102 & 102 == -1 
114 & 102 == 12 
105 & 102 == 3 
100 & 102 == -2 
97 & 102 == -5 
121 & 102 == 19 
32 & 102 == -70 
102 & 102 == 22 
114 & 102 == 12 
105 & 102 == 3 
101 & 102 == -1 
110 & 102 == 8 
100 & 102 == -2 
32 & 102 == -70 
99 & 102 == -3 
111 & 102 == 9 
109 & 102 == 7 
101 & 102 == -1 
115 & 102 == 13 
102 & 114 == -12 
114 & 114 == -1 
105 & 114 == -9 
... 

Интересная часть это:

102 & 102 == -1 
114 & 114 == -1 

Должно ли это не быть равным 0? Или что мне здесь не хватает? Функция, которую я написал, кажется, терпит неудачу, если слово im search НЕ является последним в строке [].

Надеюсь, что кто-то действительно найдет мою ошибку .. Спасибо!

ОБНОВЛЕНИЕ:

код, где я запустить InString() только одна строка:

printf("Beginn: %i\n", inString(string, substring)); 

ОБНОВЛЕНИЕ 2:

Вот простой пример проблемы:

int inString(char string[], char toFind[]){ 

    const char *pointer_toStart = strstr(string, toFind); 

    return pointer_toStart ? pointer_toStart - string : -1; 

} 

int main(int argc, const char * argv[]) { 

    char string[300], substring[300]; 

    printf("String: "); 

    fgets(&test, 20, stdin); // To capture the one '\n' inside the buffer (just ignore this line) 
    fgets(string, 300, stdin); 

    printf("toFind: "); 

    fgets(substring, 300, stdin); 

    printf("Beginn: %i\n", inString(string, substring)); 

} 
+2

Вы не можете использовать 'strcmp' для сравнения отдельных символов. –

+0

Поскольку вы используете функции c string, почему бы не заменить 'getLength' на' strlen'? – Alexguitar

+4

Возможно, strstr() может использоваться. – balabhi

ответ

5

Вы не можете использовать strcmp для сравнения частей строк C, вы можете использовать memcmp для этого. Но есть более простой подход к вашему вопросу, используя strstr.

Ниже приведена простая реализация inString в соответствии с вашей неявной спецификацией.

#include <string.h> 

int inString(const char *string, const char *toFind) { 
    const char *p = strstr(string, toFind); 
    return p ? p - string : -1; 
} 

Функция возвращает начальный индекс подстроки, если найден и -1, если не найден.

С этой реализации, следующий тест правильно печатает 25:

#include <stdio.h> 

int main(void) { 
    char string[] = "Friede freude Eierkuchen freuen sich freundlich"; 
    char toFind[] = "freuen"; 

    printf("inString(\"%s\", \"%s\") -> %d\n", string, toFind, inString(string, toFind)); 
    return 0; 
} 

В тестовом коде, вы используете fgets читать строки из стандартного ввода. Обе строки, скорее всего, содержат финальный номер '\n', поэтому вы не найдете совпадения для "freuen\n", если только в конце string, который также имеет окончательный номер '\n'. Исправьте это, удалив '\n'.Вот простой способ лишить его, что также работает, если она не существует:

string[strcspn(string, "\n")] = '\0'; 
toFind[strcspn(toFind, "\n")] = '\0'; 
+0

wow Спасибо за ответ! Не могли бы вы объяснить мне, что делает последняя строка (где возвращается значение)? (Никогда не видел этот синтаксис tho ..) – user1641602

+0

Тернарный оператор подобен выражению if/then/else. последняя строка может быть записана следующим образом: 'if (p! = NULL) return p - string; else return -1; '. Компилятор, вероятно, будет генерировать тот же самый код для обеих версий. – chqrlie

+0

Большое спасибо! к сожалению, он также не работает для всех строк: string [] = "friede freude eierkuchen freuen sich freundlich" | toFind [] = "freuen" | result = -1 – user1641602

0

Хорошо, в первую очередь, во многом благодаря chqrlie за помощь мне, что много, и указал мне в правильном направлении.

Я попробовал то, что вы упомянули, удалив '\ n' из строки [] и toFind [], но я все еще закончил с той же проблемой.

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

int inString(char string[], char toFind[]){ 

    int i_toFind, i_string, check = 0, start = -1; 

    for(i_toFind = 0; i_toFind < getLength(toFind)-1; i_toFind++){ 

     for(i_string = 0; i_string < getLength(string); i_string++){ 

     if(memcmp(&string[i_string], &toFind[i_toFind], 1)==0){ 

      if(start == -1){ 

      start = i_string; 

      } 

      check++; 
      i_toFind++; 

      if(check == getLength(toFind)-1){ 
      return start; 
      } 

     } 
     else{ 

     i_toFind = i_toFind - check; 

     check = 0; 
     start = -1; 

     } 

     } 

    } 

    return -1; 

} 

действительно дает мне также 25 на примере, приведенном выше.

+0

Ваша функция все еще слишком сложна. Вместо использования 'memcmp' для сравнения 1 байт за раз, для которого достаточно простого оператора' == ', используйте его для сравнения' strlen (toFind) 'байтов в последовательных позициях в' string', от '0' до 'strlen (string) -strlen (toFind)' включительно.Сначала вычислите длины строк amd, используя один цикл 'for' для тестов, верните первое совпадающее смещение и' -1', если все сравнения завершились с ошибкой. – chqrlie

Смежные вопросы