2010-06-22 6 views
6

Warum können utf8-Symbole nicht über glib-Funktionen gedruckt werden?Drucken von utf8 in glib

Quellcode:

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

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

es so Körperbau:

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

Sie, dass glib sehen konnte, kann nicht drucken utf8 und fprintf können:

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

Antwort

8

fprint Funktionen gehen davon aus, dass jede Zeichenkette, die Sie mit ihnen drucken, korrekt codiert ist, um der aktuellen Codierung Ihres Terminals zu entsprechen. g_print() geht nicht davon aus und wird die Kodierung konvertieren, wenn es das für notwendig hält; das ist natürlich eine schlechte Idee, wenn die Kodierung vorher korrekt war, da dies höchstwahrscheinlich die Kodierung zerstören wird. Wie lautet die Gebietsschemaeinstellung Ihres Terminals?

Sie können auf den meisten Systemen entweder das richtige Gebietsschema anhand von Umgebungsvariablen festlegen, oder Sie können dies programmatisch mithilfe der Funktion setlocale tun. Die locale Namen sind systemabhängig (nicht Teil des POSIX-Standard), aber auf den meisten Systemen folgendes funktionieren:

#include <locale.h> 

: 

setlocale(LC_ALL, "en_US.utf8"); 

Statt LC_ALL können Sie auch nur gesetzt, das Gebietsschema für bestimmte Operationen (zB „en_US“ werden Ursache für die Formatierung von englischen Zahlen und Datumsangaben, aber vielleicht möchten Sie nicht, dass Zahlen/Datumsangaben auf diese Weise formatiert werden). Um aus der setlocale man-Seite zu zitieren:

LC_ALL Stellen Sie das gesamte Gebietsschema generisch ein.

LC_COLLATE Legt ein Gebietsschema für die Sortierroutine fest. Dies steuert alphabetische Reihenfolge in strcoll() und strxfrm().

LC_CTYPE Legen Sie ein Gebietsschema für die Funktionen ctype (3) und multibyte (3) fest. Dies steuert die Erkennung von Groß- und Kleinbuchstaben, alphabetischen oder nicht-alphabetischen Zeichen, und so weiter.

LC_MESSAGES Ein Gebietsschema für die Nachricht Kataloge festlegen, siehe catopen (3) -Funktion.

LC_MONETARY Ein Gebietsschema für formatieren, das Währungswerte formatiert; Diese betrifft die localeconv() -Funktion.

LC_NUMERIC Legen Sie ein Gebietsschema für Formatierungsnummern fest. Dies steuert die Formatierung von Dezimalpunkten in Eingabe und Ausgabe von Fließkommazahlen in Funktionen wie printf() und scanf(), wie sowie Werte von localeconv() zurückgegeben.

LC_TIME Legen Sie ein Gebietsschema für Formatierung von Datum und Uhrzeit mit der strftime() -Funktion fest.

Die einzigen zwei Gebietsschemawerte, die auf allen Systemen immer verfügbar sind, sind "C", "POSIX" und "". die leere Zeichenkette „“ (die die native Umgebung bezeichnet) und die „C“ und „POSIX“ Schauplätze (die die C-Sprache-Umgebung bezeichnet):

Nur drei Schauplätze sind standardmäßig definiert. Ein Gebietsschema-Argument von NULL verursacht, dass Setlocale() das aktuelle Gebietsschema zurückgibt. Standardmäßig beginnen C-Programme im Gebietsschema "C". Die einzige Funktion in der Bibliothek, die das Gebietsschema festlegt, ist setlocale(); Das Gebietsschema wird nie als eine Seite einer anderen Routine geändert. etwas zu verwenden, um andere als ASCII-Textdateien innerhalb

+0

Nach setlocale (LC_ALL, "en_US.UTF-8") funktioniert alles, aber ohne es und mit LANG = en_US.UTF-8 ./main funktioniert es nicht. Warum ist das? Systemstandard ist en_US.UTF-8. –

+0

Müssen Sie die Variable nicht exportieren, damit sie im Unterprozess sichtbar ist? Auch die Variablen werden wie auf der man-Seite angezeigt, versuchen Sie 'export LC_ALL = en_US.utf8 &&./Main'; vielleicht genügt es auch, LC_CTYPE nur für den Ausdruck von Strings zu setzen. – Mecki

+0

Sie müssen exportieren, wenn Sie eine Variable "speichern" möchten. Wenn Sie es nur für eine Anwendung wünschen, reicht es aus, es vor den Programmnamen zu setzen. Wie auch immer, ich habe Export für LANG, LC_ALL und LC_CTYPE gemacht. Nichts. Funktioniert immer noch nicht. Seltsam ... –

1

Der String übergeben von g_print() zu glibc ist nicht notwendigerweise in der UTF-8-Kodierung, da g_print() die Zeichensatzkonvertierung in den charset-spezifischen Wert umwandelt durch das Gebietsschema.

0

Normalerweise ist es nicht empfohlen. Sie sollten Tools wie gettext verwenden, um Wörter aus verschiedenen Sprachen zu übersetzen. Wenn dies nicht möglich ist, sollten Sie Ihre Zeichenfolge in UTF-8 in Ihrem Code speichern.

Versuchen Sie diesen Druck (es ist die hexadezimale Darstellung Ihres string):

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

Das ist für mich in printf arbeitet (kann hier nicht mit glib testen):

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

die Ausgabe umleiten zu Datei und sehe es als UTF-8.

Ich hoffe, es hilft.

+0

"Marko" in * .c Datei war nur zum Beispiel. Ich verwende nicht UTF-8 im Quellcode. Die richtige Antwort wurde bereits gegeben. Trotzdem danke! –

1

Sie müssen die Codierung des Gebietsschemas durch Aufrufen von setlocale beim Programmstart initialisieren.

setlocale(LC_CTYPE, "") 

Dies wird in der Regel für Sie durchgeführt, wenn Sie einige Initialisierungsfunktion wie gtk_init(..) oder ähnliches verwenden.