2012-09-22 8 views
8

Ho Microsoft Visual Studio 2010 su Windows 7 a 64 bit. (Nella proprietà del progetto "Set di caratteri" è impostato su "Non impostato", tuttavia ogni impostazione porta ad stessa uscita.) CodiceSpiegazione necessaria per un caso UTF-8 vs cpp

Fonte:

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: Compreso windows.h scombina le cose, così ho lo includo da una cpp separata

Il file binario compilato contiene la stringa come sequenza di byte UTF-8 corretta. Se imposto la console su UTF-8 con chcp 65001 e sul numero type main.cpp, la stringa viene visualizzata correttamente.

Test (console impostato per utilizzare font Lucida Console):

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 

Qual è la spiegazione dietro questo? Posso in qualche modo chiedere allo cout di funzionare come printf?

ATTACCO

Molti dice che console di Windows non supporta caratteri UTF-8 a tutti. Sono un ragazzo ungherese in Ungheria, il mio Windows è impostata su Inglese (tranne formati di data, sono impostati ungherese) e caratteri cirillici vengono ancora visualizzati correttamente al fianco di lettere ungheresi:

Hungarian and Cyrillic letters on console at the same time

(la mia console di default codepage è CP852)

+0

possibile duplicato di [Come scrivere un facciale: codecvt facet?] (http: // stackoverflow.com/questions/ 2971386/how-do-i-write-a-stdcodecvt-facet) –

+0

@HansPassant Non credo che sia lo stesso. Sembra correlato, ma non spiega esplicitamente la differenza tra 'cout' e' printf'. E dovrei scrivere anche una faccetta 'codecvt' per dire a' cout' di non convertire nulla? Ci dovrebbe essere un modo più semplice, spero ... – Notinlist

risposta

4

Le differenze qui sono il modo in cui il runtime C++ e la libreria C gestiscono le impostazioni locali del sistema.

Per ottenere lo stesso risultato con std :: cout si può provare std::ios::imbue metodo e std::locale

Ma problema principale con utf-8 e C++ descritto here

C++ 03 offre due tipi di stringhe letterali. Il primo tipo, contenuto tra virgolette doppie, produce una matrice di tipo const con terminazione null. Il secondo tipo, definito come L "", produce una matrice di tipo termin-null con const wchar_t, dove wchar_t è un carattere wide. Né il tipo letterale offre supporto per stringhe letterali con UTF-8, UTF-16 o qualsiasi altro tipo di codifica Unicode.

Quindi, in ogni caso, è tutta specifica dell'implementazione e quindi non portabile, perché i flussi di output standard del C++ non sono in grado di comprendere utf-8.

+0

Cosa codifica per la strea il supporto ms è definito dall'implementazione. Sulla mia macchina Linux un iostream predefinito funziona perfettamente con utf8. Forse c'è qualche impostazione o qualche chiamata API che può usare su Windows per ottenere gli stessi risultati. – Sqeaky

+0

Non vedo l'ora che molte implementazioni di C++ 11 ottengano quei letterali di stringa proposti come u8, U e u. Lavoro con un prodotto internazionale e renderebbe le nostre vite molto più semplici. – stinky472

+0

Potrebbe essere possibile trovare un locale integrato che gestisca UTF-8 come mostrato nell'esempio su http://en.cppreference.com/w/cpp/locale/codecvt o forse si può trovare un modo per usare 'codecvt_byname ': http://en.cppreference.com/w/cpp/locale/codecvt_byname –

1

Su Windows, le stringhe a byte singolo vengono in genere interpretate come ASCII o una codepage di 256 caratteri. Ciò significa che non riceverai il vero supporto Unicode.

La risposta breve è: utilizzare stringhe ampie (ad esempio L""árvíztűr..." - notare la L) quindi scrivere a wcout anziché cout. Windows solitamente interpreta le stringhe di larghezza (2 byte su Windows) come UTF-16 (o almeno una variante chiusa), quindi funzionerà come previsto. Su Windows usa sempre stringhe ampie per evitare problemi di codifica.

+0

Non c'è un problema con wcout, che converte internamente Unicode in CP_ACP, e poi di nuovo in Unicode, così che wcout non supporta infatti Unicode? – Dialecticus

+0

@Dialecticus - wcout ha sempre funzionato bene per me. – AshleysBrain

+3

È l'output della console di Windows che non funziona con UTF-8 (non è una codepage valida per la console stessa). Il livello C++ su di esso non sta facendo proprio la cosa intelligente. – rubenvb

1

Prima di tutto la console di Windows non supporta UTF-8 (codepage 65001, per testare questo apre un file codificato UTF-8 che viene salvato con il blocco note in console e vedrai i dati spazzatura nella console), quindi in per verificare l'output, devi reindirizzare a un file o qualcosa del genere e controllare i risultati da lì (myapp> test.txt).

secondo in C/C++ char [] è una sequenza di caratteri che può essere interpretata comunque dal programmatore, ma UTF-8 è un protocollo speciale per codificare il set di caratteri unicode, quindi non c'è modo (accanto a C++ 11) che scrivi una sequenza di caratteri e quei caratteri codificati in UTF8 perché dirò char p[3] = "اب", ma se il compilatore vuole codificarlo in UTF-8 ha bisogno di 5 byte non 3. quindi dovresti usare qualcosa che comprenda UTF-8.

Suggerisco di utilizzare boost::locale::conv::utf_to_utf con costanti di stringa ampia. per esempio

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()); 

questo farà sì che si dispone di stringa UTF-8, ma ancora una volta non controllare con la console, dal momento che non capiscono UTF-8 a tutti !!.

+0

Ti sbagli. Impostare il font su 'Lucida Console', emettere un' chcp 65001' e vedere che i caratteri UTF-8 appaiono correttamente (solo il segno di ordine dei byte appare come un rettangolo vuoto). L'ho provato di nuovo in questo momento. Questi passaggi sono coperti nella domanda. – Notinlist

+0

Proverò questa funzione di boost più tardi a casa. Grazie per questo suggerimento. – Notinlist

+0

Ho fatto quello che dici, imposta il font su 'Lucida Console' e emetto un' chcp 65001' ma mostra solo rettangoli, se puoi vederli è possibile perché i caratteri che hai usato nel tuo file UNICODE provengono tutti da CP_ACP (la tabella codici predefinita del sistema che può essere modificata tramite il pannello di controllo). usa caratteri di altre lingue come il giapponese o qualcosa del genere e vedrai che la console non può mostrarli – BigBoss

2

La linea di comando sembra funzionare un pò con UTF-8 per la mia comprensione

  1. Un font in grado di visualizzare caratteri UTF-8
  2. Impostare il corretto codice pagina nella riga di comando (chcp 65001) non so se questo pagina di codice supporta l'intero caratteri UTF-8, ma sembra essere la migliore disponibile

check it out here e here

[EDIT] in realtà 65001 in realtà è UTF-8 dopo ho controllato 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 

È possibile utilizzare la sua PowerShell molto più potente allora la vecchia cmd.exe

Edit: Informazioni sull'uso cout se noi Stiamo parlando in Visual Studio la risposta corretta è here una spiegazione più spericolata può essere trovata here sulle migliori pratiche all'interno di Visual Studio

+0

Grazie per avermi supportato in questo argomento secondario, ma la domanda principale riguarda usando 'cout' per visualizzare le sequenze UTF-8. – Notinlist

+0

In realtà la domanda è anche correlata a Visual Studio quindi ho aggiornato la mia risposta per includere l'argomento, in visual studio dovresti includere windows.h e definire la macro del preprocessore UNICODE e usare la macro L per dichiarare le stringhe statiche, viene spiegato nell'ultimo collegamento che ho ora fornito nel mio Awnser, – forcewill

+0

Qualcosa si muove, ma non è ancora liscia. Riprenderò ad esso domani. – Notinlist

Problemi correlati