为什么无法通过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)
你可以看到glib无法打印utf8和fprintf可以:
[marko@marko-work utf8test]$ ./main
?????
марко
答案 0 :(得分: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(),as 以及localeconv()返回的值。
LC_TIME为其设置区域设置 使用。格式化日期和时间 strftime()函数。
所有系统上始终可用的唯一两个区域设置值是“C”,“POSIX”和“”。
默认情况下只定义了三个语言环境:空字符串“”(表示本机环境) 以及“C”和“POSIX”语言环境(表示C语言环境)。 locale参数为NULL 导致setlocale()返回当前的语言环境。默认情况下,C程序以“C”语言环境开始。该 只有在设置语言环境的库中的函数才是setlocale();区域设置永远不会改变 其他一些常规的效果。
答案 1 :(得分:1)
从g_print()传递给glibc的字符串不一定是UTF-8编码,因为g_print()会将字符集转换为语言环境指定的字符集。
答案 2 :(得分:1)
您需要在程序开始时调用setlocale来初始化语言环境的编码。
setlocale(LC_CTYPE, "")
如果您使用gtk_init(..)
或类似的初始化函数,通常会执行此操作。
答案 3 :(得分:0)
通常不建议在文本文件中使用除ASCII之外的任何内容。您应该使用gettext之类的工具来翻译不同语言的单词。如果这是不可能的,那么你应该在你的代码中将你的字符串存储在UTF-8中。
尝试打印这个(它是你的字符串的十六进制表示):
char hex_marco[]={0xD0, 0xBC, 0xD0, 0xB0, 0xD1, 0x80, 0xD0, 0xBA, 0xD0, 0xBE, 0};
这对我在printf中起作用(不能用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;
}
将输出重定向到文件并将其视为UTF-8。
希望它有所帮助。