Unicode-Glossar
Unicode ist ein umfangreiches und komplexes Thema. Ich möchte dort nicht zu tief waten, aber ein kurzes Glossar ist notwendig:
- Punkte Code : Code Punkte sind die grundlegenden Bausteine von Unicode, ein Codepunkt ist nur eine ganze Zahl auf einem zugeordneten Bedeutung . Der ganzzahlige Teil passt in 32 Bit (also wirklich 24 Bit), und die Bedeutung kann ein Buchstabe, ein diakritischer Wert, ein Leerzeichen, ein Zeichen, ein Smiley, eine halbe Flagge usw. sein, und es kann sogar "the" sein nächster Teil lautet von rechts nach links ".
- Graphemcluster : Graphemcluster sind Gruppen von semantisch verwandten Codepunkten. Beispielsweise wird ein Flag in Unicode durch Zuordnen von zwei Codepunkten dargestellt. Jede dieser beiden hat für sich genommen keine Bedeutung, ist jedoch in einem Graphemcluster miteinander verbunden und repräsentiert ein Flag. Graphemcluster werden in einigen Skripten auch verwendet, um einen Buchstaben mit einem diakritischen Zeichen zu koppeln.
Dies ist die Basis von Unicode. Die Unterscheidung zwischen Codepunkt und Graphemcluster kann größtenteils beschönigt werden, da für die meisten modernen Sprachen jedes "Zeichen" einem einzelnen Codepunkt zugeordnet ist (es gibt spezielle akzentuierte Formen für häufig verwendete Buchstaben- / diakritische Kombinationen). Wenn Sie sich jedoch in Smileys, Flaggen usw. wagen, müssen Sie möglicherweise auf die Unterscheidung achten.
UTF-Grundierung
Dann muss eine Reihe von Unicode-Codepunkten codiert werden. Die gemeinsamen Codierungen sind UTF-8, UTF-16 und UTF-32, wobei die beiden letzteren sowohl in Little-Endian- als auch in Big-Endian-Form existieren, für insgesamt 5 gemeinsame Codierungen.
In UTF-X, X die Größe in Bits der Code Einheit , jeder Code Point als eine oder mehrere Kode Units in Abhängigkeit von ihrer Größe dargestellt wird:
- UTF-8: 1 bis 4 Codeeinheiten,
- UTF-16: 1 oder 2 Codeeinheiten,
- UTF-32: 1 Codeeinheit.
std::stringund std::wstring.
- Nicht verwenden,
std::wstringwenn Sie Wert auf Portabilität legen ( wchar_tunter Windows sind es nur 16 Bit). benutze std::u32stringstattdessen (aka std::basic_string<char32_t>).
- Die speicherinterne Darstellung (
std::stringoder std::wstring) ist unabhängig von der Darstellung auf der Festplatte (UTF-8, UTF-16 oder UTF-32). Bereiten Sie sich also darauf vor, dass Sie an der Grenze konvertieren müssen (Lesen und Schreiben).
- Während ein 32-Bit
wchar_tsicherstellt, dass eine Codeeinheit einen vollständigen Codepunkt darstellt, repräsentiert sie immer noch keinen vollständigen Graphemcluster.
Wenn Sie nur Zeichenfolgen lesen oder komponieren, sollten Sie keine oder nur geringe Probleme mit std::stringoder haben std::wstring.
Probleme beginnen, wenn Sie mit dem Schneiden und Würfeln beginnen. Dann müssen Sie auf (1) Codepunktgrenzen (in UTF-8 oder UTF-16) und (2) Graphemclustergrenzen achten. Ersteres kann problemlos selbst gehandhabt werden, letzteres erfordert die Verwendung einer Unicode-fähigen Bibliothek.
Pflücken std::stringoder std::u32string?
Wenn die Leistung ein Problem darstellt, ist es wahrscheinlich, dass std::stringdie Leistung aufgrund des geringeren Speicherbedarfs besser ist. obwohl starker Gebrauch von Chinesisch das Geschäft ändern kann. Wie immer Profil.
Wenn Graphemcluster kein Problem darstellen, std::u32stringhat dies den Vorteil, dass die Dinge vereinfacht werden: 1 Codeeinheit -> 1 Codepunkt bedeutet, dass Sie Codepunkte nicht versehentlich aufteilen können und alle Funktionen sofort einsatzbereit sind std::basic_string.
Wenn Sie mit Software verbunden sind std::stringoder char*/ char const*, halten Sie sich an std::string, um hin und her Konvertierungen zu vermeiden. Sonst wird es ein Schmerz sein.
UTF-8 in std::string.
UTF-8 funktioniert eigentlich ganz gut in std::string.
Die meisten Vorgänge funktionieren sofort, da die UTF-8-Codierung selbstsynchronisiert und abwärtskompatibel mit ASCII ist.
Aufgrund der Art und Weise, wie Codepunkte codiert werden, kann die Suche nach einem Codepunkt nicht versehentlich mit der Mitte eines anderen Codepunkts übereinstimmen:
str.find('\n') funktioniert,
str.find("...")funktioniert für den Abgleich von Byte für Byte 1 ,
str.find_first_of("\r\n")funktioniert bei der Suche nach ASCII-Zeichen .
Ebenso regexsollte meistens sofort funktionieren. Da eine Folge von Zeichen ( "haha") nur eine Folge von Bytes ( "哈") ist, sollten grundlegende Suchmuster sofort funktionieren.
Seien Sie jedoch vorsichtig bei Zeichenklassen (z. B. [:alphanum:]), da diese je nach Regex-Geschmack und Implementierung möglicherweise mit Unicode-Zeichen übereinstimmen oder nicht.
Seien Sie in ähnlicher Weise vorsichtig, wenn Sie Repeater auf Nicht-ASCII- "Zeichen" anwenden, und betrachten Sie "哈?"möglicherweise nur das letzte Byte als optional. Verwenden Sie Klammern, um die wiederholte Folge von Bytes in solchen Fällen klar abzugrenzen : "(哈)?".
1 Die Schlüsselkonzepte für die Suche sind Normalisierung und Sortierung. Dies betrifft alle Vergleichsoperationen. std::stringvergleicht (und sortiert) immer Byte für Byte, ohne Rücksicht auf sprach- oder verwendungsspezifische Vergleichsregeln. Wenn Sie die vollständige Normalisierung / Sortierung durchführen möchten, benötigen Sie eine vollständige Unicode-Bibliothek, z. B. die Intensivstation.