2012-09-22 5 views
8

Ich habe Microsoft Visual Studio 2010 auf Windows 7 64bit. (In Projekteigenschaften „Zeichensatz“ auf „nicht festgelegt“, aber jede Einstellung zu gleicher Leistung führt.)Erklärung benötigt für eine UTF-8 vs cpp Fall

Quellcode:

using namespace std; 
    char const charTest[] = "árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP\n"; 
    cout << charTest; 
    printf(charTest); 
    if(set_codepage()) // SetConsoleOutputCP(CP_UTF8); // *1 
    cerr << "DEBUG: set_codepage(): OK" << endl; 
    else 
    cerr << "DEBUG: set_codepage(): FAIL" << endl; 
    cout << charTest; 
    printf(charTest); 

* 1: Einschließlich windows.h vermasseln Dinge, so dass ich Ich nehme es aus einer separaten cpp.

Die kompilierte Binärdatei enthält die Zeichenfolge als korrekte UTF-8-Bytefolge. Wenn ich die Konsole mit chcp 65001 auf UTF-8 setze und type main.cpp ausstelle, wird die Zeichenfolge korrekt angezeigt.

Test (Konsole eingestellt Lucida Console Schriftart verwenden):

D:\dev\user\geometry\Debug>chcp 
Active code page: 852 

D:\dev\user\geometry\Debug>listProcessing.exe 
├írv├şzt┼▒r┼Ĺ t├╝k├Ârf├║r├│g├ęp ├üRV├ŹZT┼░R┼É T├ťK├ľRF├ÜR├ôG├ëP 
├írv├şzt┼▒r┼Ĺ t├╝k├Ârf├║r├│g├ęp ├üRV├ŹZT┼░R┼É T├ťK├ľRF├ÜR├ôG├ëP 
DEBUG: set_codepage(): OK 
��rv��zt��r�� t��k��rf��r��g��p ��RV��ZT��R�� T��K��RF��R��G��P 
árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP 

Was ist die Erklärung dahinter? Kann ich irgendwie fragen cout als printf arbeiten?

ATTACHMENT

Viele sagen, dass Windows-Konsole nicht UTF-8-Zeichen überhaupt nicht unterstützt. Ich bin ein ungarischer Mann in Ungarn, mein Windows auf Englisch eingestellt ist (mit Ausnahme von Datumsformaten, werden sie auf Ungarisch festgelegt) und kyrillische Buchstaben sind noch richtig neben ungarischen Buchstaben angezeigt:

Hungarian and Cyrillic letters on console at the same time

(Meine Standardkonsole Codepage ist CP852)

+0

