Unicode_Zeichen mit Konsole ausgeben



  • Hallo zusammen,

    obschon ich natürlich vor diesem Posting im Internet gesucht habe, bin ich noch immer nicht schlauer als vorher. Seit etwa zwei Wochen benutze ich Visual Studio 2015 und bin sehr zufrieden damit. Jedoch wird es wohl C++ 2014 sein, dass dort verwendet wird, daher die Frage hier, da praktisch alle Beiträge, die eine ähnliche Frage wie meine jetzige behandeln älteren Datums sind.

    Wie kann ich unter Windows (oder generell, falls das unabhängig von einem Betriebssystem gehen sollte) beliebige Unicodezeichen auf der Konsole ausgeben? Mir geht es insbesondere um geläufige wie z. B. Buchstaben anderer Alphabete und sowas. Ich habe bereits selbst etwas versucht, aber an der Ausgabe hat sich nichts geändert.

    Vielen Dank!



  • std::wcout ?



  • Windows-only:

    WriteConsoleW() oder ...

    _setmode(_fileno(stdout), _O_U16TEXT);
    std::wcout << ...
    


  • Ok, nach weiterem Versuchen hat es noch immer nicht geklappt, keine Ahnung warum. Warum funktioniert folgendes nicht:

    wstring a = L"Кирилица";
    wcout << a << '\n';

    Was muss ich tun, damit a mit der Konsole angezeigt wird? Ich arbeite mit Visual Studio 2015.



  • Bei mir unter Linux mit gcc kommt erst was wenn ich std::locale gesetzt habe.

    Ungetestet:

    #include <locale>
    #include <iostream>
    
    int main() {
      std::locale::global(std::locale(""));
    
      std::wcout << L"Кирилица\n";
    
    }
    

    Hmm, ich hatte deinen Text kopiert, die Forumssoftware hat das jetzt so kodiert...

    Ach ja, der Quellcode sollte dann auch utf-8 haben.

    hth

    Edit: std:: vor wcout gesetzt 🙄 . trotzdem ungetestet...



  • Das mit std::locale::global(std::locale("")); habe ich auch schon versucht, auch setlocale(LC_ALL, ""), aber stets ohne den gewünschten Erfolg.



  • Du mußt die cmd.exe noch auf eine passende Schriftart umstellen.
    (Consolas?)



  • Das half leider auch nicht. Eigentlich müsste die Lösung mit setlocale, die ich bereits versucht habe, doch funktionieren? Oder liegt es an der Umgebung? Ich benutze Visual Studio 2015.



  • Tja, scheint nicht so einfach zu sein. Was (halbwegs) aktuelles von SO:

    http://stackoverflow.com/questions/32330970/c11-stdcout-string-literal-in-utf-8-to-windows-cmd-console-visual-stu

    mfg



  • Versuche mal die Konsole auf UTF umzustellen. Durch Anklicken des Fenstersymbols ganz oben links im Eingabeaufforderungsfenster geht man über "Eigenschaften" zu den Schriftarten. Dort Lucida Console wählen. Dann chcp 65001 eintippen. Das stellt die Konsole auf UTF-8 ein. UTF-16 weiß ich nicht, müsste ähnlich gehen.



  • Den SO-Beitrag habe ich auch schon gelesen, aber das stiftete nur noch mehr Verwirrung.

    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.

    Ich sollte an dieser Stelle auch mal erwähnen, warum ich das überhaupt brauche. Ich schreibe derzeit ein Programm, dass ich, sollte es mir gelingen, vielleicht auf einer Webisite zur Verfügung stelle. Meine Befürchtung (vielleicht zu Unrecht) ist, wenn Unicode-Zeichen in der Ausgabe vorkommen und die in der Ausgabe des Programms schon falsch angezeigt werden, dann könnten sie ja auch im Browser falsch angezeigt werden. Mir ist bekannt, dass man in HTML die Metaangabe <meta charset = "UTF-8"> machen kann, aber würde das dann auch tatsächlich dafür sorgen, dass die Ausgabe des Programms richtig angezeigt wird? Ich hatte auch die Idee, dass ich die Ausgabe einfach in eine Datei speichere, die die Ausgabe a priori in UTF-8 speichert und ich dann einfach diese Datei als Antwort auf einen Request zurückliefere, aber vielleicht ist das ja gar nicht nötig. Ich bin mir nicht sicher, ich habe mich vor drei Monaten mal nicht allzu ausführlich mit Webprogrammierung befasst, um mir einen kleinen Überblick zu verschaffen.



  • 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), ...

    Nicht dort, sondern direkt in der Konsole! ("Eingabeaufforderungsfenster")



  • 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


Log in to reply