As faixas alfabéticas em minúsculas e maiúsculas não cruzam um %32
limite de "alinhamento" no sistema de codificação ASCII.
É por isso que bit 0x20
é a única diferença entre as versões maiúsculas / minúsculas da mesma letra.
Se esse não fosse o caso, você precisaria adicionar ou subtrair 0x20
, não apenas alternar, e para algumas letras, seria necessário realizar outros giros mais altos. (E não haveria uma única operação que pudesse alternar, e a verificação de caracteres alfabéticos em primeiro lugar seria mais difícil porque você não poderia | = 0x20 forçar o lcase.)
Truques somente ASCII relacionados: você pode verificar se há um caractere ASCII alfabético forçando letras minúsculas com c |= 0x20
e, em seguida, verificando se (não assinado) c - 'a' <= ('z'-'a')
. Portanto, apenas três operações: OR + SUB + CMP em relação a 25 constantes. É claro que os compiladores sabem como otimizar (c>='a' && c<='z')
um ASM assim para você , portanto, no máximo, você deve fazer a c|=0x20
parte você mesmo. É bastante inconveniente fazer toda a conversão necessária, especialmente para contornar promoções inteiras padrão a serem assinadas 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 também Converter uma sequência toupper
em C ++ em maiúscula (sequência SIMD apenas para ASCII, mascarando o operando para o XOR usando essa verificação).
E também Como acessar uma matriz de caracteres e alterar letras minúsculas para maiúsculas e vice-versa
(C com intrínsecas SIMD e x86 asm escalar maiúsculas e minúsculas para caracteres ASCII alfabéticos, deixando outros não modificados).
Esses truques são úteis apenas se você otimiza manualmente algum processamento de texto com SIMD (por exemplo, SSE2 ou NEON), depois de verificar se nenhum dos char
s em um vetor tem seu bit alto definido. (E, portanto, nenhum dos bytes faz parte de uma codificação UTF-8 de vários bytes para um único caractere, que pode ter diferentes inversos maiúsculas / minúsculas). Se você encontrar algum, poderá voltar ao escalar para esse pedaço de 16 bytes ou para o restante da cadeia.
Existem até algumas localidades em que toupper()
ou tolower()
em alguns caracteres do intervalo ASCII produzem caracteres fora desse intervalo, principalmente turcos onde I I e İ ↔ i. Nesses locais, você precisaria de uma verificação mais sofisticada ou provavelmente não tentará usar essa otimização.
Mas, em alguns casos, você pode assumir ASCII em vez de UTF-8, por exemplo, utilitários Unix com LANG=C
(o local POSIX), não en_CA.UTF-8
ou o que quer.
Mas se você pode verificar se é seguro, pode toupper
usar seqüências de comprimento médio muito mais rápidas do que chamar toupper()
um loop (como 5x), e a última vez que testei com o Boost 1.58 , muito mais rápido do que o boost::to_upper_copy<char*, std::string>()
que é estúpido dynamic_cast
para todos os personagens.
@
em `usando^ 32
.