wchar_t und UCS/Unicode???



  • Weiß jemand was der Standard zu der Größe des Typs wchar_t sagt?



  • wertebereich zwischen (und einschliesslich) WCHAR_MIN und WCHAR_MAX.
    mindestens 8 bits breit.
    muss so gross sein, dass alle zeichen das 'extended character set' damit dargstellt werden können (z.b. 12 bits, 16 bits oder sowas).



  • Hem, ok. Also doch variabel. Naja, war ja nicht anders zu erwarten. 🙄 Hatte mich nur gewundert, weil im MSVC ist es 2 Bytes groß und MS sagt, das es somit UCS2 und UFT-16 kompatibel ist. Im Web hab ich dann was von 32 bit gelesen, was natürlich bei persistierung der Daten in eine Datei und beim Austausch zwischen zwei unterschiedlichen Plattformen schon zu Komplikationen führen kann. Muß ich mich dann mal genauer damit beschäftigen.



  • Artchi schrieb:

    Hem, ok. Also doch variabel. Naja, war ja nicht anders zu erwarten.

    jo, ausserdem kann's signed oder unsigned sein. ist auch nicht festgelegt.
    zum austausch von daten zwischen verschieden gearteten systemen sollte man sowieso keine eingebauten c/c++ datentypen nehmen, sondern ein eigenes, festgelegtes format (z.b. für wchar_t immer 2 bytes pro zeichen, hi-byte zuerst, o.ä.)...

    btw: du als c++ -fan hast kein iso/iec 14882 greifbar?
    schäm dich 😉



  • Ich schaue normalerweise in Stroustrups Buch rein. 😉

    Jetzt mal etwas, das die Sache weiter strickt. Ich habe versucht mit wstring (aber mit const wchar_t* natürlich genau das gleiche Phänomen) versucht, das ganze in einen Filestream zu schreiben. Sobald Zeichen >255 (also >8 bit) drin sind, werden diese nicht raus geschrieben. 😮 Das Big-Little-Endien und das 16/32-Bit Problem bei wchar_t würde somit garnicht auftauchen!!! 💡

    std::wstring text(L"Hallo \u00A5 \u0627");
    std::wofstream ofs("ucs2_utf16.txt");
    ofs << text;
    

    Ergebnis:
    Hallo wird rausgeschrieben. Auch das \u00A5 für das Yen-Symbol (alles noch 8bit Latin-1) wird korrekt raus geschrieben. Aber das arabische Alif (Unicode 0627) wird nicht raus geschrieben. Habe auch alle anderen möglichen Zeichen >8 Bit ausprobiert. Nichts.

    Habe daraufhin im Stroustrup im Anhang D gestöbert. Wenn ich es richtig verstehe, muß/sollte ich für die Persistierung meine Wide-Strings eh in ein 8-bit Format umwandeln? Habe das Buch jetzt nicht hier liegen, aber so in etwa hieß es, das man Wide-Strings in Unicode konvertieren kann. Im Hauptspeicher machen 8bit-Unicodes (UTF-8) nicht zwingend Sinn, für Datenaustausch aber schon.

    Wer hat schon mal mit diesen ganzen Konvertierungs-Klassen aus der Std-Lib gearbeitet? Immerhin soll die Std-Lib sogar zwischen verschiedenen japanischen Zeichencodierungen unterscheiden können!!! Habe bisher immer gedacht, ISO-C++ hat absolut keinen Plan von Unicode? 🙄

    Werde mich die nächsten Abende mal damit ausführlicher Beschäftigen. Aber falls jemand sein Wissen mitgeben will, bitte hier im Thread weiter geben.



  • Artchi schrieb:

    Jetzt mal etwas, das die Sache weiter strickt. Ich habe versucht mit wstring (aber mit const wchar_t* natürlich genau das gleiche Phänomen) versucht, das ganze in einen Filestream zu schreiben. Sobald Zeichen >255 (also >8 bit) drin sind, werden diese nicht raus geschrieben. 😮 Das Big-Little-Endien und das 16/32-Bit Problem bei wchar_t würde somit garnicht auftauchen!!! 💡

    Was für ein Stream war das? Für wchar_t-Ein/Ausgabe solltest du auch die wchar_t-Streams verwenden (z.B. wifstream)



  • Habe selbstverständlich wfstream benutzt. fstream würde glaube ich meckern. (Typsicherheit)

    Vielleicht noch als Anmerkung: im Debugger von MSVC2003 erscheinen alle Unicodezeichen (Arabisch, Japanisch) vom wstring korrekt! Also der Container von wstring macht es richtig.

    wcout verhält sich analog wofstream und gibt auch nichts aus, wobei ich erst dachte, das liegt an der WinXP-Konsole, die eh nicht Unicode-fähig ist. Aber selbst Müll gibt sie nicht aus, weil wcout nichts an die Konsole gibt.



  • Habe mich etwas weiter informiert und probiert bzg. wchar_t-Strings.

    Der ISO C++ Spec gibt hier keine Konvertierung vor, wenn ich einen Wide-String in ein File speichere und auch umgekehrt. Der Einfachheit haben aber wohl die meisten Standard-Library-Implementierung ein ganz einfaches Verfahren: Zeichenwerte größer 255 werden einfach ignoriert und werden nicht in eine Datei geschrieben.

    Dafür ist die codecvt-Implementierung (eine Locale Facet) zuständig, welcher sich jeder fstream bedient.

    Ich gehe jetzt hier von der Implementierung aus, die meinem MSVC7.1 mitgeliefert wurde. (eine Teil-Lib von Dinkumwares Lib)

    Dinkumware selbst bietet eine komplette Implementierung an, um wstrings mit allen gängigen Codierungen zu konvertieren. Also z.B. um einen wstring in eine UTF-8 Datei zu speichern und auch umgekehrt.

    #include <fstream>
    #include <locale>
    #include "Dinkum/codecvt/utf8"
    .....
        {   // write Hello as one line to a file
        std::wofstream mystr("myfile.txt"); // open file as wide stream
        std::locale loc(std::locale::classic(),
            new Dinkum::codecvt::codecvt_utf8<wchar_t>);
        mystr.imbue(loc);  // replace codecvt<wchar_t, char, std::mbstate_t>
        mystr << L"Hello" << std::endl;
        }
    

    Ich habe mal versucht das ganze bildlich zu verdeutlichen:
    http://www.kharchi.de/codecvt.png

    Hem, da frage ich mich natürlich, warum das C++ Komitee nicht einfach beschliesst, das im nächsten Standard solche Sachen wie codecvt_utf8 oder codecvt_JIS enthalten sein müssen, die entsprechend eine bestimmte Konvertierung nach Norm X vornehmen. 🙄 Dann hätten wir doch das "Problem" mit den Unicode gelöst? Denn im Hauptspeicher arbeiten Java, ICU und Windows NT (ich glaube auch Solaris auch) mit Widecharacter-Strings. Was auch logisch ist, da dies von der Performance am schnellsten ist. Und wenn man Daten übers Netz schickt oder in eine Datei speichert, ist ja erst UTF-8 und Konsorten angebracht.



  • Hier von Boost eine Implementierung für eine Konvertierung von UCS4-Strings (32 bittingen wchar_t!) nach UTF-8 und umgekehrt:
    http://www.boost.org/libs/serialization/doc/codecvt.html

    Ob es auch auf MSVC funktioniert, der UCS2-Strings (16 bittingen wchar_t) hat, weiß ich nicht.

    codecvt_utf8 Vorschlag für ISO C++0x von Dinkumware:
    http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n1957.html 😃 👍 Ob es aufgenommen wurde, weiß ich nicht. Im Working Draft C++0x ist davon leider nichts zu sehen. Aber immerhin wurde etwas eingereicht!


Log in to reply