Los rangos alfabéticos en minúsculas y mayúsculas no cruzan un %32
límite de "alineación" en el sistema de codificación ASCII.
Es por eso que bit 0x20
es la única diferencia entre las versiones en mayúsculas / minúsculas de la misma letra.
Si este no fuera el caso, necesitaría sumar o restar 0x20
, no solo alternar, y para algunas letras se realizaría para voltear otros bits más altos. (Y no habría una sola operación que pudiera alternar, y buscar caracteres alfabéticos en primer lugar sería más difícil porque no podría | = 0x20 forzar lcase).
Trucos relacionados solo con ASCII: puede verificar si hay un carácter ASCII alfabético forzando minúsculas con c |= 0x20
y luego verificando si (sin signo) c - 'a' <= ('z'-'a')
. Entonces, solo 3 operaciones: OR + SUB + CMP contra una constante 25. Por supuesto, los compiladores saben cómo optimizar (c>='a' && c<='z')
en asm como este para usted , por lo que a lo sumo debe hacer la c|=0x20
parte usted mismo. Es bastante inconveniente hacer todo el casting necesario usted mismo, especialmente para evitar promociones enteras predeterminadas para firmar int
.
unsigned char lcase = y|0x20;
if (lcase - 'a' <= (unsigned)('z'-'a')) { // lcase-'a' will wrap for characters below 'a'
// c is alphabetic ASCII
}
// else it's not
Consulte también Convertir una cadena en C ++ a mayúsculas (cadena SIMDtoupper
solo para ASCII, enmascarando el operando para XOR usando esa verificación).
Y también Cómo acceder a una matriz de caracteres y cambiar las letras minúsculas a mayúsculas, y viceversa
(C con intrínsecos SIMD y mayúscula escalar x86 asm para caracteres alfabéticos ASCII, dejando otros sin modificar).
La mayoría de estos trucos solo son útiles si se optimiza manualmente el procesamiento de texto con SIMD (por ejemplo, SSE2 o NEON), después de comprobar que ninguno de los char
s en un vector tiene su bit alto establecido. (Y, por lo tanto, ninguno de los bytes forma parte de una codificación UTF-8 de varios bytes para un solo carácter, que podría tener diferentes inversas en mayúsculas / minúsculas). Si encuentra alguno, puede recurrir al escalar para este fragmento de 16 bytes, o para el resto de la cadena.
Incluso hay algunas configuraciones regionales donde toupper()
o tolower()
en algunos caracteres en el rango ASCII producen caracteres fuera de ese rango, especialmente en turco donde I ↔ ı e İ ↔ i. En esos entornos locales, necesitaría una verificación más sofisticada, o probablemente no intente utilizar esta optimización en absoluto.
Pero en algunos casos, se le permite asumir ASCII en lugar de UTF-8, por ejemplo, utilidades Unix con LANG=C
(la ubicación POSIX), no en_CA.UTF-8
o lo que sea.
Pero si puede verificar que es seguro, puede hacer toupper
cadenas de longitud media mucho más rápido que llamar toupper()
en un bucle (como 5x), y la última vez que probé con Boost 1.58 , mucho más rápido de lo boost::to_upper_copy<char*, std::string>()
que hace una estupidez dynamic_cast
por cada personaje.
@
a `mediante^ 32
.