Die alphabetischen Bereiche in Klein- und Großbuchstaben %32
überschreiten im ASCII-Codierungssystem keine "Ausrichtungsgrenze".
Aus diesem Grund ist Bit 0x20
der einzige Unterschied zwischen den Groß- / Kleinbuchstaben desselben Buchstabens.
Wenn dies nicht der Fall wäre, müssten Sie addieren oder subtrahieren 0x20
, nicht nur umschalten, und für einige Buchstaben würde es eine Ausführung geben, um andere höhere Bits umzudrehen. (Und es würde keine einzige Operation geben, die umschalten könnte, und es wäre schwieriger, zunächst nach alphabetischen Zeichen zu suchen, da Sie | = 0x20 nicht zwingen könnten, lcase zu erzwingen.)
Verwandte Nur-ASCII-Tricks: Sie können nach einem alphabetischen ASCII-Zeichen suchen, indem Sie Kleinbuchstaben mit erzwingen c |= 0x20
und dann prüfen, ob (ohne Vorzeichen) c - 'a' <= ('z'-'a')
. Also nur 3 Operationen: OR + SUB + CMP gegen eine Konstante 25. Natürlich wissen Compiler, wie (c>='a' && c<='z')
man so etwas für Sie optimiert , also sollten Sie den c|=0x20
Teil höchstens selbst erledigen . Es ist ziemlich unpraktisch, alle erforderlichen Castings selbst durchzuführen, insbesondere um standardmäßige Ganzzahl-Promotions für signierte zu umgehen 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
Siehe auch Konvertieren einer Zeichenfolge in C ++ in Großbuchstaben (SIMD-Zeichenfolge)toupper
für ASCII, wobei der Operand für XOR mithilfe dieser Prüfung maskiert wird.)
Außerdem erfahren Sie, wie Sie auf ein Zeichenarray zugreifen und Kleinbuchstaben in Großbuchstaben ändern und umgekehrt
(C mit SIMD-Eigenheiten und skalarem x86-Asm-Fall-Flip für alphabetische ASCII-Zeichen, wobei andere unverändert bleiben).
Diese Tricks sind meistens nur nützlich, wenn Sie eine Textverarbeitung mit SIMD (z. B. SSE2 oder NEON) von Hand optimieren, nachdem Sie überprüft haben, ob bei keinem der char
s in einem Vektor das High-Bit gesetzt ist. (Und daher ist keines der Bytes Teil einer Multi-Byte-UTF-8-Codierung für ein einzelnes Zeichen, die möglicherweise unterschiedliche Inversen in Groß- / Kleinbuchstaben aufweist.) Wenn Sie welche finden, können Sie für diesen 16-Byte-Block oder für den Rest der Zeichenfolge auf den Skalar zurückgreifen.
Es gibt sogar einige Gebietsschemas, in denen toupper()
oder tolower()
auf einigen Zeichen im ASCII-Bereich Zeichen außerhalb dieses Bereichs erzeugt werden, insbesondere auf Türkisch, wo I ↔ ı und İ ↔ i. In diesen Gebietsschemas benötigen Sie eine differenziertere Prüfung oder versuchen wahrscheinlich gar nicht, diese Optimierung zu verwenden.
In einigen Fällen dürfen Sie jedoch ASCII anstelle von UTF-8 annehmen, z. B. Unix-Dienstprogramme mit LANG=C
(dem POSIX-Gebietsschema), nichten_CA.UTF-8
oder was auch immer.
Aber wenn Sie überprüfen können, ob es sicher ist, können Sie toupper
Zeichenfolgen mittlerer Länge viel schneller als toupper()
in einer Schleife aufrufen (wie 5x), und zuletzt habe ich mit Boost 1.58 getestet , viel schneller als das, boost::to_upper_copy<char*, std::string>()
was dynamic_cast
für jeden Charakter dumm ist .
@
mithilfe von in ` konvertieren^ 32
.