Почему 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 может:
[marko@marko-work utf8test]$ ./main
?????
марко
Функции 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 (); локаль никогда не меняется как сторона эффект какой-то другой рутины.
Обычно не рекомендуется использовать что-либо кроме 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.
Надеюсь, это поможет.
Строка, переданная из g_print () в glibc, не обязательно в кодировке UTF-8, поскольку g_print () выполняет преобразование набора символов в кодировку, указанную локалью.
Вам необходимо инициализировать кодировку языкового стандарта, вызвав setlocale при запуске вашей программы.
setlocale(LC_CTYPE, "")
Обычно это выполняется за вас, если вы используете какую-либо функцию инициализации, например gtk_init (..)
или аналогичную.