[C++] Umgang mit Unicode
[C++] Umgang mit Unicode
Hi,
von meiner SDL-Oberfläche lese ich einen String ein, der Unicode-Zeichen enthält. Diesen will ich per SDL_Net (also via Socket) an die Gegenseite schicken. Da ich mit dem Versenden von Strings bisher Probleme hatte, sende ich zuerst die Länge der Zeichenkette (als unsigned int) und dann jeden char (mit myString[index]) einzeln und lese auf der Gegenseite die entsprechenden Daten und rekonstruiere den String. Allerdings gehen dabei Sonderzeichen wie ß usw. verloren.
Wie gehe ich am besten mit Unicode-Characters um? Im Grunde könnte ich ja den int-Wert des Zeichens schicken und daraus das Zeichen rekonstruieren. Nur weiß ich nicht, wie ich an den Wert komme und wie ich quasi "zurück-caste". Mit normalen char ist das ja kein Problem ^^
Btw verwende ich kein .NET
LG Glocke
von meiner SDL-Oberfläche lese ich einen String ein, der Unicode-Zeichen enthält. Diesen will ich per SDL_Net (also via Socket) an die Gegenseite schicken. Da ich mit dem Versenden von Strings bisher Probleme hatte, sende ich zuerst die Länge der Zeichenkette (als unsigned int) und dann jeden char (mit myString[index]) einzeln und lese auf der Gegenseite die entsprechenden Daten und rekonstruiere den String. Allerdings gehen dabei Sonderzeichen wie ß usw. verloren.
Wie gehe ich am besten mit Unicode-Characters um? Im Grunde könnte ich ja den int-Wert des Zeichens schicken und daraus das Zeichen rekonstruieren. Nur weiß ich nicht, wie ich an den Wert komme und wie ich quasi "zurück-caste". Mit normalen char ist das ja kein Problem ^^
Btw verwende ich kein .NET
LG Glocke
Rage - ein "modernes" Rogue-like (C++11, SFML)
- cloidnerux
- Moderator
- Beiträge: 3125
- Registriert: Fr Sep 26, 2008 4:37 pm
- Wohnort: Ram (Gibts wirklich)
Re: [C++] Umgang mit Unicode
Auch ein Unicode-Zeichen ist nur eine Zahl, die etwas repräsentieren soll. Ein char ist auch eine Zahl, aber eben eine kleinere und ein "char" kann nach ASCII nicht so viele Zeichen einnehmen. Was du also machen musst, ist denn UNICDE-String Zahl für Zahl zu senden und zu wieder zu einem string zusammen bauen.Wie gehe ich am besten mit Unicode-Characters um? Im Grunde könnte ich ja den int-Wert des Zeichens schicken und daraus das Zeichen rekonstruieren. Nur weiß ich nicht, wie ich an den Wert komme und wie ich quasi "zurück-caste". Mit normalen char ist das ja kein Problem ^^
Redundanz macht wiederholen unnötig.
quod erat expectandum
quod erat expectandum
Re: [C++] Umgang mit Unicode
Soweit so gut, aber wie wandel ich meine Zahl (die ein Unicodezeichen repräsentiert) wieder zum Zeichen zurück? Ein cast zu char hilft da ja nicht.
LG Glocke
LG Glocke
Rage - ein "modernes" Rogue-like (C++11, SFML)
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: [C++] Umgang mit Unicode
Bist du sicher, dass das ein Unicode-Problem ist? Wenn deine Oberfläche tatsächlich unicode einliest und die Gegenseite tatsächlich Unicode empfängt, sollte es keine Probleme geben. Ich glaube, es liegt eher daran dass eine der Seiten eine andere Kodierung verwendet. Überprüf mal die einlesefunktionen der SDL bzw. dem was du auf der Gegenseite zum Anzeigen verwendest.Glocke hat geschrieben:von meiner SDL-Oberfläche lese ich einen String ein, der Unicode-Zeichen enthält. Diesen will ich per SDL_Net (also via Socket) an die Gegenseite schicken. Da ich mit dem Versenden von Strings bisher Probleme hatte, sende ich zuerst die Länge der Zeichenkette (als unsigned int) und dann jeden char (mit myString[index]) einzeln und lese auf der Gegenseite die entsprechenden Daten und rekonstruiere den String. Allerdings gehen dabei Sonderzeichen wie ß usw. verloren.
So ganz einfach ist das nicht. Das stimmt für UTF-32-Kodierte Zeichen, wenn sie aber UTF-8/UTF-16 kodiert sind, könnte es passieren dass sie in mehrere bytes aufgespalten werden, so wird schnell aus einem Zeichen 3 (nicht 2! Das unicode steuerzeichen kommt noch dazu.) bzw 5 Bytes.cloidnerux hat geschrieben:Auch ein Unicode-Zeichen ist nur eine Zahl, die etwas repräsentieren soll.
Haters gonna hate, potatoes gonna potate.
- Xin
- nur zu Besuch hier
- Beiträge: 8862
- Registriert: Fr Jul 04, 2008 11:10 pm
- Wohnort: /home/xin
- Kontaktdaten:
Re: [C++] Umgang mit Unicode
Das ist auch nicht nötig, denn eine ASCII-Zeichen ist eine Zahl und ein Unicodezeichen sind eine Reihe von Zahlen.Glocke hat geschrieben:Soweit so gut, aber wie wandel ich meine Zahl (die ein Unicodezeichen repräsentiert) wieder zum Zeichen zurück? Ein cast zu char hilft da ja nicht.
Bitte gib den String mal Zahl für Zahl aus, zum Beispiel so:
Code: Alles auswählen
char const * text = "Hello World";
unsigned int i=0;
while( text[i] )
{
printf( "%d. Zeichen: %d\n", i, text[i] );
i++;
};
Kommen die Zahlen identisch an?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Re: [C++] Umgang mit Unicode
Unicode Zeichen sind in SDL keine chars, sondern Uint16.Glocke hat geschrieben:Soweit so gut, aber wie wandel ich meine Zahl (die ein Unicodezeichen repräsentiert) wieder zum Zeichen zurück? Ein cast zu char hilft da ja nicht.
Einlesen kannst du das grob gesagt so:
Code: Alles auswählen
void readUnicode()
{
SDL_EnableUNICODE( 1 );
SDL_EnableKeyRepeat( 400, 30 );
// ...
while( !done )
{
SDL_WaitEvent( &event );
switch( event.type )
{
case SDL_KEYDOWN:
unkey = event.key.keysym.unicode;
mod = event.key.keysym.mod;
// Gültige Taste und Strg ist nicht gedrückt.
if( unkey != SDLK_UNKNOWN && !(mod & KMOD_CTRL) )
{
if( unkey == SDLK_BACKSPACE )
{
// Letztes Zeichen löschen.
// ...
}
// Enter gedrückt -> Eingabe abbrechen, wenn Zeichen vorhanden sind.
else if( (unkey == SDLK_RETURN || unkey == SDLK_KP_ENTER) )
{
if (i > 0)
done = 1;
}
// Gültiges Zeichen und es wurden weniger als 15 Zeichen eingegeben.
else if( i < 15 && unkey != SDLK_TAB && unkey != SDLK_ESCAPE )
{
// Zeichen an den Unicode-String (Uint16[]) dranhängen und Ausgabe aktualisieren.
// ...
}
}
break;
}
}
SDL_EnableKeyRepeat( 0, 30 );
SDL_EnableUNICODE( 0 );
}
http://www.libsdl.org/projects/SDL_ttf/ ... html#SEC45
Re: [C++] Umgang mit Unicode
@Xin: Also auf beiden Seiten stimmt die Reihenfolge
@fat-lobyte: Das was von der Oberfläche eingelesen wird ist Unicode. Gebe ich den string außerdem mit std::cout aus, erscheinen die korrekten Symbole im Terminal. Auf beiden Seite des Sockets verwende ich SDL_Net - somit sollte die Kodierung die gleiche sein.
@nufan: Das Problem ist das Senden via Socket! Einlesen von der Oberfläche funktioniert.

