C++Guns – RoboBlog

11.01.2018

C++ Guns: C++ && Unicode

Filed under: Allgemein — Tags: — Thomas @ 09:01

Vorheriger Post Qt && Unicode

Heute möchste ich Unicode Zeichen mit C++ schreiben. Und zwar mit dem normalen 1 Byte std::string und std::ostream, also std::cout. Mit Qt war das einfach, wie im vorherigen Post zu lesen ist. Die Klasse QString nutz intern 2 Byte Zeichen und sonst kümmert sich Qt ja auch um alles.

Mit std C++ ist es eigentlich auch ganz einfach. Man darf sich nur nicht durch UTF8, UTF16, UTF32, Raw Strings, Kodierungen und Locale verwirren lassen.

Das Problem ist einfach gesagt, dass es viel mehr Zeichen auf der Welt gibt, als mit einem normalen, klassichen 1 Byte char dargestellt werden kann. Da passen nur 256 unterscheidliche Zeichen rein. Von denen werden für ASCII noch viel weniger benutzt. Um mehr Zeichen darzustellen, nutzt man einfach einen größeren Char Type. Da gibt es den wide char wchar_t, der aber nicht standardisiert ist und unter Windows und Linux wohl unterschiedlich viele Byte gelegt.

Die standardisierten Typen lauten char16_t und char32_t mit 2 und 4 Byte. Mit dem 4 Byte Char lassen sich ca. 2 bzw 4 Milliarden unterschiedliche Zeichen darstellen! Das sollte dann wohl reichen.
Leider bezahlt man dafür mit doppelten bzw. vierfachen Speicherplatzverbrauch, was für manche Anwendungen unmöglich ist. Noch dazu möchte man auch kompatibel zu anderen Code sein, der komplett auf std::string setzt. Und das ständige Unterscheiden zwischen std::string, std::wstring, std::u16string und std::u32string ist auch unmöglich.

Also hat man sich überlegt, ob nicht die gebräuchlichsten UTF-32 Zeichen als 1- oder 2 Byte gespeichert werden kann. So ist dann wohl UTF-16 und UTF-8 entstanden.
Konkret bedeutet dies, dass UTF-8 eine Kodierung mit variabler Breite ist. Häufig vorkommende Zeichen passen in 1 Byte, weniger oft verwendete Zeichen in 2 Byte und seltene Zeichen in 3 oder 4 Byte.

Damit ist, bist auf Umlaute, wieder alles gut. Umlaute müssen in UTF-8 als zwei 1 Byte Zeichen kodiert werden. Damit besteht der UTF-8 String u8"L\u00e4cheln!" zwar aus ach Unicode-Zeichen, aber da das zweite Zeichen ein kleines ä ist, welches in UTF-8 als zwei Bytes, nämlich 0xc3a4 kodiert ist, ist der komplette String 9 Zeichen lang!

Dies führt nun zu bestimmten Problemen, wenn Strings nach ihrer Länge ausgewertet werden. Oder wenn Zeichen in UTF-8 Strings gesucht werden. Aus diesem Grund benutzt Qt's QString Klasse wohl UTF-16.

Beispiele:

    std::string UTF8laecheln1 = "Lächeln!";
    std::string UTF8laecheln2 = u8"L\u00e4cheln!";
    std::cout << "locale    : " << UTF8laecheln1 << " size: " << UTF8laecheln1.size() << "\n";
    std::cout << "UTF-8     : " << UTF8laecheln2 << " size: " << UTF8laecheln2.size() << "\n";
    std::cout << u8"\u2581" << u8"\u2582" << u8"\u2583" << u8"\u2584" << u8"\u2585" << u8"\u2586" << u8"\u2587" << u8"\u2588";
locale    : Lächeln! size: 9
UTF-8     : Lächeln! size: 9
????????

Scheint als wäre mein Code Editor schon auf UTF8 eingestellt, der Browser wohl nicht. Die Konvertierung nach UTF-16 ist leider schon wieder so ein Brainfuck, dass ich obwohl mit Beispiel nicht geschafft habe.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress