strcmp () и подписанные / неподписанные символы - PullRequest
16 голосов
/ 31 августа 2009

Меня смущает strcmp (), точнее то, как это определяется стандартом. Попробуйте сравнить две строки, в которых одна содержит символы вне диапазона ASCII-7 (0-127).

Стандарт C определяет:

int strcmp (const char * s1, const char * s2);

Функция strcmp сравнивает строку, на которую указывает s1, со строкой на который указывает s2.

Функция strcmp возвращает целое число, большее, равное или меньше нуля, соответственно как строка, на которую указывает s1, больше чем, равно или меньше чем строка, на которую указывает s2.

Параметры: char *. Не unsigned char *. Не существует понятия, что «сравнение должно выполняться как unsigned».

Но все стандартные библиотеки, которые я проверял, считают, что «высокий» символ - это просто значение выше , чем символы ASCII-7.

Я понимаю, что это полезно и ожидаемое поведение. Я не хочу сказать, что существующие реализации неправильны или что-то в этом роде. Я просто хочу знать, какую часть стандартных характеристик я пропустил ?

int strcmp_default( const char * s1, const char * s2 )
{
    while ( ( *s1 ) && ( *s1 == *s2 ) )
    {
        ++s1;
        ++s2;
    }
    return ( *s1 - *s2 );
}

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

    while ( ( *p1 ) && ( *p1 == *p2 ) )
    {
        ++p1;
        ++p2;
    }
    return ( *p1 - *p2 );
}

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

int main()
{
    char x1[] = "abc";
    char x2[] = "abü";
    printf( "%d\n", strcmp_default( x1, x2 ) );
    printf( "%d\n", strcmp_unsigned( x1, x2 ) );
    printf( "%d\n", strcmp( x1, x2 ) );
    return 0;
}

Вывод:

103
-153
-153

1 Ответ

28 голосов
/ 31 августа 2009

7.21.4 / 1 (C99), акцент мой:

Знак ненулевого значения, возвращаемого функциями сравнения memcmp, strcmp, а strncmp определяется знаком разности значений первого пара символов ( оба интерпретируются как беззнаковый символ ), которые различаются по объектам по сравнению.

Есть что-то похожее в C90.

Обратите внимание, что strcoll () может быть более адаптированным, чем strcmp (), особенно если у вас есть символы вне базового набора символов.

...