¿Por qué el alfabeto se divide en múltiples rangos en este código C?

161

En una biblioteca personalizada vi una implementación:

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

¿Es un huevo de Pascua o cuáles son las ventajas frente al método estándar C / C ++?

inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}
Vladimir Ch.
fuente
Tenga en cuenta que en EBCDIC, el rango de caracteres para letras minúsculas va antes que el rango de caracteres para letras mayúsculas, y ambos van antes de los dígitos, que es exactamente lo opuesto al orden en codificaciones basadas en ASCII (como el 8859- x series, o Unicode, o CP1252, o ...).
Jonathan Leffler
1
Nota: si 'J' - 'I'y 'S' - 'R'ambos son iguales 1, entonces espero que un optimizador razonable convierta el primero en el segundo.
Matthieu M.

Respuestas:

214

El autor de este código, presumiblemente, tuvo que soportar EBCDIC en algún momento, donde los valores numéricos de las letras son no contiguos (existen brechas entre I, Jy R, Scomo habrá adivinado).

Vale la pena señalar que la C y estándares de C ++ única garantía de que los personajes 0que 9tienen valores numéricos contiguos precisamente por esta razón, por lo que ninguno de estos métodos es estrictamente estándar conformes.

Wintermute
fuente
64
La WTF real es por qué no lo hizo el autor original puesto en un comentario: // In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details. Entonces nunca tendrías que hacer la pregunta. Tendría la respuesta incorporada al código.
abelenky
66
@abelenky Si el código era originalmente para un sistema en el que normalmente se usa ebcdic, puede haber parecido obvio en ese momento y no necesitó un comentario, desafortunadamente las cosas que parecen estar bien en el código heredado parecen extrañas ahora.
Vality
26
@abelenky: El verdadero WTF es por qué el autor original no usó la funcionalidad estándar, es decir return ( isalpha( chValue ) && isupper( chValue ) )...
DevSolar
44
@Damon: Ese no es el problema. Puede que tenga que procesar una codificación "alienígena" incluso en un sistema que no usa esa codificación de forma nativa. Así que configura su configuración regional en la codificación dada, y luego debe mantener los dedos cruzados para que el programador realmente use funciones estándar en lugar de hacer una codificación "inteligente" como la anterior, pensando que sabe cada codificación que su programa encontrará ...
DevSolar
66
Si fue escrito para admitir EBCDIC desde la década de 1970, ¿isalpha e isupper incluso ANSI o era compatible con la mayoría de los compiladores en ese entonces?
nickalh
54

Parece que intenta cubrir tanto EBCDIC como ASCII. Su método alternativo no funciona para EBCDIC (tiene falsos positivos, pero no falsos negativos)

C y C ++ no requieren que '0'-'9'son contiguos.

Tenga en cuenta que las llamadas a las bibliotecas estándar no sabe si se ejecutan en ASCII, EBCDIC o otros sistemas, por lo que son más fáciles de transportar y posiblemente más eficiente.

MSalters
fuente
55
std::isupperen realidad consulta la configuración regional global C actualmente instalada.
Lingxi
1
Sí, tiene usted razón. El método está escrito para cubrir ambas codificaciones. ¡Gracias por la respuesta!
Vladimir Ch.
44
@Lingxi: Cierto, pero eso no significa que pueda cambiar la configuración regional de ASCII a EBCDIC. 'A'tiene que permanecer 'A'independientemente de la configuración regional. ASCII a UTF-8, eso sería posible.
MSalters
2
@Lingxi: std::isupperconsulta la configuración regional global C instalada actualmente, sí, pero la fase de compilación que interpreta los literales de caracteres no.
Carreras de ligereza en órbita
1
@Lingxi - Solo una nota rápida. Es cuestionable si std::isupperrealmente es necesario en la mayoría de los casos. Respeta las configuraciones regionales utilizadas para la entrada del usuario. Pero al analizar archivos, al interactuar con bases de datos, generalmente se espera algún otro entorno local. Además, al menos en Linux, estas llamadas relacionadas con la configuración regional son muy lentas; por ejemplo, std::isalphallama a dynamic_cast dos veces para "encontrar" la implementación de la configuración regional adecuada antes de comparar un solo carácter.
ibre5041