@fat-lobyte: Das was von der Oberfläche eingelesen wird ist Unicode. Gebe ich den string außerdem mit std::cout aus, erscheinen die korrekten Symbole im Terminal. Auf beiden Seite des Sockets verwende ich SDL_Net - somit sollte die Kodierung die gleiche sein.
@nufan: Das Problem ist das Senden via Socket! Einlesen von der Oberfläche funktioniert.
Rage - ein "modernes" Rogue-like (C++11, SFML)
- Xin
- nur zu Besuch hier
- Beiträge: 8862
- Registriert: Fr Jul 04, 2008 11:10 pm
- Wohnort: /home/xin
- Kontaktdaten:
Re: [C++] Umgang mit Unicode
Okay, Du empfängst also, was Du sendest.Glocke hat geschrieben:@Xin: Also auf beiden Seiten stimmt die Reihenfolge
Heißt, Du kannst das ganze Network-Zeugs als Fehlerquelle ausklammern, Du kannst Dir also überlegen, warum zwei Programme diese Zeichenreihenfolge mal so und mal so interpretieren.
Hast Du beide auf Unicode eingestellt?
Code: Alles auswählen
SDL_EnableUNICODE( 1 );
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: [C++] Umgang mit Unicode
nufan hat geschrieben, dass die eingelesenen Zeichen Uint16 sind, das bedeutet sie sind UTF-16 kodiert.Glocke hat geschrieben:@fat-lobyte: Das was von der Oberfläche eingelesen wird ist Unicode. Gebe ich den string außerdem mit std::cout aus, erscheinen die korrekten Symbole im Terminal. Auf beiden Seite des Sockets verwende ich SDL_Net - somit sollte die Kodierung die gleiche sein.
Wenn du Zeichen mit std::cout ausgibst, wird erwartet, dass die Zeichen UTF-8 kodiert sind. Genau das wird wahrscheinlich das Problem sein.
Du könntest, wenn du auf Windows bist std::wcout verwenden, das verwendet statt char's wchar_t's. wchar_t ist auf Windows 16 Bit groß, auf Linux 32 Bit.
Ansonsten musst du deine Strings irgendwie umkodieren. Dazu kannst du entweder die libicu verwenden, oder wenn du C++11 verwenden kannst, irgendwie mit der String-Konvertierungslibrary: http://en.cppreference.com/w/cpp/string/multibyte
Haters gonna hate, potatoes gonna potate.
Re: [C++] Umgang mit Unicode
Wie eingangs gesagt, weiß ich nicht wie ich die einzelnen Unicode-Chars korrekt sende. Wandle ich jeden char des Strings in einen unsigned int um (um den Zahlenwert zu erhalten), bekomme ich ihn auf der Gegenseite nicht wieder zusammengesetzt, weil ich nicht weiß wie. Wie gesagt: Der cast zum char wäre ja Quatsch.
Und nein, auf beiden Seiten ist SDL-seitig Unicode aktiviert. Btw habe ich zu Testzwecken eine Variable mal direkt mit "asßdf" initialisiert. Dabei gibt es beim ß Probleme. Ich hole zeichenweise mit myString[index] die chars, caste die zum unsigned int und schicke die rüber. Für die Zeichenkette sendet er die Zahlen 97 ("a"), 115 ("s"), 4294967235, 4294967199, 100 ("d") und 102 ("f").
/EDIT: ich schau mir mal http://en.cppreference.com/w/cpp/string/multibyte an
Und nein, auf beiden Seiten ist SDL-seitig Unicode aktiviert. Btw habe ich zu Testzwecken eine Variable mal direkt mit "asßdf" initialisiert. Dabei gibt es beim ß Probleme. Ich hole zeichenweise mit myString[index] die chars, caste die zum unsigned int und schicke die rüber. Für die Zeichenkette sendet er die Zahlen 97 ("a"), 115 ("s"), 4294967235, 4294967199, 100 ("d") und 102 ("f").
/EDIT: ich schau mir mal http://en.cppreference.com/w/cpp/string/multibyte an
Rage - ein "modernes" Rogue-like (C++11, SFML)