2013-06-08 2 views
2

Существует ли подходящий способ сравнения двух char-массивов, если они не равны по длине? Как проверить, какой символ не равен?Правильный способ сравнения неравных массивов символов в c

strcmp, кажется, дает мне только большее или меньшее число, а не положение неравного характера.

Например, строки:

/home/jjjj/ and 
/home/jjjj/kkkk/asdasd 

должен возвращать 12

ответ

4

Использование strlen() и strstr() вы можете достичь этого в два шага подхода:

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


char str1[] = "this is a long string"; 
char str2[] = "long"; 

{ 
    char * ss = NULL; 
    char * sg = NULL; 
    size_t size1 = strlen(str1) 
    size_t size2 = strlen(str2); 
    size_t size_ss = 0; 

    /* step 1: determine which of the two strings tobe compared it the smaller/greater one. */ 
    if (size1 > size2) 
    { 
    size_ss = size2; 
    ss = str2; 
    sg = str1; 
    } 
    else 
    { 
    size_ss = size1; 
    ss = str1; 
    sg = str2; 
    } 

    /* step 2: find out where the smaller string is located in the greater one, if ever... */ 
    { 
    char * p = strstr(sg, ss); 

    if (p) 
    { 
     printf("'%s' is the same as '%s' from character %zu to character %zu.\n", 
     sg, ss, p - sg, p - sg + size_ss); 
    } 
    else 
    { 
     /* printf("The strings are 100%% differently!\n"); */ /* changed as per Jonathan's comment. */ 
     printf("'%s' does not appear in '%s'.\n", ss, sg); 
    } 
    } 
} 

Это решение не принимает что более короткая строка может появляться более одного раза в более длинной строке. Он всегда уведомляет о первом вхождении.

+0

Хорошо, спасибо, я попробую, что – Vanguard

+0

Да, это сработало, спасибо еще раз :) – Vanguard

+0

Добро пожаловать! А также вы можете переложить ответ, если вам понравилось ... ;-) – alk

3

Не существует стандартной функции С, которая возвращает первую точку несоответствия между двумя строками.

Нетрудно создать его; возьмите версию strcmp() из учебника и измените ее так, чтобы возвращать смещение строк в точке, где результат «интересен». Если строки равны, это будет смещение нулевого терминатора ('\0'); в противном случае это будет смещение, когда две строки отличаются.

+1

Или, если вы не думаете, что C++ - esque, но C-esque, то вы возвращаете 'NULL', если они равны, и указатель на другой символ, если они не являются :) –

+0

Проблема с возвратом указателя заключается в том, что указатель асимметричен. Какая из двух строк указатель указывает? Вы также должны выполнить дополнительные вычисления, чтобы найти правильный символ в другой строке. Смещение нейтрально между двумя строками. –

1

Может быть что-то вроде этого:

const char* strcmp_plusplus (const char* str1, const char* str2) 
{ 
    const char* result = NULL; // return NULL if equal 

    while(*str1 != '\0') 
    { 
    if(*str1 != *str2) 
    { 
     result = str1; // point at where in str1 they are different 
     break; 
    } 

    str1++; 
    str2++; 
    } 

    return result; 
} 

Обратите внимание, что мы не должны проверить, если str2 является \0, потому что стандарт C позволяет читать один элемент за пределами массива, не прибегая к неопределенному поведению. Если str2 заканчивается до str1, функция вернет указатель на нулевое завершение str1.

+1

Нулевой байт является частью объекта, поэтому вы не будете читать за пределами массива. – wildplasser

+0

@wildplasser Хм да, вы правы. Если str1 указывает на что-то внутри своей строки и str2 на '\ 0 ', итерация все равно будет остановлена. – Lundin

+0

Если строки имеют длину 32 байта, скажем, и отличаются в первом байте, ваш код все еще сканирует остальные байты в строке перед завершением цикла. Вы можете сделать «return result;» в условном выражении внутри цикла, а затем просто «вернуть NULL» в конце, в результате чего «result» будет ненужным в качестве переменной. –

0

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

#include <stdio.h> 

size_t lead_cmp(const char * one, const char * two, int *result); 
size_t lead_cmp(const char * one, const char * two, int *result) 
{ 
    size_t pos; 

    for(pos=0; one[pos] && two[pos]; pos++) { 
     if (one[pos] != two[pos]) break; 
    } 

    *result = one[pos] - two[pos]; 
    return pos; 
} 

int main(int argc, char **argv) 
{ 
    size_t len; 
    int diff; 

    len = lead_cmp (argv[1], argv[2], &diff); 
    printf("Pos=%zu, Rc=%d\n", len, diff); 

    return 0; 
} 

Результат:

$ ./a.out /home/jjjj/ /home/jjjj/kkkk/ 
Pos=11, Rc=-107 
$ 

Найденное положение 11, а не 12, поскольку С использует 0 на основе индексации.

Он возвращает количество совпадающих символов: длину общего префикса.

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