2014-09-29 3 views
6

Ich schreibe einige String-Konvertierungsfunktionen ähnlich atoi() oder strtoll(). Ich wollte eine Version meiner Funktion hinzufügen, die char16_t * oder char32_t * anstatt nur char * oder wchar_t * akzeptiert.C11 Unicode-Unterstützung

Meine Funktion funktioniert gut, aber als ich es schrieb, erkannte ich, dass ich nicht verstehe, was char16_t oder char32_t sind. Ich weiß, dass der Standard nur erfordert, dass sie ein Integer-Typ von jeweils mindestens 16 oder 32 Bits sind, aber die Implikation ist, dass sie UTF-16 oder UTF-32 sind.

Ich weiß auch, dass der Standard ein paar Funktionen definiert, aber sie enthalten keine * get oder * Put-Funktionen (wie sie taten, wenn sie in wchar.h in C99 hinzugefügt).

Also frage ich mich: Was erwarten sie von mir mit char16_t und char32_t?

+1

In UTF-8 konvertieren, was sonst? – Deduplicator

+0

@Deduplicator: Wenn das ist, was sie erwartet haben, dass Sie mit ihnen tun, würden Sie denken, dass sie Ihnen Funktionen gegeben hätten, um das zu tun ... –

+0

Planen Sie, nicht nur '0.9' (U + 0030 .. U + 0039) (und möglicherweise 'A..Z/a..z', für die bis zu der höchsten üblichen Stufe, Basis-36), aber alle anderen Zeichen, die in der vollständigen Unicode-Tabelle ebenfalls mit" Numerisch "gekennzeichnet sind? "Dazu gehören typografische Formen (Super- und Indices; eingekreiste Zahlen bis zu 20 (!)) Und skriptspezifische Formen (arabische Zahlen, hebräische Zahlen) sowie römische Zahlen, Altgriechisch und" Zählstäbe "und vieles mehr. – usr2564301

Antwort

9

Das ist eine gute Frage ohne offensichtliche Antwort.

Die in C11 hinzugefügten Typen und Funktionen uchar.h sind weitgehend nutzlos. Sie unterstützen nur Konvertierungen zwischen dem neuen Typ (char16_t oder char32_t) und der Gebietsschema-spezifischen, implementierungsdefinierten Multibyte-Codierung, die nur dann vollständig ist, wenn das Gebietsschema UTF-8-basiert ist. Die nützlichen Konvertierungen (zu/von wchar_t und zu/von UTF-8) werden nicht unterstützt. Natürlich können Sie Ihre eigenen für Conversions zu/von UTF-8 rollen, da diese Conversions zu 100% durch die relevanten RFCs/UCS/Unicode-Standards spezifiziert sind. Aber Vorsicht: Die meisten implementieren sie falsch und haben gefährliche Bugs.

beachte, dass die neue Compiler-Ebene für UTF-8-Funktionen, UTF-16 und UTF-32-Literale (u8, u und U, jeweils) sind potentiell nützlich; Sie können die resultierenden Zeichenfolgen mit Ihren eigenen Funktionen auf sinnvolle Weise verarbeiten, die gar nicht von der Ländereinstellung abhängen. Aber die Bibliothek-Ebene Unterstützung für Unicode in C11 ist meiner Meinung nach im Grunde nutzlos.

+0

Weißt du, wie sehr es die Portabilität einschränkt, um anzunehmen, dass die Multibyte-Codierung UTF-8 ist? (Ich meine, ist das etwas wie "der Standard erlaubt Nicht-2-Ergänzung", die oft in der Praxis ignoriert werden kann, oder ist das wirklich etwas, worüber ich mich sorgen sollte?) – mafso

+0

@mafso: Ich glaube nicht die * interne * Darstellung von Strings als UTF8 ist ein potenzielles Portabilitätsproblem. Aber wie werden Sie Ihren Text anzeigen, wenn es kein tragbares (fast sicher "per definition") Weg gibt, das Ergebnis zu zeigen? – usr2564301

+1

