Pourquoi l'alphabet est-il divisé en plusieurs plages dans ce code C?

161

Dans une bibliothèque personnalisée, j'ai vu une implémentation:

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

Est-ce un œuf de Pâques ou quels sont les avantages par rapport à la méthode C / C ++ standard?

inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}
Vladimir Ch.
la source
Notez que dans EBCDIC, la plage de caractères pour les lettres minuscules vient avant la plage de caractères pour les lettres majuscules, et les deux viennent avant les chiffres - ce qui est exactement le contraire de l'ordre dans les encodages ASCII (comme le 8859- x série, ou Unicode, ou CP1252, ou…).
Jonathan Leffler
1
Remarque: si 'J' - 'I'et les 'S' - 'R'deux sont égaux 1, alors je m'attends à ce qu'un optimiseur raisonnable transforme le premier en le second.
Matthieu M.

Réponses:

214

L'auteur de ce code avait sans doute pour soutenir EBCDIC à un moment donné, où les valeurs numériques des lettres sont non contiguës (lacunes existent entre I, Jet R, Scomme vous l'aurez deviné).

Il est intéressant de noter que le C et les normes C de seulement la garantie que les caractères 0à 9avoir des valeurs numériques contiguës précisément pour cette raison, si aucune de ces méthodes est strictement conforme à la norme.

Wintermute
la source
64
Le vrai WTF est pourquoi ne pas l'auteur original mis dans un commentaire: // In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details. Alors vous n'aurez même jamais à poser la question. Vous auriez la réponse intégrée au code.
abelenky
66
@abelenky Si le code était à l'origine pour un système sur lequel ebcdic est normalement utilisé, cela peut avoir semblé évident à l'époque et ne nécessitait pas de commentaire, malheureusement, les choses qui semblent bien dans le code hérité semblent maintenant étranges.
Vality
26
@abelenky: Le vrai WTF est la raison pour laquelle l'auteur original n'a pas utilisé les fonctionnalités standard, c'est-à-dire return ( isalpha( chValue ) && isupper( chValue ) )...
DevSolar
4
@Damon: Ce n'est pas le problème. Vous devrez peut-être traiter un encodage «étranger» même sur un système qui n'utilise pas cet encodage nativement. Donc, vous définissez votre locale sur le codage donné, et ensuite vous devez garder les doigts croisés pour que le programmeur ait réellement utilisé des fonctions standard au lieu de faire un codage "intelligent" comme ci-dessus, pensant qu'il connaît chaque codage que son programme rencontrera jamais ...
DevSolar
6
S'il a été écrit pour supporter EBCDIC à partir des années 1970, isalpha et isupper étaient-ils même ANSI ou supportés par la majorité des compilateurs à l'époque?
nickalh
54

On dirait qu'il tente de couvrir à la fois EBCDIC et ASCII. Votre méthode alternative ne fonctionne pas pour EBCDIC (elle a des faux positifs, mais pas de faux négatifs)

C et C ++ ne nécessitent que '0'-'9'sont contiguës.

Notez que les appels bibliothèque standard ne sait si elles fonctionnent sur ASCII, EBCDIC ou d' autres systèmes, ils sont donc plus portable et peut - être plus efficace.

MSalters
la source
5
std::isupperinterroge en fait la locale C globale actuellement installée.
Lingxi
1
Oui, tu as raison. La méthode est écrite pour couvrir les deux encodages. Merci d'avoir répondu!
Vladimir Ch.
4
@Lingxi: C'est vrai, mais cela ne veut pas dire que vous pouvez passer de l'ASCII à EBCDIC. 'A'doit rester 'A'indépendamment de la localisation. ASCII à UTF-8, ce serait possible.
MSalters
2
@Lingxi: std::isupperinterroge la locale C globale actuellement installée, oui, mais pas la phase de compilation qui interprète les caractères littéraux.
Courses de légèreté en orbite
1
@Lingxi - Juste un petit mot. On peut se demander si std::isupperc'est vraiment nécessaire dans la plupart des cas. Il respecte les paramètres régionaux utilisés pour les entrées de l'utilisateur. Mais lors de l'analyse des fichiers, de l'interaction avec les bases de données, vous attendez généralement d'autres paramètres régionaux. De plus, au moins sous Linux, ces appels liés à la locale sont très lents - par exemple, std::isalphaappelle dynamic_cast deux fois pour "trouver" l'implémentation appropriée de la locale avant de comparer un seul caractère.
ibre5041