Warum ist das Alphabet in diesem C-Code in mehrere Bereiche unterteilt?

161

In einer benutzerdefinierten Bibliothek habe ich eine Implementierung gesehen:

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

Ist das ein Osterei oder was sind die Vorteile gegenüber der Standard-C / C ++ - Methode?

inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}
Vladimir Ch.
quelle
Beachten Sie, dass in EBCDIC der Zeichenbereich für Kleinbuchstaben vor dem Zeichenbereich für Großbuchstaben steht und beide vor den Ziffern stehen - was genau das Gegenteil der Reihenfolge bei ASCII-basierten Codierungen ist (z. B. 8859-). x-Serie oder Unicode oder CP1252 oder…).
Jonathan Leffler
1
Hinweis: Wenn 'J' - 'I'und 'S' - 'R'beide gleich sind 1, erwarte ich, dass ein vernünftiger Optimierer den ersteren in den letzteren umwandelt.
Matthieu M.

Antworten:

214

Der Autor dieses Code vermutlich hatte zu unterstützen EBCDIC an einem gewissen Punkt, wo die numerischen Werte der Buchstaben sind nicht zusammenhängende (Lücken bestehen zwischen I, Jund R, Swie Sie vielleicht schon erraten haben).

Es ist erwähnenswert, dass die C- und C ++ Standards nur garantiert werden, dass die Zeichen 0auf 9genau aus diesem Grunde zusammenhängende numerische Werte, also keines dieser Verfahren streng normgerechten sind.

Wintermute
quelle
64
Die wahre WTF ist, warum der ursprüngliche Autor keinen Kommentar abgegeben hat : // In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details. Dann müssten Sie nie einmal die Frage stellen. Sie hätten die Antwort in den Code integriert.
Abelenky
66
@abelenky Wenn der Code ursprünglich für ein System war, auf dem ebcdic normalerweise verwendet wird, schien er zu diesem Zeitpunkt offensichtlich zu sein und brauchte keinen Kommentar. Leider scheinen Dinge, die im Legacy-Code in Ordnung zu sein scheinen, jetzt seltsam.
Vality
26
@abelenky: Die echte WTF ist, warum der ursprüngliche Autor nicht die Standardfunktionalität verwendet hat, dh return ( isalpha( chValue ) && isupper( chValue ) )...
DevSolar
4
@Damon: Das ist nicht das Problem. Möglicherweise müssen Sie verarbeiten eine „fremde“ kodiert , sogar auf einem System, das nicht nativ - Codierung verwenden. Sie stellen also Ihr Gebietsschema auf die angegebene Codierung ein und drücken dann die Daumen, dass der Programmierer tatsächlich Standardfunktionen verwendet hat, anstatt wie oben beschrieben "intelligent" zu codieren. Er glaubt, dass er weiß, dass jede Codierung, auf die sein Programm jemals stoßen wird ...
DevSolar
6
Wenn es geschrieben wurde, um EBCDIC aus den 1970er Jahren zu unterstützen, war isalpha und isupper damals sogar ANSI oder wurde es von der Mehrheit der Compiler unterstützt?
Nickalh
54

Es scheint, als würde versucht, sowohl EBCDIC als auch ASCII abzudecken. Ihre alternative Methode funktioniert nicht für EBCDIC (sie hat falsch positive, aber keine falsch negativen Ergebnisse).

C und C ++ Sie verlangen , dass '0'-'9'angrenzen.

Beachten Sie, dass die Standard - Bibliothek Anrufe Sie wissen , ob sie auf ASCII laufen, EBCDIC oder anderen Systemen, so dass sie mehr tragbar und möglicherweise effizienter sind.

MSalters
quelle
5
std::isupperfragt tatsächlich das aktuell installierte globale C-Gebietsschema ab.
Lingxi
1
Ja, du hast recht. Die Methode ist für beide Codierungen geschrieben. Danke für die Antwort!
Vladimir Ch.
4
@Lingxi: Stimmt, aber das bedeutet nicht, dass Sie das Gebietsschema von ASCII auf EBCDIC umstellen können. 'A'muss 'A'unabhängig vom Gebietsschema bleiben . ASCII zu UTF-8, das wäre möglich.
MSalters
2
@Lingxi: Fragt std::isupperdas aktuell installierte globale C-Gebietsschema ab, ja, die Kompilierungsphase, in der Zeichenliterale interpretiert werden, jedoch nicht.
Leichtigkeitsrennen im Orbit
1
@ Lingxi - Nur eine kurze Notiz. Es ist fraglich, ob std::isupperin den meisten Fällen wirklich benötigt wird. Es berücksichtigt Gebietsschemas, die für die Eingabe durch den Benutzer verwendet werden. Wenn Sie jedoch Dateien analysieren und mit Datenbanken interagieren, erwarten Sie normalerweise ein anderes Gebietsschema. Darüber hinaus sind diese Aufrufe im Zusammenhang mit dem Gebietsschema zumindest unter Linux sehr langsam. std::isalphaRufen Sie beispielsweise dynamic_cast zweimal auf, um die richtige Implementierung des Gebietsschemas zu "finden", bevor Sie tatsächlich ein einzelnes Zeichen vergleichen.
ibre5041