소문자 및 대문자 알파벳 범위는 %32
ASCII 코딩 시스템에서 "정렬"경계를 넘지 않습니다 .
그렇기 때문에 비트 0x20
가 동일한 문자의 대문자 / 소문자 버전 간의 유일한 차이점입니다.
그렇지 않은 경우에는 0x20
토글뿐만 아니라을 더하거나 빼야 하며 일부 문자의 경우 다른 높은 비트를 뒤집기 위해 수행해야합니다. (그리고 토글 할 수있는 단일 조작이 없으며, lcase를 강제하기 위해 | = 0x20을 사용할 수 없기 때문에 처음에 알파벳 문자를 확인하는 것이 더 어려울 것입니다.)
관련 ASCII 전용 트릭 : 소문자를 강제로 입력하고 (부호없는) 여부를 확인 하여 알파벳 ASCII 문자c |= 0x20
를 확인할 수 c - 'a' <= ('z'-'a')
있습니다. 따라서 상수 25에 대한 OR + SUB + CMP의 세 가지 작업 만 수행하십시오. 물론 컴파일러는 (c>='a' && c<='z')
이와 같이 asm 으로 최적화하는 방법을 알고 있으므로 최대 c|=0x20
부분을 직접 수행해야합니다 . 필요한 모든 캐스팅을 직접 수행하는 것은 다소 불편합니다. 특히 기본 정수 승격 문제를 해결하려면 signed를 사용하십시오 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
참조 문자열에서 C ++로 대문자로 변환 (SIMD 문자열 toupper
만 ASCII 동안 그 수표를 사용하여 XOR의 피연산자를 마스킹.)
또한 char 배열에 액세스하고 소문자를 대문자로 바꾸거나 그 반대로 변경하는 방법
(SIMD 내장 함수를 사용하는 C, 알파벳 ASCII 문자의 경우 스칼라 x86 asm case-flip, 다른 문자는 수정하지 않음)
이 트릭은 SIMD (예 : SSE2 또는 NEON)를 사용하여 일부 텍스트 처리를 수동으로 최적화하는 경우에만 유용합니다 char
. 벡터 의 s 중 어느 것도 높은 비트 세트를 가지고 있지 않은지 확인합니다 . (따라서 바이트 중 어느 것도 단일 문자에 대한 멀티 바이트 UTF-8 인코딩의 일부가 아니며 다른 대문자 / 소문자 역수를 가질 수 있습니다). 발견하면 16 바이트의 청크 또는 나머지 문자열에 대해 스칼라로 폴백 할 수 있습니다.
ASCII 범위의 일부 문자 toupper()
또는 tolower()
일부 문자는 해당 범위 밖의 문자, 특히 I ↔ ı 및 İ ↔ i의 터키어를 생성하는 로케일도 있습니다 . 이러한 로케일에서는보다 정교한 검사가 필요하거나이 최적화를 전혀 사용하지 않을 것입니다.
그러나 어떤 경우에는 UTF-8 대신 ASCII를 가정 할 수 있습니다 LANG=C
( 예 : POSIX 로켈이있는 유닉스 유틸리티 ) en_CA.UTF-8
.
당신이 안전 확인할 수 있다면, 당신은 할 수 있습니다 toupper
중간 길이 문자열 훨씬 빠른 호출하는 것보다 toupper()
(5 배 등) 루프, 그리고 마지막으로 내가 부스트 1.58 테스트 훨씬, 훨씬 더 빠른 것보다 boost::to_upper_copy<char*, std::string>()
바보를 수행하는 dynamic_cast
모든 문자.
@
사용하여` 로 변환 할 수 있습니다^ 32
.