2010-06-22 23 views
6

Perché i simboli utf8 non possono essere stampati tramite le funzioni di glib?stampa utf8 in glib

Codice sorgente:

#include "glib.h" 
#include <stdio.h> 

int main() { 
    g_print("марко\n"); 
    fprintf(stdout, "марко\n"); 
} 

costruirlo in questo modo:

gcc main.c -o main $(pkg-config glib-2.0 --cflags --libs) 

Si vedeva che glib non può stampare utf8 e fprintf può:

[[email protected] utf8test]$ ./main 
????? 
марко 

risposta

8

Le funzioni di stampa presuppongono che ogni stringa stampata con esse sia codificata correttamente per corrispondere alla codifica corrente del terminale. g_print() non assume che e convertirà la codifica se pensa che sia necessario; ovviamente questa è una cattiva idea, se la codifica fosse effettivamente corretta prima, dal momento che molto probabilmente distruggerà la codifica. Qual è l'impostazione locale del tuo terminale?

È possibile impostare la locale corretta in base alle variabili di ambiente sulla maggior parte dei sistemi oppure è possibile farlo in modo programmatico utilizzando la funzione setlocale. I nomi di locale dipendono dal sistema (non fa parte dello standard POSIX), ma sulla maggior parte dei sistemi di seguito funzioneranno:

#include <locale.h> 

: 

setlocale(LC_ALL, "en_US.utf8"); 

Invece di LC_ALL si possono anche impostare solo il locale per alcune operazioni (ad esempio, "en_US" volontà causa la formattazione di numeri e date in inglese, ma forse non vuoi che i numeri/le date siano formattati in quel modo). Per citare dalla pagina man setlocale:

LC_ALL Impostare genericamente l'intera locale .

LC_COLLATE Impostare una locale per le routine di confronto delle stringhe . Controlla l'ordinamento alfabetico in strcoll() e strxfrm().

LC_CTYPE Impostare una locale per le funzioni tipo ctype (3) e multibyte (3). Controlla il riconoscimento di maiuscolo e minuscolo, alfabetico o non alfabetico caratteri e così via.

LC_MESSAGES Impostare una locale per i cataloghi del messaggio , vedere la funzione catopen (3).

LC_MONETARY Impostare una locale per formattazione dei valori monetari; questo influenza la funzione localeconv().

LC_NUMERIC Impostare una locale per i numeri di formattazione . Controlla la formattazione dei punti decimali in input e output di numeri in virgola mobile nelle funzioni come printf() e scanf(), come oltre ai valori restituiti da localeconv().

LC_TIME Impostare una locale per per la formattazione delle date e delle ore utilizzando la funzione strftime().

Gli unici due valori di locale che sono sempre disponibili su tutti i sistemi sono "C", "POSIX" e "".

Solo tre zone sono definiti per default: stringa vuota "" (che denota l'ambiente nativo) e "C" e "locali" (POSIX che denotano l'ambiente linguaggio C). Un argomento locale di NULL fa sì che setlocale() restituisca le impostazioni locali correnti. Per impostazione predefinita, i programmi C iniziano nella locale "C". La funzione nella libreria che imposta le impostazioni internazionali è setlocale(); la locale non è mai cambiata come effetto laterale di qualche altra routine.

+0

Dopo setlocale (LC_ALL, "en_US.UTF-8") tutto funziona, ma senza di esso e con LANG = en_US.UTF-8 ./main non funziona. Perchè è questo? L'impostazione predefinita del sistema è en_US.UTF-8. –

+0

Non devi esportare la variabile per essere visibile al processo secondario? Anche le variabili sono nominate come mostrato nella pagina man, prova 'export LC_ALL = en_US.utf8 &&./Main'; forse è anche sufficiente impostare LC_CTYPE solo per la stampa su stringa. – Mecki

+0

È necessario esportare se si desidera salvare la variabile. Se lo vuoi solo per un'applicazione, è sufficiente metterlo prima del nome del programma. Ad ogni modo, ho esportato per LANG, LC_ALL e LC_CTYPE. Niente. Ancora non funziona. Strano ... –

1

La stringa passata da g_print() a glibc non è necessariamente nella codifica UTF-8 poiché g_print() esegue la conversione del set di caratteri nello specifico charset Ied by the local.

0

Di solito è non consigliato di utilizzare qualsiasi cosa tranne ASCII all'interno di file di testo. Dovresti usare strumenti come gettext per tradurre parole da diverse lingue. Se questo è fuori discussione, dovresti memorizzare la tua stringa in UTF-8 nel tuo codice.

Provare a stampare questo uno (è la rappresentazione esadecimale della stringa):

char hex_marco[]={0xD0, 0xBC, 0xD0, 0xB0, 0xD1, 0x80, 0xD0, 0xBA, 0xD0, 0xBE, 0}; 

Questo funziona per me in printf (non si può provare qui con glib):

#include <stdio.h> 

char hex_marco[]={0xD0, 0xBC, 0xD0, 0xB0, 0xD1, 0x80, 0xD0, 0xBA, 0xD0, 0xBE, 0}; 

int main(void) 
{ 
    printf("%s\n",hex_marco); 
    return 0; 
} 

reindirizzare l'output file e vederlo come UTF-8.

Spero che aiuti.

+0

"marko" nel file * .c era solo per esempio. Non sto usando UTF-8 all'interno del codice sorgente. La risposta giusta era già stata data. Grazie lo stesso! –

1

È necessario inizializzare la codifica delle impostazioni locali chiamando setlocale all'avvio del programma.

setlocale(LC_CTYPE, "") 

Questo viene normalmente effettuata per voi, se si utilizza una funzione di inizializzazione come gtk_init(..) o simili.