Unicode_Zeichen mit Konsole ausgeben



  • Ja, das hab ich schon verstanden, dass ich es dort tun sollte, aber dort konnte man nirgends selbst Text eingeben, ich konnte lediglich zwischen drei Fonts auswählen, unter denen auch Lucida Console ist.



  • Ich hab die Seiten von SO jetzt nicht offen, aber war das chcp nicht ein Konmando für die Eingabeaufforderung? Na egal, in ähnlichen Thread auf SO hatte ich gestern gesehen das man das auch über eine Windows-Funktion setzen kann. Wäre dann aber nicht mehr portabel.

    Versuche mal die Ausgabe in ein Programm zu pipen was dir den Hexcode anzeigt und schaue ob es sich um utf-8 handelt. Dann kannst du besser die verschiedenen Versionen prüfen.

    Soll das Programm später auf einen Windows-Webserver laufen oder auf was unixoides? Wenn letzteres würde ich mir um die falsche Ausgabe in der Konsole erstmal keine Gedanken machen und mit std::locale und wcout arbeiten.

    Oder nur mit std::cout und da einfach utf-8 reinschieben. Ich weiß aber nicht ob der Compiler dann meckert. Irgenwer hat mal was geschrieben warum es bei Windows besser schonender für die Nerven ist. Zumindest hatte ich eine Diskussion darüber mit jemanden (SeppJ? evtl.)

    Ich selbst hab kein Windows daher kann ich leider auch nicht weiterhelfen.

    cu
    dirkski



  • Alex1994 schrieb:

    Ja, das hab ich schon verstanden, dass ich es dort tun sollte, aber dort konnte man nirgends selbst Text eingeben, ich konnte lediglich zwischen drei Fonts auswählen, unter denen auch Lucida Console ist.

    Hä? Seit wann kann man in die Konsole keinen Text eintippen?
    Du tippst da doch auch z.B. "dir" ein, um die Dateien anzuzeigen.



  • Also ich habe jetzt einen Test aufs Äußerste gemacht und vier verschiedene Schriften, darunter Arabisch und Kyrillisch in ein und denselben String gepackt und mit einem ganz normalen cout auf der Konsole ausgegeben. Was angezeigt wurde war natürlich Unfug, aber Beschwerden gabs vonseiten des Compilers keine.



  • Sorry, Konsolenfreak, mein Fehler. Es hat sich nun tatsächlich was geändert, die Fragezeichen sind verschwunden und haben einer Zeichensequenz Platz gemacht, die wie eine hexadezimale Codierung aussieht, dann jedenfalls, wenn ich den auszudruckenden String mit dem L-Präfix versehe. Tue ich das nicht, bleibt es bei den Fragezeichen.

    Wie oben gesagt, es ist mir ja eigentlich nicht sonderlich wichtig, wie ich das hier auf meinem Computer sehe, sondern nur, dass es dann am Ende beim Anwender richtig dargestellt wird, siehe mein Beitrag oben.



  • Alex1994 schrieb:

    Also ich habe jetzt einen Test aufs Äußerste gemacht und vier verschiedene Schriften, darunter Arabisch und Kyrillisch in ein und denselben String gepackt und mit einem ganz normalen cout auf der Konsole ausgegeben. Was angezeigt wurde war natürlich Unfug, aber Beschwerden gabs vonseiten des Compilers keine.

    Ok... Zu meinen obigen Post: Ja, war SeppJ und er verwies mich auf dieses Manifest von http://utf8everywhere.org/... Ich habs jetzt aber nicht gelesen.

    So, wenn deine Quellkode-Dateien utf-8 gespeichert sind müsste theoretisch auch utf-8 rauskommen. Theoretisch weil ich irgendwo auf SO gestern gelesen habe das der vc je nach dem ob die Dateien mit oder ohne BOM gespeichert wurden sich anders verhält.

    Prüfe also am besten noch mit einem Hex-Anzeiger ob die Ausgabe des Programms korrektes utf-8 ist.

    cu
    dirkski

    Edit: Eine Anmerkung: Wenn du mit std::string/cout anstatt wstring/wcout arbeitest bekommst du bei Mehr-Byte-Sequenzen eine falsche Länge des Strings (glaub ich, mein ich)...



  • Alex1994 schrieb:

    Sorry, Konsolenfreak, mein Fehler. Es hat sich nun tatsächlich was geändert, die Fragezeichen sind verschwunden und haben einer Zeichensequenz Platz gemacht, die wie eine hexadezimale Codierung aussieht, dann jedenfalls, wenn ich den auszudruckenden String mit dem L-Präfix versehe.

    Der L-Präfix ist ein wchar_t, nicht UTF. UTF-8 wird in C++ mit einem u8-Präfix gekennzeichnet. Aus dem C++-Standard (2.14.5)
    "A string-literal that begins with u8, such as u8"asdf", is a UTF-8 string literal."

    Präfix u ist char16_t. Leider wird nicht gesagt, dass dem UTF-16 entspricht.



  • Alex1994 schrieb:

    Was das Umstellen in der Konsole betrifft: Da ich unter den Eigenschaften nicht direkt chcp 65001 eintippen konnte (ich wüsste nicht wo dort), hab ich es über [HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\Autorun] versucht, aber diese verdammten Fragezeichen halten sich hartnäckig.

    Das "chcp 65001" kannst du auch direkt in deinem Programm machen, mit SetConsoleOutputCP:

    #include <Windows.h>
    #include <Wincon.h>
    ...
    SetConsoleOutputCP(CP_UTF8);
    

    Die Konsole akzeptiert dann tastächlich UTF-8-Ausgabe, allerdings macht dabei zumindest das iostreams- cout von Visual Studio noch irgendeine zusätzliche Magie, so dass es damit dann trotzdem nicht funktioniert.
    Was jedoch lustigerweise dennoch klappt, ist den Text an iostreams vorbei mit Low-Level-Funktionen auszugeben:

    #include <Windows.h>
    #include <Wincon.h>
    #include <io.h>
    #include <string>
    
    auto main() -> int
    {
        SetConsoleOutputCP(CP_UTF8);
        std::string utf8 = u8"ÖÄÜß";
        _write(_fileno(stdout), utf8.data(), static_cast<unsigned int>(utf8.size()));
        return 0;
    }
    

    Hinweis: Mein String war eigentlich "ÖÄÜß Ελληνικά Русский", aber irgendwie scheinen die Code-Tags damit Probleme zu haben.

    Möglich dass es auch mit printf() oder fwrite() funktioniert, das habe ich nicht ausprobiert.
    Kein Wunder, dass sich viele mit UTF-8-Ausgabe unter Windows schwertun, wenn iostreams nicht mitspielt.
    UTF-8-Eingabe kannst du meines Wissens übrigens vergessen - die Ausgabe scheint das höchste der Gefühle auf diesem UTF16-affinen System zu sein.

    Finnegan



  • Wo wir gerade dabei sind, noch ein Wort zu einer anderen Funktion, die ich vor ein paar Tagen im Rahmen meiner Suche nach einer Lösung angetroffen habe. Inwiefern unterscheidet sich denn die Wirkung von z. B. cout.imbue(locale("GERMAN")), also wenn man diese imbue-Funktion auf cout oder cin anwendet, ist es nicht hinreichend setlocale(LC_ALL, "GERMAN") zu schreiben (ungeachtet der Frage, ob es dann auf der Konsole richtig dargestellt wird oder nicht)? Worin besteht denn der Unterschied zwischen beiden?


  • Mod

    setlocale setzt (global) die C-Locale, cout.imbue setzt nur für cout eine C++-Locale. C-Locales betreffen nur C-Funktionen. Setzt man mittels locale::global eine globale C++-Locale betrifft dies aber sowohl C++ als auch C-Funktionen.


Anmelden zum Antworten