Próbuję ponownie wdrożyć strcasecmp
funkcję w C i zauważyłem, co wydaje się być niespójnością w procesie porównywania.
Od man strcmp
Funkcja strcmp () porównuje dwa ciągi s1 i s2. Ustawienia regionalne nie są brane pod uwagę (dla porównania uwzględniającego ustawienia regionalne, patrz strcoll (3)). Zwraca liczbę całkowitą mniejszą, równą lub większą od zera, jeśli okaże się, że s1 jest odpowiednio mniejsza niż, do dopasowania lub większa niż s2.
Od man strcasecmp
Funkcja strcasecmp () wykonuje porównanie bajtów po bajtach ciągów s1 i s2, ignorując wielkość liter w znakach. Zwraca liczbę całkowitą mniejszą, równą lub większą od zera, jeśli okaże się, że s1 jest odpowiednio mniejsza niż, do dopasowania lub większa niż s2.
int strcmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2);
Biorąc pod uwagę te informacje, nie rozumiem wyniku następującego kodu:
#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
Wygląda na to, że jeśli bieżącym znakiem w s1
jest litera, to zawsze jest konwertowany na małe litery, niezależnie od tego, czy bieżącym znakiem s2
jest litera, czy nie.
Czy ktoś może wyjaśnić to zachowanie? Czy pierwsza i trzecia linia nie powinny być identyczne?
Z góry dziękuję!
PS:
Używam gcc 9.2.0
na Manjaro.
Ponadto, kiedy kompiluję z -fno-builtin
flagą, otrzymuję zamiast tego:
-30
2
2
2
Chyba dlatego, że program nie korzysta ze zoptymalizowanych funkcji gcc, ale pozostaje pytanie.
strcasecmp
którego się odnosisz, nie jest dokładny. Więcej szczegółów w recenzowanych odpowiedziach.
A < _ && a > _ && A == a
, spowodowałaby tyle problemów.
unsigned char
. C17 / 18 „Obsługa ciągów <ciąg.h>” -> „Dla wszystkich funkcji w niniejszej podsekcji każdy znak należy interpretować tak, jakby miał typ unsigned char
”. To robi różnicę, gdy char
wartości są poza zakresem 0-127 ASCII.
printf("%i\n", strcasecmp("a", "_"));
Prawdopodobnie powinien on mieć taki sam wynik jakprintf("%i\n", strcasecmp("A", "_"));
Ale Oznacza to, że jedno z tych dwóch połączeń bez rozróżniania wielkości liter nie zgadza się z jego odpowiednikiem z rozróżnianiem wielkości liter.