Я намагаюся повторно реалізувати 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;
}
Вихід:
-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
Manjaro.
Крім того, коли я компілюю з -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", "_"));
Але Але це означає, що один із цих двох викликів, що не враховують регістр, не погодиться зі своїм аналогом, залежним від регістру.