[C++] Umgang mit Unicode

Simple Directmedia Layer: Portable Spieleprogrammierung
nufan
Wiki-Moderator
Beiträge: 2446
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [C++] Umgang mit Unicode

Beitrag von nufan » So Okt 28, 2012 3:40 pm

Glocke hat geschrieben:
nufan hat geschrieben:Sehs leider erst jetzt. So hast du eindeutig die 2. Möglichkeit und musst Uint16 verwenden, sonst verlierst du Informationen.
Übrigens hab ich das Thema mal ins SDL-Forum verschoben.
Also meine Eingabe ist UTF-16, also muss ich den Netzwerk-Teil auf UTF-16 umschreiben, oder?
Jop, siehe meine anderen Beiträge in diesem Thread ^^ Ich hab dir die Lösung für dein Problem erklärt, bevor dir das Problem überhaupt bewusst war ^^
Du musst deine Eingabe in einem Array aus Uint16 speichern und dieses Array auch übers Netzwerk schicken. Danach mit der entsprechenden TTF-Funktion für Unicode (siehe mein erster Beitrag) rendern und anzeigen.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: [C++] Umgang mit Unicode

Beitrag von Glocke » So Okt 28, 2012 3:47 pm

nufan hat geschrieben:Jop, siehe meine anderen Beiträge in diesem Thread ^^ Ich hab dir die Lösung für dein Problem erklärt, bevor dir das Problem überhaupt bewusst war ^^
Jup :)
nufan hat geschrieben:Du musst deine Eingabe in einem Array aus Uint16 speichern und dieses Array auch übers Netzwerk schicken. Danach mit der entsprechenden TTF-Funktion für Unicode (siehe mein erster Beitrag) rendern und anzeigen.
Also schreibe ich mir besser eine eigene UTF-16 String-Klasse, lasse meine Eingaben darin laden und bastel mit Methoden dazu, dass ich damit vernünftig arbeiten kann? Ich hoffe ich verstehe dich da richtig :)

nufan
Wiki-Moderator
Beiträge: 2446
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [C++] Umgang mit Unicode

Beitrag von nufan » So Okt 28, 2012 3:49 pm

Glocke hat geschrieben:
nufan hat geschrieben:Du musst deine Eingabe in einem Array aus Uint16 speichern und dieses Array auch übers Netzwerk schicken. Danach mit der entsprechenden TTF-Funktion für Unicode (siehe mein erster Beitrag) rendern und anzeigen.
Also schreibe ich mir besser eine eigene UTF-16 String-Klasse, lasse meine Eingaben darin laden und bastel mit Methoden dazu, dass ich damit vernünftig arbeiten kann? Ich hoffe ich verstehe dich da richtig :)
Das wäre eine Möglichkeit... aber siehe meinen Tipp ganz unten ;)
https://www.proggen.org/forum/viewtopic ... =10#p27116

Wenn du dieses typdef verwendest (bzw. von dieser Klasse ableitest), kannst du damit praktisch das gleiche wie mit std::string machen. Und wenn du wirklich das reine Array brauchst (wie zum Beispiel bei den TTF-Funktionen), rufst du einfach die Methode c_str() auf.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: [C++] Umgang mit Unicode

Beitrag von Glocke » So Okt 28, 2012 3:58 pm

Ach base_string ist generisch und ich kann mir (mit dem oben genannten typedef) nen "base string of UTF-16" erzeugen? versteh ich das so richtig?

nufan
Wiki-Moderator
Beiträge: 2446
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [C++] Umgang mit Unicode

Beitrag von nufan » So Okt 28, 2012 4:08 pm

Glocke hat geschrieben:Ach base_string ist generisch und ich kann mir (mit dem oben genannten typedef) nen "base string of UTF-16" erzeugen? versteh ich das so richtig?
Die Klasse base_string ist eine Template-Klasse, die du auf beliebige Typen anwenden kannst.
Siehe hier:
http://www.cplusplus.com/reference/string/string/
Das was du als std::string kennst, ist nichts weiter als die Anwendung des Templates auf den Typ char:

Code: Alles auswählen

 typedef basic_string<char> string; 
Das gleiche kannst du jetzt für Uint16 anstatt char machen. Oder du erstellst dir eine neue Klasse, die du von basic_string<Uint16> ableitest, dann kannst du ihr noch mehr Funktionalitäten geben.

Mit dieser Klasse kannst du dann sowas machen:

Code: Alles auswählen

void Network::send( UnicodeString& message, TCPsocket *socket )
{
  SDLNet_TCP_Send( socket, message.c_str(), sizeof( Uint16 ) * message.size() );
}

UnicodeString Network::receive( TCPsocket *socket )
{
  Uint16 buffer;
  UnicodeString tmp;
  do
  {
    SDLNet_TCP_Recv( socket, &buffer, sizeof( Uint16 ) );
    tmp += buffer;
  } while( buffer != SDLK_UNKNOWN );
  return tmp;
}
Ist doch schon ganz hübsch, oder?
Mit c_str() bekommst du den reinen Array (Uint16 *). size() gibt dir die Anzahl an Elementen zurück, also brauchst du dich um das auch nicht kümmern. Außerdem kannst du weitere Zeichen einfach mit += dranhängen.
Beim rendern sieht das dann einfach so aus:

Code: Alles auswählen

SDL_Surface *surface = TTF_RenderUNICODE_Solid( arial16, message.c_str(), fc.white );
Alles klar? :)

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: [C++] Umgang mit Unicode

Beitrag von Glocke » So Okt 28, 2012 4:13 pm

nufan hat geschrieben:Alles klar? :)
Mehr als das: ein Traum *-* Ich stelle gerade mein ganzes Projekt auf den UTF-16 String um - ich denke ich könnte nichts schlimmeres machen, als unterschiedliche Strings zu benutzen, oder? :D

/EDIT: Ich habe zwei Funktionen im Code fromString<T> und toString, die bisher zum Konvertieren verwendet werden. Die verwenden allerdings ostringstream und ich weiß gerade nicht, wie ich das auf meinen neuen String ummünze :lol:

nufan
Wiki-Moderator
Beiträge: 2446
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [C++] Umgang mit Unicode

Beitrag von nufan » So Okt 28, 2012 4:17 pm

Glocke hat geschrieben:Mehr als das: ein Traum *-*
;)
Glocke hat geschrieben:Ich stelle gerade mein ganzes Projekt auf den UTF-16 String um - ich denke ich könnte nichts schlimmeres machen, als unterschiedliche Strings zu benutzen, oder? :D
Wäre schlecht ^^ Ein std::string besteht aus char-Elementen, die 1 Byte groß sind. UTF-16 hat wie der Name schon sagt 16 Bit, also 2 Byte. Wenn du einem char ein Uint16 zuweist und du im höherwertigem Byte Daten hast, gehen diese einfach verloren.

nufan
Wiki-Moderator
Beiträge: 2446
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [C++] Umgang mit Unicode

Beitrag von nufan » So Okt 28, 2012 4:26 pm

Glocke hat geschrieben:/EDIT: Ich habe zwei Funktionen im Code fromString<T> und toString, die bisher zum Konvertieren verwendet werden. Die verwenden allerdings ostringstream und ich weiß gerade nicht, wie ich das auf meinen neuen String ummünze :lol:
Kannst du mir bitte den Code zeigen? So kann ich mir darunter schwer was vorstellen ^^

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: [C++] Umgang mit Unicode

Beitrag von Glocke » So Okt 28, 2012 4:29 pm

Code: Alles auswählen

template<class T> string toString(const T& t) {
    std::ostringstream stream;
    stream << t;
    return stream.str();
}

template<class T> T fromString(const string& s) {
    std::istringstream stream (s);
    T t;
    stream >> t;
    return t;
}
Wahrscheinlich ist es alles andere als schön :D

nufan
Wiki-Moderator
Beiträge: 2446
Registriert: Sa Jul 05, 2008 3:21 pm

Re: [C++] Umgang mit Unicode

Beitrag von nufan » So Okt 28, 2012 4:48 pm

Das sind Methoden um primitive Typen (int, long, float, ...) in einen std::string zu konvertieren bzw. umgekehrt.
Hier die ganze Liste: http://www.cplusplus.com/reference/iost ... tor%3C%3C/
Aber das sind alles Zahlen, du brauchst zur Darstellung keine Unicode-Zeichen. Du bewegst dich hier im ASCII-Bereich, der in UTF-16 identisch ist. Du kannst also alles einfach in einen std::string umwandeln und dann zeichenweise deinem Unicode-String zuweisen, du verlierst dadurch keine Informationen.

Einfacher wäre es auch eigene Methoden für die Zuweisung zwischen std::string und UnicodeString zu verwenden:

Code: Alles auswählen

class UnicodeString : public basic_string<Uint16>
{
  public:
    static UnicodeString fromString( const std::string& str );
    static std::string toString( const UnicodeString& uStr );
};

UnicodeString UnicodeString::fromString( const std::string& str )
{
  UnicodeString tmp;
  for( int i = 0; i < str.size(); i++ )
    tmp += (Uint16) str[i];
  return tmp;
}

std::string UnicodeString::toString( const UnicodeString& uStr );
{
  std::string str;
  for( int i = 0; i < uStr.size(); i++ )
    str += (char) uStr[i];
  return str;
}
Achtung, ungetestet ^^ Aber das Prinzip sollte klar sein.
Dann kannst du folgende Kovnertierungs-Funktionen definieren:

Code: Alles auswählen

template<class T>
UnicodeString toString(const T& t) 
{
        std::ostringstream stream;
        stream << t;
        return UnicodeString::fromString( stream.str() );
}

template<class T> 
T fromString(const UnicodeString& s) 
{
        std::istringstream stream (UnicodeString::toString( s ));
        T t;
        stream >> t;
        return t;
}
EDIT:
Kleine Korrektur im Code.

Antworten