@Jongware: Ich weiß, dass es nicht tragbar ist (in der Theorie). Aber dieses "locale-spezifische Multibyte-Encoding" und "locale-spezifische Wide Character Encoding" wurde mit C89 standardisiert, einer Zeit, in der Unicode-Codierungen nicht so weit verbreitet waren wie heute (IIRC waren sie nicht gerade) zu dieser Zeit standardisiert). Meine Frage ist, ob es heutzutage sicher ist, Unicode-Kodierungen in der Praxis zu akzeptieren. – mafso

3

Testen, ob ein UTF-16 oder UTF-32-Charter im ASCII-Bereich eine der "üblichen" 10 Ziffern ist, +, - oder ein "normaler" Leerraum ist ebenso einfach umzusetzen wie '0'-'9' eine Ziffer. In Anbetracht dessen läuft atoi_utf16/32() wie atoi() weiter. Überprüfen Sie einfach jeweils einen Buchstaben.

Testen, wenn einige andere UTF-16/UTF-32 ist eine Ziffer oder Leerzeichen - das ist härter. Code würde eine erweiterte isspace(), isdigit() benötigen, die Gebietsschemas (setlocale()) haben kann, wenn das benötigte Gebietsschema verfügbar ist. (Anmerkung: wahrscheinlich locale wiederherstellen müssen, wenn die Funktion erfolgt

ein Zeichen konvertieren, die isdigit() passiert, ist aber nicht eine der üblichen 10 auf seinen Wert ist problematisch Anyways, dass erscheint nicht einmal erlaubt werden...

Umwandlungsschritte:

  1. Set locale mit einem entsprechenden für UTF-16/UTF-32

  2. Verwenden isspace() f. oder Weißraumerkennung.

  3. Convert ist eine ähnliche Mode für your_atof().

  4. Wiederherstellung lokal.

+0

Und vergessen Sie nicht, dass UTF-16 und UTF-32 beide Big-Endian und Little-Endian-Varianten haben, und Sie könnten sich interessieren. – JohnH

+0

@JohnH: Wie kann dies für UTF-32 relevant sein? – mafso

+1

@mafso Die big/little endian-Varianten gelten sowohl für UTF-16 als auch für UTF-32. Auf der _byte_-Ebene haben die 2 oder 4 Bytes eine Reihenfolge, die untypisch der Byte-Reihenfolge der Software entspricht. Dies kann durch verschiedene Byte-Umordnungsfunktionen korrigiert werden. Bei einem Unicode-Codepunkt> = 0x10000 und Codierung in UTF-16 tritt die Reihenfolge der 2 UTF-16-Surrogate manchmal in der großen oder kleinen Endian-Reihenfolge auf. Nur eine davon ist richtig (vergiss was).Wenn der falsche Code verwendet wird, sollte er als Kodierungsfehler angezeigt werden, obwohl einige Systeme nachsichtig sind (nicht zu beanstanden). – chux

0

Diese Frage kann ein bisschen alt, aber ich würde gerne bei der Umsetzung Ihrer Funktionen mit char16_t und char32_t Unterstützung berühren.

Der einfachste Weg, dies zu tun, ist Ihre strtoull Funktion schreiben mit demTyp (nennen Sie es so etwas wie strtoull_c32). Dies erleichtert das Parsen von Unicode, da jedes Zeichen in UTF-32 vier Bytes belegt. Implementieren Sie dann strtoull_c16 und strtoull_c8, indem Sie die Codierungen UTF-8 und UTF-16 intern in UTF-32 konvertieren und an strtoull_c32 übergeben.

Ich habe ehrlich gesagt nicht die Unicode-Einrichtungen in der C11-Standard-Bibliothek angeschaut, aber wenn sie keine geeignete Möglichkeit zur Umwandlung dieser Typen in UTF-32 bieten, dann können Sie eine Drittanbieter-Bibliothek verwenden, um die Konvertierung für Sie .

Es gibt ICU, die von IBM gestartet und dann vom Unicode-Konsortium übernommen wurde. Es ist eine sehr funktionsreiche und stabile Bibliothek, die es schon lange gibt.

Ich habe vor kurzem eine UTF-Bibliothek (UTFX) für C89 gestartet, die Sie auch dafür verwenden könnten. Es ist ziemlich einfach und leicht, Einheit geprüft und dokumentiert. Sie könnten das ausprobieren oder mehr darüber erfahren, wie UTF-Konvertierungen funktionieren.

Verwandte Themen