Umgebungsunabhängige Unicode-Strings



  • Hallo,

    ich bin neu hier im Forum, deswegen möchte ich mich zuerst einmal vorstellen 🙂 Ich bin eigentlich noch Programmieranfänger, aber programmiere im Moment schon einige Zeit mit Python. Das ist auch eigentlich eine ganz nette Sprache, aber ich würde auch gerne etwas C++ lernen (hauptsächlich um bei Open-Source-Anwendungen mithelfen zu können).

    Naja, die grundlegende C++-Programmierung klappt auch schon ganz gut, aber mich wundert bei C++ eine Sache: Wie bekomme ich umgebungsunabhängige Unicode-Strings hin? Wenn ich einfach nur die normalen String-Klasse aus der Standardbibliothek nutze, werden ja einfach nur die Bytes gespeichert, was ja folgende Effekte hat (siehe auch hier):

    1. Der Quelltext muss in UTF-8 kodiert sein → auf einem normalen Linux-System wird es richtig angezeigt, unter Windows mit CP-1252 kommt dann natürlich Chaos bei heraus.
    2. Würde ich den Quelltext mit CP-1252 speichern, kriege ich unter Linux dann nur Zeichensalat.
    3. Will ich alles noch von Dateien lesen/speichern, habe ich noch mehr Chaos.

    Unter Python (3) wird der ganz normale String ja intern als Unicode verwaltet und der Interpreter erkennt automatisch, welche Kodierung die Konsole hat. Der Quelltext kann ja auch als UTF-8 gespeichert werden, so dass es mit Python eigentlich gar keine Probleme mit Kodierungen gibt.

    Daher wollte ich fragen, ob man das auch irgendwie mit C++ erreichen kann? Die Standardbibiliothek scheint das ja nicht herzugeben, aber gibt es dafür eine bequeme Bibliothek, die die Zeichenketten intern als Unicode speichert, die nötigen Umwandlungen vollautomatisch durchführt und auch nach belieben in andere Kodierungen umwandelt? Ich glaaaube, dass Qt mit den QStrings so etwas anbietet, aber bei einer Konsolenanwendung direkt Qt einzubinden scheint mir etwas zu sehr wie mit Kanonen auf Spatzen zu schießen.

    Schon einmal vielen Dank 🙂



  • Mit welcher Kodierung Du Deinen Quellcode hast, ist nicht so wichtig. Hauptsache, man weiß welche und der Compiler unterstützt diese. Beim GCC gibt's z.B. extra Kommandozeilen-Parameter, über die dem Compiler sagen kann, welches Encoding die Quellcodedateien haben und so weiter. Ich würde aber UTF-8 nehmen.

    Wenn Du String-Konstanten im Quellcode brauchst, wo Zeichen außerhalb des "basic character sets" vorkommen sollen, müsstest Du das...

    // so ...
    const char s1[] = u8"Täterätätä";
    
    // oder so ...
    const char s2[] = u8"T\u00E4ter\u00E4t\u00E4t\u00E4";
    

    machen können. Letzteres erlaubt es Dir, den Quellcode im ASCII-Subset zu speichern.

    Das u8 am Anfang ist wichtig. Das sagt dem Compiler, dass er daraus ein UTF-8 String machen soll -- auch wenn Dein Quellcode z.B. in ISO-8859-15 abgespeichert wurde und auch so vom Compiler verstanden wird. Einen UTF-8-String kannst Du problemlos in einer string -Variablen speichern. Du musst allerdings berücksichtigen, dass ein Code-Point so auf eine variable Anzahl von Bytes abgebildet wird und dass die Schnittstelle von std::string eben nur Byte-orientiert ist und nichts von Code-Points weiß.

    Für Ein-/Ausgabe zur Laufzeit bräuchtest Du wahrscheinlich noch eine Abstraktionsschicht, die ggf das Übersetzen übernehmen würde. In der Standardbibliothek gibt's da meines Wissens nach nichts fertiges. std::cout und std::cin arbeiten mit dem "execution character set" und das ist eben plattformabhängig.

    Für die Konvertierung zwischen UTF-8, UTF-16 und UTF-32 kann ich Dir UTFCPP empfehlen.

    Wie man jetzt relativ einfach und portabel UTF-8 auf einer Konsole ausgeben kann, so dass zumindest die Zeichen aus ISO-8859-15 auf richtig erscheinen (egal wo, unter Windows oder Linux oder was weiß ich), weiß ich nicht. Ich denke, da muss man wirklich Hand anlegen und plattformabhängige Konvertierungen irgendwo in einer Zwischenschicht verstecken. Wenn es so'was schon gibt, wär' ich dankbar für eine Referenz.

    Wenn man eine GUI-Anwendung bauen will übernehmen Frameworks à la Qt das mit der systemspezifischen Übersetzung.



  • die Unicode-Unterstützung von C++ und der Standardbibliothek ist noch sehr bescheiden. Soweit ich weiß, beschränkt sich das aktuell nur auf char16_t für UTF-16, char32_t für UTF-32 und char für UTF-8, wobei es noch dazu passende Stringliterale

    u8"kodiert mit UTF-8" // char[]
    u"kodiert mit UTF-16" // char16_t[]
    U"kodiert mit UTF-32" // char32_t[]
    

    und Zeichenliterale

    u'ä' // char16_t (Beschränkung auf die "basic plane" AFAIK)
    U'ä' // char32_t
    

    gibt.

    Das Hin- und Herkonvertieren und Unicode Ein-/Ausgabe gibt es AFAIK nicht in der Standardbibliothek.



  • Und wenn ich das hier richtig deute, scheint Windows 7 generell ein Problem mit Codepoints in der Konsole zu haben, die außerhalb der Basic Multilingual Plane liegen. Das läuft untenrum anscheinend über UTF-16, ohne dass die Konsole wirklich erwartet, dass mal ein Zeichen aus mehr als einem 16bit-Wert besteht. Also doch nur UCS-2/BMP in der Konsole. Shame on you, Microsoft.





  • Ah, danke an die vielen Antworten 🙂

    Hm, so wie ich das sehe, scheint es doch wirklich so unbequem zu sein, wie ich dachte. Der Vorteil an Python ist ja eben, dass das alles vollautomatisch im Hintergrund passiert.

    Ich werde es mal mit den Tipps hier versuchen. Ansonsten bleibe ich für Konsolenanwendungen vielleicht doch lieber bei Python, scheint mir eventuell etwas bequemer zu sein 😃

    Danke!



  • Das sind halt verschiedene Sprachen mit unterschiedlichen Abstraktionsniveaus und auch Zielen.

    Python ist interpretiert und nimmt dir viel Arbeit ab. Umgekehrt hast du quasi keinerlei Kontrolle auf Hardwareebene und bist um einen gewaltigen Faktor langsamer.

    Kommt halt immer drauf an was du vorhast und wofür... 🙂



  • Ja, das stimmt. Allerdings dachte ich, dass sich C++ durch solche Bibliotheken ganz gut nachrüsten ließe.

    Ich werde das aber mal mit den QStrings ausprobieren, wobei ich bei Qt noch ein wenig Probleme habe, den Compiler einzurichten. Das finde ich bei normalem C++ ja schon schwierig, und dann Qt mit dem Moc noch problematischer.


Anmelden zum Antworten