Я пытаюсь переопределить strcasecmp
функцию в C, и я заметил несоответствие в процессе сравнения.
От man strcmp
Функция strcmp () сравнивает две строки s1 и s2. Локаль не учитывается (сравнение с учетом локали смотрите в strcoll (3)). Он возвращает целое число, меньшее, равное или большее нуля, если найдено, что s1 соответственно меньше, соответствует или больше s2.
От man strcasecmp
Функция strcasecmp () выполняет побитовое сравнение строк s1 и s2, игнорируя регистр символов. Он возвращает целое число, меньшее, равное или большее нуля, если найдено, что s1 соответственно меньше, соответствует или больше s2.
int strcmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2);
Учитывая эту информацию, я не понимаю результат следующего кода:
#include <stdio.h>
#include <string.h>
int main()
{
// ASCII values
// 'A' = 65
// '_' = 95
// 'a' = 97
printf("%i\n", strcmp("A", "_"));
printf("%i\n", strcmp("a", "_"));
printf("%i\n", strcasecmp("A", "_"));
printf("%i\n", strcasecmp("a", "_"));
return 0;
}
Ouput:
-1 # "A" is less than "_"
1 # "a" is more than "_"
2 # "A" is more than "_" with strcasecmp ???
2 # "a" is more than "_" with strcasecmp
Похоже, что если текущий символ в s1
является буквой, он всегда преобразуется в нижний регистр, независимо от того, является ли текущий символ в s2
букве или нет.
Может кто-нибудь объяснить это поведение? Разве первая и третья строки не должны совпадать?
Заранее спасибо!
PS:
я использую gcc 9.2.0
на Манджаро.
Кроме того, когда я компилирую с -fno-builtin
флагом, я получаю вместо этого:
-30
2
2
2
Я думаю, это потому, что программа не использует оптимизированные функции gcc, но вопрос остается.
strcasecmp
которому вы обращаетесь, не является точным. Больше подробностей в ответах.
A < _ && a > _ && A == a
, вызовет так много проблем.
unsigned char
. C17 / 18 «Обработка строк <string.h>» -> «Для всех функций в этом подпункте каждый символ должен интерпретироваться так, как если бы он имел тип unsigned char
». Это имеет значение, когда char
значения выходят за пределы диапазона ASCII 0-127.
printf("%i\n", strcasecmp("a", "_"));
должен иметь тот же результат, что иprintf("%i\n", strcasecmp("A", "_"));
Но, это означает, что один из этих двух нечувствительных к регистру вызовов будет не согласен с его чувствительным к регистру аналогом.