2011-09-21 9 views
7

Sto provando a stampare una stringa wchar_t *. Codice va sotto:char vs wchar_t

#include <stdio.h> 
#include <string.h> 
#include <wchar.h> 

char *ascii_ = "中日友好"; //line-1 
wchar_t *wchar_ = L"中日友好"; //line-2 

int main() 
{ 
    printf("ascii_: %s\n", ascii_); //line-3 
    wprintf(L"wchar_: %s\n", wchar_); //line-4 
    return 0; 
} 

//Output 
ascii_: 中日友好 

Domanda:

  1. A quanto pare non dovrebbe assegnare i caratteri CJK a char * puntatore nella line-1, ma ho appena fatto, e l'uscita della linea -3 è corretto, quindi perché? Come potrebbe printf() nella riga 3 darmi i caratteri non-ascii? Conosce la codifica in qualche modo?

  2. Presumo che il codice nella riga 2 e la riga 4 siano corretti, ma perché non ho ricevuto alcun output di line-4?

+0

Che compilatore stai utilizzando? Il GCC ha come valore predefinito Utf-8 o la maggior parte delle piattaforme. Sembra un problema di codifica per me. – cyco130

+0

@ cyco130, si, gcc – Alcott

risposta

8

Prima di tutto, di solito non è una buona idea usare caratteri non ASCII nel codice sorgente. Quello che probabilmente sta succedendo è che i caratteri cinesi vengono codificati come UTF-8 che funziona con ASCII.

Ora, come per il motivo che il wprintf() non funziona. Questo ha a che fare con l'orientamento del flusso. Ogni stream può essere impostato su normale o ampio. Una volta impostato, non può essere modificato. È impostato la prima volta che viene utilizzato. (che è ascii a causa di printf). Successivamente, lo wprintf non funzionerà a causa dell'orientamento errato.

In altre parole, una volta utilizzato printf() è necessario continuare a utilizzare printf(). Allo stesso modo, se si inizia con wprintf(), è necessario continuare a utilizzare wprintf().

Non è possibile mescolare printf() e wprintf(). (Eccetto Windows)

EDIT:

di rispondere alla domanda sul perché la linea wprintf non funziona anche da solo. Probabilmente è perché il codice viene compilato in modo che il formato UTF-8 di 中日友好 sia memorizzato in wchar_. Tuttavia, wchar_t richiede la codifica unicode a 4 byte. (2-byte in Windows)

Quindi ci sono due opzioni che mi viene in mente:

  1. Non perdete tempo con wchar_t, e solo bastone con multi-byte char s. Questo è il modo semplice, ma potrebbe interrompersi se il sistema dell'utente non è impostato sulle impostazioni internazionali cinesi.
  2. Utilizzare wchar_t, ma è necessario codificare i caratteri cinesi utilizzando sequenze di escape unicode. Questo ovviamente lo renderà illeggibile nel codice sorgente, ma funzionerà su qualsiasi macchina in grado di stampare caratteri di caratteri cinesi indipendentemente dalle impostazioni locali.
+0

se usa unicode escape seq, devo trovare ogni seq di parola cinese, giusto? Ci vorrà un bel po 'di lavoro: P – Alcott

+1

corretto. Tuttavia, sono sicuro che questo è abbastanza comune dove puoi trovare uno strumento online che puoi semplicemente copiare e incollare il testo cinese e ti darà la sequenza di escape unicode. E per mantenere leggibile il codice, puoi mantenere il testo cinese effettivo accanto alla sequenza di escape come commento. – Mysticial

+0

grazie Mysticial – Alcott

6

La riga 1 non è ascii, è qualunque sia la codifica multibyte utilizzata dal compilatore in fase di compilazione. Sui sistemi moderni è probabilmente UTF-8. printf non conosce la codifica. Sta solo inviando byte allo stdout, e finché le codifiche corrispondono, va tutto bene.

Un problema da tenere presente è che le linee 3 e 4 invocano insieme un comportamento non definito. Non è possibile combinare io basato su caratteri e caratteri wide sullo stesso FILE (stdout).Dopo la prima operazione, il FILE ha un "orientamento" (o byte o ampio), e dopo che qualsiasi tentativo di eseguire operazioni dell'orientamento opposto risulta in UB.

+0

commento il linea printf(), ho avuto qualche output ma non i caratteri cinesi. Perché? – Alcott

+0

Probabilmente la codifica delle impostazioni locali è sbagliata. –

+0

codifica delle impostazioni internazionali? Come sistemarlo? – Alcott

1

Stai omettendo un passaggio e quindi pensi nel modo sbagliato.

Si dispone di un file C su disco, contenente byte. Hai una stringa "ASCII" e una stringa larga.

La stringa ASCII prende i byte esattamente come sono nella riga 1 e li emette. Questo funziona fintanto che la codifica del lato utente è uguale a quella sul lato del programmatore.

La stringa larga prima decodifica i byte dati in codepoint unicode e memorizzati nel programma, forse questo va storto dalla tua parte. All'uscita sono codificati di nuovo secondo la codifica sul lato dell'utente. Ciò garantisce che questi caratteri siano emessi come sono destinati, non al momento dell'immissione.

O il compilatore assume la codifica errata oppure il terminale di uscita è impostato in modo errato.