9

utf8シンボルをglib関数で印刷できないのはなぜですか?

ソースコード:

#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 
?????
марко
4

4 に答える 4

10

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)およびmultibyte(3)関数のロケールを設定します。これは、大文字と小文字、アルファベットまたは非アルファベット文字などの認識を制御します。

LC_MESSAGESメッセージカタログのロケールを設定します。catopen(3)関数を参照してください。

LC_MONETARY金銭的価値をフォーマットするためのロケールを設定します。これはlocaleconv()関数に影響します。

LC_NUMERIC数値をフォーマットするためのロケールを設定します。これは、printf()やscanf()などの関数の浮動小数点数の入力と出力の小数点のフォーマット、およびlocaleconv()によって返される値を制御します。

LC_TIME strftime()関数を使用して、日付と時刻をフォーマットするためのロケールを設定します。

すべてのシステムで常に使用できるロケール値は、「C」、「POSIX」、および「」の2つだけです。

デフォルトでは、空の文字列 ""(ネイティブ環境を表す)と"C"および"POSIX"ロケール(C言語環境を表す)の3つのロケールのみが定義されています。NULLのロケール引数により、setlocale()は現在のロケールを返します。デフォルトでは、Cプログラムは「C」ロケールで起動します。ロケールを設定するライブラリ内の唯一の関数はsetlocale()です。他のルーチンの副作用としてロケールが変更されることはありません。

于 2010-06-22T11:14:20.077 に答える
2

プログラムの開始時にsetlocaleを呼び出して、ロケールのエンコーディングを初期化する必要があります。

setlocale(LC_CTYPE, "")

gtk_init(..)これは通常、または同様の初期化関数を使用する場合に実行されます。

于 2010-06-23T00:36:25.193 に答える
1

g_print()はロケールで指定された文字セットへの文字セット変換を行うため、g_print()からglibcに渡される文字列は必ずしもUTF-8エンコーディングである必要はありません。

于 2010-06-22T11:10:44.967 に答える
0

通常、テキストファイル内でASCII以外のものを使用することはお勧めしません。異なる言語の単語を翻訳するには、gettextなどのツールを使用する必要があります。これが問題外の場合は、コードのUTF-8に文字列を格納する必要があります。

これを印刷してみてください(これは文字列の16進表現です):

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として表示します。

それが役に立てば幸い。

于 2010-06-22T11:16:59.560 に答える