Как работает strcmp()?

Я искал справедливый бит для ответа. Я собираюсь сделать ряд собственных строковых функций, таких как my_strcmp(), my_strcat() и т.д.

Работает ли strcmp() каждый индекс из двух массивов символов, и если значение ASCII меньше при идентичном индексе двух строк, эта строка имеет более широкую букву и, следовательно, возвращается 0 или 1 или 2? Я предполагаю, что я спрашиваю, использует ли он значения ASCII символов для возврата этих результатов?

Любая помощь будет принята с благодарностью.

[REVISED]

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

Какие-нибудь советы?

int my_strcmp(char s1[], char s2[])
{   
    int i = 0;
    while ( s1[i] != '\0' )
    {
        if( s2[i] == '\0' ) { return 1; }
        else if( s1[i] < s2[i] ) { return -1; }
        else if( s1[i] > s2[i] ) { return 1; }
        i++;
    }   
    return 0;
}


int main (int argc, char *argv[])
{
    int result = my_strcmp(argv[1], argv[2]);

    printf("Value: %d \n", result);

    return 0;

}

Ответы

Ответ 1

"реализация" псевдокода strcmp будет выглядеть примерно так:

define strcmp (s1, s2):
    p1 = address of first character of str1
    p2 = address of first character of str2

    while contents of p1 not equal to null:
        if contents of p2 equal to null: 
            return 1

        if contents of p2 greater than contents of p1:
            return -1

        if contents of p1 greater than contents of p2:
            return 1

        advance p1
        advance p2

    if contents of p2 not equal to null:
        return -1

    return 0

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

Только если символы идентичны, вы переходите к следующему символу, и, если все символы идентичны, возвращается ноль.

Обратите внимание, что вы можете не обязательно получать 1 и -1, спецификации говорят, что любое положительное или отрицательное значение будет достаточным, поэтому вы всегда должны проверять возвращаемое значение с помощью < 0, > 0 или == 0.

Включение этого в реальное С было бы относительно простым:

int myStrCmp (const char *s1, const char *s2) {
    const unsigned char *p1 = (const unsigned char *)s1;
    const unsigned char *p2 = (const unsigned char *)s2;

    while (*p1 != '\0') {
        if (*p2 == '\0') return  1;
        if (*p2 > *p1)   return -1;
        if (*p1 > *p2)   return  1;

        p1++;
        p2++;
    }

    if (*p2 != '\0') return -1;

    return 0;
}

Также имейте в виду, что "больше" в контексте символов необязательно основывается на простом упорядочении ASCII для всех строковых функций.

C имеет понятие "локали", которое задает (помимо прочего) сортировку или упорядочивание базового набора символов, и вы можете, например, найти символы a, á, à и ä все считаются идентичными. Это произойдет для таких функций, как strcoll.

Ответ 2

Вот BSD-реализация:

int
strcmp(s1, s2)
    register const char *s1, *s2;
{
    while (*s1 == *s2++)
        if (*s1++ == 0)
            return (0);
    return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}

После несоответствия между двумя символами он просто возвращает разницу между этими двумя символами.

Ответ 3

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

Например:

strcmp("abc", "def") < 0
strcmp("abc", "abcd") < 0 // null character is less than 'd'
strcmp("abc", "ABC") > 0 // 'a' > 'A' in ASCII
strcmp("abc", "abc") == 0

Точнее, как описано в strcmp Open Group спецификации:

Знак ненулевого возвращаемого значения определяется значком разницы между значениями первой пары байтов (оба интерпретируются как тип unsigned char), которые различаются в сравнении строк.

Обратите внимание, что возвращаемое значение может не совпадать с этой разницей, но оно будет иметь один и тот же знак.

Ответ 4

Вот моя версия, написанная для небольших приложений микроконтроллеров, совместимая с MISRA-C. Основная цель этого кода заключалась в том, чтобы написать читаемый код вместо однострочного goo, найденного в большинстве библиотек компилятора.

int8_t strcmp (const uint8_t* s1, const uint8_t* s2)
{
  while ( (*s1 != '\0') && (*s1 == *s2) )
  {
    s1++; 
    s2++;
  }

  return (int8_t)( (int16_t)*s1 - (int16_t)*s2 );
}

Примечание: код предполагает 16-разрядный тип int.

Ответ 5

Это из самих мастеров (K & R, 2nd ed., стр. 106):

// strcmp: return < 0 if s < t, 0 if s == t, > 0 if s > t
int strcmp(char *s, char *t) 
{
    int i;

    for (i = 0; s[i] == t[i]; i++)
        if (s[i] == '\0')
            return 0;
    return s[i] - t[i];
}

Ответ 6

Этот код эквивалентен, короче и читабельнее:

int8_t strcmp (const uint8_t* s1, const uint8_t* s2)
{
    while( (*s1!='\0') && (*s1==*s2) ){
        s1++; 
        s2++;
    }

    return (int8_t)*s1 - (int8_t)*s2;
}

Нам нужно только проверить конец s1, потому что, если мы дойдем до конца s2 до конца s1, цикл завершится (так как * s2!= * s1).

Возвращаемое выражение вычисляет правильное значение в каждом случае, если мы используем только 7-битные (чистые ASCII) символы. Тщательное мышление необходимо для создания правильного кода для 8-битных символов из-за риска переполнения целых чисел.

Ответ 8

Вот как я реализовал мой strcmp: он работает следующим образом: он сравнивает первую букву двух строк, если она идентична, она продолжает следующую букву. Если нет, он возвращает соответствующее значение. Это очень просто и легко понять:   # include

//function declaration:
int strcmp(char string1[], char string2[]);

int main()
{
    char string1[]=" The San Antonio spurs";
    char string2[]=" will be champins again!";
    //calling the function- strcmp
    printf("\n number returned by the strcmp function: %d", strcmp(string1, string2));
    getch();
    return(0);
}

/**This function calculates the dictionary value of the string and compares it to another string.
it returns a number bigger than 0 if the first string is bigger than the second
it returns a number smaller than 0 if the second string is bigger than the first
input: string1, string2
output: value- can be 1, 0 or -1 according to the case*/
int strcmp(char string1[], char string2[])
{
    int i=0;
    int value=2;    //this initialization value could be any number but the numbers that can be      returned by the function
    while(value==2)
    {
        if (string1[i]>string2[i])
        {
            value=1;
        }
        else if (string1[i]<string2[i])
        {
            value=-1;
        }
        else
        {
            i++;
        }
    }
    return(value);
}

Ответ 9

Это только:

int strcmp(char *str1, char *str2){
    while( (*str1 == *str2) && (*str1 != 0) ){
        ++*str1;
        ++*str2;
    }
    return (*str1-*str2);
}

если вы хотите быстрее, вы можете добавить "register" перед типом, например: зарегистрировать char

то вот так:

int strcmp(register char *str1, register char *str2){
    while( (*str1 == *str2) && (*str1 != 0) ){
        ++*str1;
        ++*str2;
    }
    return (*str1-*str2);
}

таким образом, если это возможно, используется регистр ALU.