2010-06-22 43 views
6

爲什麼utf8符號不能通過glib函數打印?在glib中打印utf8

的源代碼:

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

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

建立這樣的:

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

你可以看到,油腔滑調不能打印UTF8和fprintf可以:

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

回答

8

fprint函數假定您用它們打印的每個字符串都被正確編碼以匹配終端的當前編碼。 g_print()不會假設它並且會轉換編碼,如果它認爲是必要的;當然這是一個壞主意,如果之前的編碼實際上是正確的,因爲這很可能會破壞編碼。您的終端的區域設置是什麼?

您可以在大多數系統上通過環境變量設置正確的語言環境,也可以使用setlocale函數以編程方式執行語言環境。語言環境的名稱取決於系統(不是POSIX標準的一部分),但在大多數系統下面的工作:

#include <locale.h> 

: 

setlocale(LC_ALL, "en_US.utf8"); 

相反LC_ALL的你也可以只設置指定的工作區域(如「EN_US」將導致英文數字和日期格式,但也許你不希望數字/日期格式化)。要從setlocale手冊頁引用:

LC_ALL一般設置整個語言環境 。

LC_COLLATE設置字符串 排序規則的語言環境。這控制 strcoll()和strxfrm()的字母順序。

LC_CTYPE設置 ctype(3)和多字節(3)函數的語言環境。 這控制了 字符的大寫和小寫,字母或非字母 等的識別。

LC_MESSAGES設置消息 目錄的語言環境,請參閱catopen(3)函數。

LC_MONETARY設置格式化貨幣值的區域設置爲 ;這個 影響localeconv()函數。

LC_NUMERIC爲 格式化數字設置語言環境。這可控制 格式的 輸入和輸出函數 (如printf()和scanf())中的浮點數,如 以及localeconv()返回的值。

LC_TIME使用 strftime()函數爲 格式化日期和時間設置語言環境。

在所有系統上始終可用的唯一兩個區域設置值是「C」,「POSIX」和「」。

只有三個區域設置缺省定義:空字符串「」(其表示天然環境) 和「C」和「POSIX」地點(其表示C語言環境)。 NULL 的區域設置參數會導致setlocale()返回當前語言環境。默認情況下,C程序以「C」語言環境啓動。 僅在設置語言環境的庫中的函數是setlocale();語言環境永遠不會改變爲某個其他例程的效果。

+0

在setlocale(LC_ALL,「en_US.UTF-8」)之後一切正常,但沒有它並且LANG = en_US.UTF-8 ./main,它不起作用。爲什麼是這樣? 系統默認值是en_US.UTF-8。 – 2010-06-22 11:29:40

+0

您是否必須將變量導出到子流程纔可見?此外,變量的名稱如手冊頁所示,請嘗試'export LC_ALL = en_US.utf8 &&。/ main';也許僅爲字符串打印設置LC_CTYPE就足夠了。 – Mecki 2010-06-22 12:08:34

+0

如果您想'保存'變量,則需要導出。如果您只想爲一個應用程序使用它,則只需將其放在程序名稱之前即可。無論如何,我已經完成了LANG,LC_ALL和LC_CTYPE的導出。沒有。仍然不工作。奇怪... – 2010-06-22 13:25:35

1

傳遞的字符串從g_print()到glibc不一定採用UTF-8編碼,因爲g_print()將字符集轉換爲字符集指定由地區設置。

0

通常它是而不是建議在文本文件中使用除ASCII以外的任何內容。您應該使用像gettext這樣的工具來翻譯來自不同語言的單詞。如果這沒有問題,那麼你應該在你的代碼中以UTF-8格式存儲你的字符串。

嘗試打印這一項(這是你的字符串的十六進制表示):

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

這在printf的工作,我(不能與油嘴測試這裏):

#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; 
} 

輸出重定向到文件並將其視爲UTF-8。

希望它有幫助。

+0

* .c文件中的「marko」僅僅是一個例子。我沒有在源代碼中使用UTF-8。已經給出了正確的答案。不管怎樣,謝謝你! – 2010-06-22 11:33:33

1

您需要在程序啓動時通過調用setlocale來初始化語言環境的編碼。

setlocale(LC_CTYPE, "") 

這通常是進行你,如果你使用像gtk_init(..)或類似的一些初始化函數。