Wie std::wcout benutzen?



  • Hi!

    Ich versuche etwas mit wstrings zu arbeiten und diese auf wcout auszugeben, allerdings gelingt mir das nicht ganz. Zum Testen habe ich mir nun folgendes Minimalbeispiel ausgedacht:

    int main() {
        std::wcout.imbue(std::locale(""));
        std::wstring myString(L"Liebe Grüße!");
        std::wcout << myString << std::endl;
    }
    

    (mein locale is de_DE.UTF-8)

    Als Ausgabe des Programmes erhalte ich nur "Liebe Gr", selbst der Zeilenumbruch durch std::endl wird nicht mehr ausgegeben.

    myString scheint noch korrekt zu sein, wenn ich über die Zeichen iterriere und mir die Codepoints ausgeben lasse, dann ist das "ü" und das "ß" korrekt vorhanden.

    Wie muss ich diesen std::wcout denn nun benutzten? Dokumentation zu den ganzen wchar_t-Objekten in der Standardlib sind auf Google irgendwie schwierig zu finden.

    Danke euch!



  • Hallo,

    ich habe mir gestern mal die Doku von gtkmm durchgelesen und da gab es unter
    anderem folgendes:

    http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/ch03s04.html

    Liess dir das mal durch, vielleicht hilft dir das was dort ueber UTF steht ja
    weiter. Ich kenne ich mich mit UTF nicht aus, aber hoffe das dir der Link
    was bringt (es geht ja jetzt nicht um ustring, sondern um die Erklaerung von
    UTF auf der verlinkten Seite).

    Sry das ich dir nicht genau weiterhelfen kann.

    mfg
    v R



  • virtuell Realisticer schrieb:

    Liess dir das mal durch, vielleicht hilft dir das was dort ueber UTF steht ja
    weiter. Ich kenne ich mich mit UTF nicht aus, aber hoffe das dir der Link
    was bringt (es geht ja jetzt nicht um ustring, sondern um die Erklaerung von
    UTF auf der verlinkten Seite).

    Danke dir, UTF-8 ist mir schon ganz geläufig, aber in der Tat etwas anderes als ich brauche. In std::wstring habe ich ja nicht Bytes stehen. std::wstring entspricht damit wohl eher UCS-2, aber auch das ist weniger das Problem.
    Die Frage ist echt eher wieso mir std::wcout alles außerhalb von US-ASCII verschluckt bzw. die Ausgabe dort sogar einstellt. Ich benutze übrigens Debian Sid, die Standardbibliothek sollte damit recht aktuell sein.

    Mal schauen, vielleicht muss ich mich ja durch den Code der Standardbibliothek mal durchhängeln wie wcout arbeitet, aber ich befürchte das ist nichts zum "schnell mal reinschauen".



  • wchar_t entspricht (beim GCC) UTF-32 (UCS-4), also auch alle w-Sachen. UTF-8 ist eine andere Kodierung, die mit Multibyte Zeichen verteilt auf 8bit große Bytes arbeitet. Dh. die Sonderzeichen von UTF-32 werden von deiner Terminal Emulation auf 8bit Blöcke geschnippselt und als UTF-8 interpretiert, was bedeutet, dass bei nicht US-ASCII Zeichen Multibyte Zeichen gelesen werden, was deine Ausgabe durcheinander wirft.

    Entweder wandelst du dann die Zeichen entsprechend der Lokalen um und gibst sie aus oder du stellst die Terminal Emulation auf UTF-32 um.



  • kingruedi schrieb:

    wchar_t entspricht (beim GCC) UTF-32 (UCS-4), also auch alle w-Sachen. UTF-8 ist eine andere Kodierung, die mit Multibyte Zeichen verteilt auf 8bit große Bytes arbeitet. Dh. die Sonderzeichen von UTF-32 werden von deiner Terminal Emulation auf 8bit Blöcke geschnippselt und als UTF-8 interpretiert, was bedeutet, dass bei nicht US-ASCII Zeichen Multibyte Zeichen gelesen werden, was deine Ausgabe durcheinander wirft.

    Ich versuche mal zu interpretieren was du mit "schnippseln" usw. meinst ...

    kingruedi schrieb:

    Entweder wandelst du dann die Zeichen entsprechend der Lokalen um und gibst sie aus oder du stellst die Terminal Emulation auf UTF-32 um.

    Ich denke nicht, dass ich manuell konvertieren muss. In meinem auf wchar_t basierenden String sind auch die ASCII zeichen ganz normale 32-b-Integer. Da die ASCII-Zeichen aber korrekt ausgegeben werden scheint die Standardbibliothek die Umwandlung in mein Locale schon auszuführen. Damit das korrekt funktionieren sollten, habe ich mit imbue ja auch dem std::wcout gesagt, was mein Locale ist.

    Wenn ich die Ausgabe von meinem Testprogramm durch hexdump pipe, dann sehe ich auch, dass der Programm sehr wohl die Ausgabe nicht als 32-b-Werte vornimmt, sondern mir ASCII-Zeichen auswirft - bzw. mir ab dem ersten Non-ASCII-Zeichen eben nichts mehr auswirft. Man könnte fast meinen dass die libstdc++ meint ich sei in einem US-ASCII-Locale und darum die Ausgabe abbricht, da es keine Kodierung für das entsprechende Zeichen gibt. Das das Locale ist aber auch definitiv gewechselt und nicht mehr das POSIX-Locale, das habe ich getestet indem ich eine Fließkommazahl ausgegeben habe und ich dabei ein Dezimalkomma statt einem Dezimalpunkt bekommen habe. - War nämlich mein erster "Verdacht", dass er mein Locale nicht erkennen würde.

    (BTW: Ja ich meinte oben mit UCS-2 eigentlich UCS-4, hatte ich mich auf die Schnelle vertan.)



  • ASCII Zeichen sind ja in UCS-4 AFAIK gleich, deswegen gibt es dabei keine Probleme. Der Rest wird aber nicht ausgegeben, weil deine Terminal Emulation UTF-8 Zeichen (also Multibyte Sequenzen) lesen will, du aber UTF-32 ausgibst, also die Sequenzen nicht stimmen.

    Genau kenn ich mich mit Terminal Emulationen nicht aus.

    Ich würde mir an deiner Stelle zur Ausgabe einfach einen streambuf schreiben, der UTF-32 dann in UTF-8 umwandelt und ausgibt oder intern direkt UTF-8 benutzen.



  • kingruedi schrieb:

    ASCII Zeichen sind ja in UCS-4 AFAIK gleich, deswegen gibt es dabei keine Probleme. Der Rest wird aber nicht ausgegeben, weil deine Terminal Emulation UTF-8 Zeichen (also Multibyte Sequenzen) lesen will, du aber UTF-32 ausgibst, also die Sequenzen nicht stimmen.

    Die Gleichheit existiert nur zwischen ASCII und UTF-8 sowie "weitgehend" zwischen ASCII und UTF-7.

    In UCS-4/UTF-32 wird jedes Zeichen grundsätzlich über 4 Bytes / 32 Bit dargestellt. Damit kann die Kodierung ja gar nicht der Kodierung mit dem ASCII in einem Ein-Byte-pro-Zeichen-String entsprechen.

    kingruedi schrieb:

    Ich würde mir an deiner Stelle zur Ausgabe einfach einen streambuf schreiben, der UTF-32 dann in UTF-8 umwandelt und ausgibt oder intern direkt UTF-8 benutzen.

    Danke ... ich muss gestehen das Problem ist bei mir derzeit mehr "akademischer" Natur. Möglichkeiten es zu umgehen sehe ich auch. Es geht mir mehr darum zu verstehen wie ein wcout zu benutzen ist und ob ich es falsch mache oder ob es ein Bug in der Stdlib-Implementierung ist. Und sicher wirst du zugeben, dass es "eleganter" wäre einen wstring eben auf ein wcout auszugeben anstatt erst manuelle Umkodierungen durchzuführen.

    Dass es am Terminal liegt schließe ich wie oben geschrieben an sich aus, da dann mir ja zumindest hexdump die ausgegebenen Zeichen anzeigen müsste (als Zahlen natürlich). Auch tut das Terminal ja beispielsweise auch wenn ich

    wprintf(L"Liebe Grüße");
    

    programmiere.

    Ich danke euch aber trotzdem schonmal für eure Überlegungen und werde euch nach der (hoffentlichen) Lösung des Problems auf jeden Fall daran teilhaben lassen.



  • Ich komme der Lösung wohl näher. Ich denke, dass es nicht an meinem Programm liegt, sondern an der STL. Seit ich von gcc 3.3.4 auf gcc 3.4 gewechselt bin ist die Ausgabe schon sinnvoller geworden. Ich erhalte nun "Liebe Gr?sse" und den abschließenden Zeilenumbruch ausgegeben. Sieht schonmal viel besser aus. Interessant finde ich vorallem, dass er mir aus dem "ß" im Programm ein "ss" in der Ausgabe macht.
    Mal schauen, ich werde noch gcc 3.5 pre ausprobieren, vielleicht funktioniert da die Ausgabe dann sogar korrekt, wer weiß. 😉



  • Was muss man in Dev-C++ einstellen/includieren, damit man wcout verwenden kann?



  • Erhard Henkes schrieb:

    Was muss man in Dev-C++ einstellen/includieren, damit man wcout verwenden kann?

    Sorry, ich kenne Dev-C++ nicht und weiß darum nicht, ob du irgendwas spezielles einstellen musst.

    Unter GCC muss ich keine besonderen Bibliotheken linken und der Header, der std::wcout enthält ist auch iostream, also ein normales #include<iostream> am Anfang.



  • Normalerweise solltest du das wie mawis bereits sagte in <iostream> finden, da das ja "nur" Typedefs für die stream-templates mit anderen Template-Parametern sind.



  • Funktioniert in Dev-C++ seltsamerweise nicht. wcout ist nicht bekannt.


Anmelden zum Antworten