mögliche Duplikat von [Wie schreibe ich eine std :: Codecvt Facette?] (http: // stackoverflow.com/questions/ 2971386/how-do-ich-schreibe-a-stdcodecvt-facette) –

+0

@HansPassant Ich glaube nicht, dass es das gleiche ist. Es scheint verwandt zu sein, erklärt aber nicht explizit den Unterschied zwischen "cout" und "printf". Und sollte ich auch eine 'Codecvt'-Facette schreiben, um' Cout' zu sagen, nichts zu konvertieren? Es sollte einen einfacheren Weg geben, hoffe ich ... – Notinlist

Antwort

4

Die Unterschiede hier ist, wie C++ - Laufzeit und C-Bibliothek Systemgebietsschema behandelt.

Um gleiches Ergebnis mit std :: cout erreichen Sie std::ios::imbue Methode versuchen würden und std::locale

Aber Hauptsache mit utf-8 und C++ beschrieben here

C++ 03 bietet zwei Arten von String-Literalen. Die erste Art, die in Anführungszeichen steht, erzeugt ein nullterminiertes Array vom Typ const char. Die zweite Art, definiert als L "", erzeugt ein nullterminiertes Array vom Typ const wchar_t, wobei wchar_t ein Wide-Zeichen ist. Beide Literaltypen bieten keine Unterstützung für Zeichenfolgenliterale mit UTF-8, UTF-16 oder anderen Unicode-Codierungen.

Also sowieso ist es alle Implementierung spezifisch und folglich nicht tragbar, weil nicht von den Standard-C + + Ausgabeströmen UTF-8 verstehen können.

+0

Was codiert die Strea ms Unterstützung ist Implementierung definiert. Auf meinem Linux-Rechner funktioniert ein Standard-Iostream gut mit utf8. Vielleicht gibt es eine Einstellung oder einen API-Aufruf, den er unter Windows verwenden kann, um die gleichen Ergebnisse zu erhalten. – Sqeaky

+0

Ich kann nicht warten, bis viele C++ 11-Implementierungen die vorgeschlagenen String-Literale wie u8, U und u erhalten. Ich arbeite mit einem internationalen Produkt und es würde unser Leben so viel einfacher machen. – stinky472

+0

Möglicherweise können Sie ein integriertes Gebietsschema finden, das UTF-8 verarbeitet, wie im Beispiel unter http://en.cppreference.com/w/cpp/locale/codecvt zu sehen ist, oder Sie können einen Weg finden, 'codecvt_byname' zu ​​verwenden ': http://en.cppreference.com/w/cpp/locale/codecvt_byname –

1

Unter Windows werden Einzelbyte-Zeichenfolgen normalerweise als ASCII oder eine 256-Zeichen-Codepage interpretiert. Das bedeutet, dass Sie keine echte Unicode-Unterstützung erhalten.

Die kurze Antwort ist: Verwenden Sie breite Zeichenfolgen (z. B. L""árvíztűr..." - beachten Sie die L) und schreiben Sie dann wcout anstelle von cout. Windows interpretiert in der Regel breite (2 Bytes unter Windows) Strings als UTF-16 (oder zumindest eine Close-Variante), so dass es wie vorgesehen funktioniert. Verwenden Sie unter Windows immer breite Zeichenfolgen, um Codierungsprobleme zu vermeiden.

+0

Gibt es nicht ein Problem mit wcout, das Unicode intern in CP_ACP umwandelt und dann zurück in Unicode, so dass wcout Unicode tatsächlich nicht unterstützt? – Dialecticus

+0

@Dialecticus - wcout hat immer gut für mich gearbeitet. – AshleysBrain

+3

Es ist die Ausgabe der Windows-Konsole, die mit UTF-8 nicht funktioniert (es ist keine gültige Codepage für die Konsole selbst). Die C++ - Schicht darüber versäumt es, die schlaue Sache zu tun. – rubenvb

1

Zuerst Windows-Konsole unterstützt nicht UTF-8 (Codepage 65001, um dies zu testen öffnen Sie eine UTF-8-codierte Datei, die mit Notepad in der Konsole gespeichert und Sie werden Junk-Daten in der Konsole sehen), so in Um Ihre Ausgabe zu überprüfen, sollten Sie sie in eine Datei oder etwas Ähnliches umleiten und das Ergebnis von dort überprüfen (myapp> test.txt).

zweite in C/C++ char [] ist eine Folge von Zeichen, die sowieso interpretiert werden kann, die Programmierer wollen, aber UTF-8 ist ein spezielles Protokoll zum Unicode-Zeichensatz zu codieren, so gibt es keine Möglichkeit (neben C++ 11) dass Sie eine Sequenz von Zeichen schreiben und diese Zeichen in UTF8 codiert haben, weil ich sagen werde char p[3] = "اب", aber wenn der Compiler dies in UTF-8 verschlüsseln will, benötigt er 5 Bytes, nicht 3. Sie sollten also etwas verwenden, das UTF-8 versteht.

Ich empfehle die Verwendung boost::locale::conv::utf_to_utf mit breiten String-Konstanten. zum Beispiel

std::string sUTF8 = boost::locale::conv::utf_to_utf(L"árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP\n"); 
std::cout << sUTF8; // or printf("%s", sUTF8.c_str()); 

dies stellt sicher, dass Sie UTF-8-String haben, aber auch hier kann es nicht mit Konsole überprüfen, da es UTF-8 nicht verstehen überhaupt !!.

+0

Sie liegen falsch. Setzen Sie die Schriftart auf "Lucida Console", geben Sie einen 'chcp 65001' aus und sehen Sie, dass UTF-8-Zeichen korrekt angezeigt werden (nur die Byte-Reihenfolge wird als leeres Rechteck angezeigt). Ich habe es in diesem Moment erneut getestet. Diese Schritte werden in der Frage behandelt. – Notinlist

+0

Ich werde diese Boost-Funktion später zu Hause versuchen. Danke für diesen Hinweis. – Notinlist

+0

Ich habe getan, was Sie sagen, setzen Sie die Schriftart zu 'Lucida Console' und eine' chcp 65001' ausgeben, aber es zeigt nur Rechtecke, wenn Sie sie sehen können, ist es möglicherweise, weil die Zeichen, die Sie in Ihrer UNICODE-Datei aus CP_ACP verwendet (Standard-Codepage des Systems, die über das Control Panel geändert werden kann). Verwenden Sie Zeichen aus anderen Sprachen wie Japanisch oder so ähnlich und Sie werden sehen, dass Konsole sie nicht zeigen kann – BigBoss

2

Die in der Befehlszeile scheint irgendwie mit UTF-8 für mein Verständnis

  1. Eine Schrift zur Anzeige UTF-8-Zeichen
  2. Stellen Sie die richtige Codepage in der Befehlszeile (chcp fähig zu arbeiten 65001) nicht unbedingt die volle UTF-8-Zeichen unterstützt, wenn dieser Code Seite, aber es scheint die beste verfügbare

Check it here und erwiesen here

[EDIT] tatsächlich 65001 tatsächlich ist UTF-8, nachdem ich in Powershell

PS C:\Users\forcewill> chcp 65001 
Active code page: 65001 
PS C:\Users\forcewill> [Console]::OutputEncoding 


BodyName   : utf-8 
EncodingName  : Unicode (UTF-8) 
HeaderName  : utf-8 
WebName   : utf-8 
WindowsCodePage : 1200 
IsBrowserDisplay : True 
IsBrowserSave  : True 
IsMailNewsDisplay : True 
IsMailNewsSave : True 
IsSingleByte  : False 
EncoderFallback : System.Text.EncoderReplacementFallback 
DecoderFallback : System.Text.DecoderReplacementFallback 
IsReadOnly  : True 
CodePage   : 65001 

geprüft können Sie die Powershell seine viel mächtiger dann mit dem alten cmd.exe

Edit: Über cout, wenn wir mit im Visual Studio sprechen die richtige Antwort ist here eine mehr Tourough Erklärung kann gefunden werden here über die besten Praktiken in Visual Studio

+0

Vielen Dank für Ihre Unterstützung in diesem Unterthema, aber die Hauptfrage geht um Verwenden von "cout" zum Anzeigen von UTF-8-Sequenzen. – Notinlist

+0

Eigentlich bezieht sich die Frage auch auf Visual Studio, also habe ich meine Antwort aktualisiert, um das Thema aufzunehmen, in Visual Studio sollten Sie die windows.h einschließen und den Präprozessor-Makro UNICODE definieren und das L-Makro verwenden, um statische Zeichenfolgen zu deklarieren im letzten link habe ich jetzt in meinem Awnser, – forcewill

+0

etwas bewegt, aber noch nicht glatt. Ich werde morgen weitermachen. – Notinlist

Verwandte Themen