Dlaczego alfabet jest podzielony na wiele zakresów w tym kodzie C?

161

W bibliotece niestandardowej zobaczyłem implementację:

inline int is_upper_alpha(char chValue)
{
    if (((chValue >= 'A') && (chValue <= 'I')) ||
        ((chValue >= 'J') && (chValue <= 'R')) ||
        ((chValue >= 'S') && (chValue <= 'Z')))
        return 1;
    return 0;
}

Czy to jajko wielkanocne, czy też jakie są zalety w porównaniu ze standardową metodą C / C ++?

inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}
Vladimir Ch.
źródło
Zwróć uwagę, że w EBCDIC zakres znaków dla małych liter występuje przed zakresem znaków dla dużych liter, a oba występują przed cyframi - co jest dokładnie odwrotnością kolejności w kodowaniu opartym na ASCII (takim jak 8859- x, Unicode, CP1252 lub…).
Jonathan Leffler
1
Uwaga: jeśli 'J' - 'I'i 'S' - 'R'oba są równe 1, to spodziewam się, że rozsądne byłoby włączyć optymalizator były w tym ostatnim.
Matthieu M.

Odpowiedzi:

214

Autor tego kodu prawdopodobnie musiał w pewnym momencie obsługiwać EBCDIC , gdy wartości liczbowe liter nie są ciągłe (istnieją luki między I, Ja R,S jak można się domyślić).

Warto zauważyć, że standardy C i C ++ gwarantują tylko, że znaki 0będą 9miały ciągłe wartości liczbowe właśnie z tego powodu, więc żadna z tych metod nie jest ściśle zgodna ze standardami.

Wintermute
źródło
64
Prawdziwy WTF to dlaczego nie oryginalny autor umieścić w komentarzu: // In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details. Wtedy nigdy nie musiałbyś nawet zadawać tego pytania. Odpowiedź byłaby wbudowana w kod.
abelenky
66
@abelenky Jeśli kod był pierwotnie przeznaczony dla systemu, w którym normalnie używany jest ebcdic, mógł wydawać się wtedy oczywisty i nie wymagał komentarza, niestety rzeczy, które wydają się dobrze w starszym kodzie, wydają się teraz dziwne.
Vality
26
@abelenky: Prawdziwe WTF jest to, dlaczego oryginalny autor nie użył standardowej funkcjonalności, tj. return ( isalpha( chValue ) && isupper( chValue ) )...
DevSolar
4
@Damon: To nie jest problem. Być może trzeba będzie przetworzyć kodowanie „obcego”, nawet w systemie, który nie używa tego kodowania natywnie. Więc ustawiasz swoje locale na podane kodowanie, a potem musisz trzymać kciuki, że programista faktycznie używał standardowych funkcji zamiast robić "inteligentne" kodowanie jak powyżej, myśląc, że zna każde kodowanie, jakie jego program kiedykolwiek napotka ...
DevSolar
6
Jeśli został napisany do obsługi EBCDIC od lat 70., czy isalpha i isupper byłby nawet ANSI, czy był obsługiwany przez większość kompilatorów w tamtych czasach?
nickalh
54

Wygląda na to, że próbuje objąć zarówno EBCDIC, jak i ASCII. Twoja alternatywna metoda nie działa w przypadku EBCDIC (ma fałszywe alarmy, ale nie ma fałszywych negatywów)

C i C ++ nie wymagają, '0'-'9'są przyległe.

Należy pamiętać, że standardowe połączenia biblioteki nie wiem, czy działają one na ASCII, EBCDIC lub innych systemów, więc są bardziej przenośne i prawdopodobnie bardziej efektywne.

MSalters
źródło
5
std::isupperfaktycznie pyta o aktualnie zainstalowane globalne locale C.
Lingxi
1
Tak masz rację. Metoda została napisana w celu pokrycia obu kodowań. Dziękuję za odpowiedź!
Vladimir Ch.
4
@Lingxi: Prawda, ale to nie znaczy, że możesz zmienić ustawienia regionalne z ASCII na EBCDIC. 'A'musi pozostać 'A'niezależnie od lokalizacji. ASCII do UTF-8, to byłoby możliwe.
MSalters
2
@Lingxi: std::isupperodpytuje aktualnie zainstalowane globalne locale C, tak, ale faza kompilacji, która interpretuje literały znaków, nie.
Wyścigi lekkości na orbicie
1
@Lingxi - tylko krótka notatka. Wątpliwe jest, czy std::isupperw większości przypadków jest to naprawdę potrzebne. Szanuje ustawienia regionalne używane do wprowadzania danych przez użytkownika. Ale podczas analizowania plików, interakcji z bazami danych, zwykle spodziewasz się innych ustawień regionalnych. Co więcej, przynajmniej w Linuksie te wywołania związane z ustawieniami lokalnymi są bardzo powolne - na przykład std::isalphawywołanie dynamic_cast dwa razy w celu „znalezienia” właściwej implementacji ustawień regionalnych przed faktycznym porównaniem pojedynczego znaku.
ibre5041