Phạm vi chữ cái viết thường và viết thường không vượt qua %32
ranh giới "căn chỉnh" trong hệ thống mã hóa ASCII.
Đây là lý do tại sao bit 0x20
là sự khác biệt duy nhất giữa các phiên bản chữ hoa / thường của cùng một chữ cái.
Nếu đây không phải là trường hợp, bạn cần thêm hoặc bớt 0x20
, không chỉ chuyển đổi và đối với một số chữ cái sẽ có thể thực hiện để lật các bit cao hơn khác. (Và sẽ không có một thao tác nào có thể chuyển đổi và việc kiểm tra các ký tự chữ cái ở vị trí đầu tiên sẽ khó hơn vì bạn không thể | = 0x20 để ép buộc.)
Các thủ thuật chỉ liên quan đến ASCII: bạn có thể kiểm tra ký tự ASCII chữ cái bằng cách buộc chữ thường c |= 0x20
và sau đó kiểm tra xem (không dấu) c - 'a' <= ('z'-'a')
. Vì vậy, chỉ có 3 thao tác: HOẶC + SUB + CMP theo hằng số 25. Tất nhiên, trình biên dịch biết cách tối ưu hóa (c>='a' && c<='z')
thành asm như thế này cho bạn , vì vậy, nhiều nhất bạn nên c|=0x20
tự mình thực hiện phần này. Thật bất tiện khi tự mình thực hiện tất cả các lần truyền cần thiết, đặc biệt là làm việc xung quanh các chương trình khuyến mãi số nguyên mặc định để ký 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
Xem thêm Chuyển đổi một chuỗi trong C ++ sang chữ hoa (chuỗi SIMD toupper
chỉ cho ASCII, che dấu toán hạng cho XOR bằng cách sử dụng kiểm tra đó.)
Và cũng như Cách truy cập một mảng char và thay đổi chữ in thường thành chữ in hoa và ngược lại
(C với nội tại SIMD, và lật x8 asm case-flip cho các ký tự ASCII chữ cái, không để lại chữ cái khác.)
Các thủ thuật này hầu như chỉ hữu ích nếu tối ưu hóa một số xử lý văn bản bằng SIMD (ví dụ SSE2 hoặc NEON), sau khi kiểm tra xem không có char
s nào trong vectơ có bit cao được đặt. (Và do đó, không có byte nào là một phần của mã hóa UTF-8 nhiều byte cho một ký tự, có thể có các nghịch đảo chữ hoa / chữ thường khác nhau). Nếu bạn tìm thấy bất kỳ, bạn có thể quay lại vô hướng cho đoạn 16 byte này hoặc cho phần còn lại của chuỗi.
Thậm chí có một số địa phương nơi toupper()
hoặc tolower()
trên một số ký tự trong phạm vi ASCII tạo ra các ký tự nằm ngoài phạm vi đó, đáng chú ý là tiếng Thổ Nhĩ Kỳ nơi tôi và tôi. Ở những địa phương đó, bạn cần kiểm tra tinh vi hơn hoặc có thể không cố gắng sử dụng tối ưu hóa này.
Nhưng trong một số trường hợp, bạn được phép sử dụng ASCII thay vì UTF-8, ví dụ: các tiện ích Unix có LANG=C
(ngôn ngữ POSIX), không en_CA.UTF-8
hoặc bất cứ điều gì.
Nhưng nếu bạn có thể xác minh đó là an toàn, bạn có thể toupper
chuỗi dài vừa nhanh hơn nhiều so với gọi toupper()
trong một vòng lặp (như 5x), và tôi kiểm tra lần cuối với Boost 1,58 , nhiều nhiều nhanh hơn boost::to_upper_copy<char*, std::string>()
mà không một ngu ngốc dynamic_cast
cho mỗi nhân vật.
@
thành `bằng cách sử dụng^ 32
.