[C++0x] Welche Strings soll man denn nun verwenden?



  • Guten Abend liebe Community,

    Ich beschäftige mich gerade ein wenig mit dem Thema der Strings in C++0x, und dabei bin ich ein wenig stutzig geworden. Ich habe mir die Frage gestellt, welche Art von Strings man in seinen Programmen benutzen sollte. Bisher habe ich unwissend immer schwer in Richtung wstring s und wchar_t tendiert, was ja scheinbar eine schlechte Sache ist, weil es nicht genau definiert ist. Java und .NET verwenden bekanntlich für alles UTF-16, bei C++ weiss man es bisher nicht so genau.

    Nun kommen aber im neuen Standard neue String- und Character-Typen dazu. Genannt seien hier einmal die Unicode-Konsorten char16_t und char32_t , sowie u16string und u32string . Da jedoch scheinbar im neuen Standard bewusst auf eine Bereitstellung einer vollständigen Unicode-Collation verzichtet wird, funktionieren die Funktionen der Klassen nicht immer wie erwartet.

    Beispielsweise wird die Member-Funktion length bei u16string die Anzahl der char16_t -Entitäten (was für ein grauenhaftes Wort) im String zurückgeben, was aber nicht der Länge des Strings entsprechen muss (hierfür müsste der Standard definieren, wie die Hersteller die sog. grapheme clusters berechnen können, soweit ich es verstanden habe). Das einzige, was scheinbar gut funktioniert, ist das Einlesen und Schreiben von Unicode mittels Streams und codecvt .

    Zusammengefasst zu meiner Frage: Wenn man die neuen Typen nicht richtig nutzen kann, was bringen sie mir denn innerhalb meines Programms? Gehe ich richtig in der Annahme, dass es sowieso nicht gedacht ist, Unicode programmintern zu verwenden, und dass man wie gewohnt auf normale string s und char s setzen sollte?



  • Ach ja, Unicode mit C++ ist und bleibt eine Krux - jedenfalls in der Theorie, in der Praxis funktioniert das Ganze ja erstaunlich gut. Zusammengesetzte vs Decomposed Characters, vier Normalformen, das Rechts-Nach-Links-Zeug und alleine das Vergleichen von Strings ist ein Wahnsinn. Java und .NET verwenden afaik übrigens UCS-2 (also fix 16 Bit pro Code Point, bei UTF-16 sind's 2 oder 4 Byte).

    Da muss man also pragmatisch rangehen.

    Zu deinen Fragen im letzten Absatz: Man kann ja auch jetzt halbwegs mit std::wstring arbeiten. Klar hat man keine definierten Größen und macht keine Checks auf verquere Chars im String, verzichtet auf Normalformen usw aber trotzdem klappt's ja. In der Regel. Mit den neuen Typen wird sich da imo nicht viel ändern, außer ein wenig anfänglicher Verwirrung.


  • Mod

    Ich sag msl so: Mit UTF-8 kommt auch ein normaler char-String zurecht.



  • SeppJ schrieb:

    Ich sag msl so: Mit UTF-8 kommt auch ein normaler char-String zurecht.

    Sind 256 mögliche Zeichen = früherer ASCII-Standard? Es gab auch mal die Hälfte mit 128 Zeichen und hatte auch gereicht. UTF-8 Sollte für die meisten Dinge voll reichen. Oder man will etwas mit z.B. chinesischem Text oder sogar mehrsprachiges. Dann kann man immer noch weiter nachdenken!



  • SeppJ schrieb:

    Ich sag msl so: Mit UTF-8 kommt auch ein normaler char-String zurecht.

    Aber length()/strlen() für einen String mit Umlauten liefert z.B. die Anzahl der Bytes aber nicht die Anzahl der Zeichen.



  • Verstehe ich so alles nicht! 😮

    char text[20];        // ASCII
    int len;
    strcpy(text,"äöü");   // Text reinsetzen
    len = strlen(text);   // liefert 3 was sonst?
    

    Was soll ich mich mit Unicode etc. herumschlagen, wenn ich es nicht notwendig brauche? 😕 Ist allerdings native C ohne die Stringklasse von C++.
    Reicht meist völlig aus. Es sei denn wir haben hier wieder die nie endende Diskussion C versus C++. 😞



  • // liefert 3 was sonst?

    Es könnte auch etwas vollkommen anderes liefern, da bei UTF8 nunmal ein Zeichen mit einer variablen Anzahl Bytes kodiert wird.
    Wenn text vom Benutzer eingeben wird und dieser chinesische Schriftzeichen verwendet, dürfte etwas anderes dabei herauskommen.


  • Administrator

    berniebutt schrieb:

    Verstehe ich so alles nicht! 😮

    char text[20];        // ASCII
    int len;
    strcpy(text,"äöü");   // Text reinsetzen
    len = strlen(text);   // liefert 3 was sonst?
    

    Was soll ich mich mit Unicode etc. herumschlagen, wenn ich es nicht notwendig brauche?

    Problem ist, dass du hier wahrscheinlich Latin-1 oder Latin-2 verwendest. In UTF-8 wäre der String 6 Bytes lang, weil ä, ö und ü ausserhalb des 7 Bit Bereichs von ASCII sind. Theoretisch wäre es sogar möglich, dass er noch länger wäre, weil man ä, ö und ü auch als a, o und u mit jeweils einem Trema schreiben kann.

    Wieso du dich mit Unicode herumschlagen sollst? Sobald du deine Applikation in die weite Welt hinausbringen willst und Übersetzungen anbieten möchtest, hast du ein riesen Problem, wenn du nicht vorher an Unicode gedacht hast.

    fdfdg schrieb:

    Java und .NET verwenden afaik übrigens UCS-2 (also fix 16 Bit pro Code Point, bei UTF-16 sind's 2 oder 4 Byte).

    .Net verwendet UTF-16, bzw. zum Teil sogar UTF-8.
    http://msdn.microsoft.com/en-us/library/9b1s4yhz.aspx

    Grüssli



  • berniebutt schrieb:

    SeppJ schrieb:

    Ich sag msl so: Mit UTF-8 kommt auch ein normaler char-String zurecht.

    Sind 256 mögliche Zeichen = früherer ASCII-Standard? Es gab auch mal die Hälfte mit 128 Zeichen und hatte auch gereicht. UTF-8 Sollte für die meisten Dinge voll reichen. Oder man will etwas mit z.B. chinesischem Text oder sogar mehrsprachiges. Dann kann man immer noch weiter nachdenken!

    Du denkst UTF-8 == 256 Zeichen, oder? 😮
    Wirf mal einen Blick in die Wiki und ignoriere das Thema nicht.



  • Britney Spears schrieb:

    Du denkst UTF-8 == 256 Zeichen, oder? 😮
    Wirf mal einen Blick in die Wiki und ignoriere das Thema nicht.

    Das Thema sollte man wirklich nicht ignorieren, wenn man mehr vorhat oder seine Applikation weltweit verbreiten möchte!
    Aber für den Hausgebrauch oder einen Anwender im gleichen Srachgebiet? Wozu das Leben unnötig schwer machen 😕
    Ging doch alles und geht noch mit 256 verfügbaren Zeichen (ASCII) mit native C! 😮

    Könnt ihr euch am Thema austoben, meinetwegen.
    daddeldu! :p



  • berniebutt schrieb:

    char text[20];        // ASCII
    

    Eine char-Variable kann zumindest ASCII Codes speichern, da char mindenestens Werte im Bereich 0-127 speichern kann. Ob nun aber ein 'A' wirklich dem Wert 65 (siehe ASCII-Tabelle) entspricht, ist gar nicht festfelegt!

    Was Du in einem char speicherst, ist Dir und dem System überlassen. Der Sprache C++ ist das egal, was das genau ist. Der Quelltext besteht aus Zeichen des "basic source character sets" wobei die Kodierung nicht festgelegt ist:

    The basic source character set consists of 96 characters: the space character, the control characters representing horizontal tab, vertical tab, form feed, and new-line, plus the following 91 graphical characters:

    abcdefghijklmnopqrstuvwxyz
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
    0123456789
    _{}[]#()<>%:;.?*+-/^&|~!=,\"'
    

    Schreibt man im Quelltext beispielsweise 'K' hin, so soll der Compiler dieses Literal durch einen zugehörigen Zahlenwert des sogenannten "excecution character set" ersetzten. Das muss meines Wissens nach nicht ASCII sein und ist eben systemabhängig bzw implementation-defined.

    Mit C++11 bekommen wir aber neue character-Typen und auch neue Literale. So ist beispielsweise u'K' ein Literal vom Typ char16_t und der numerische Wert ergibt sich anhand ISO 10646 (UCS, universal character set). Und ein großes U als Präfix, also U'K' ist ein Literal vom Typ char32_t wobei der numerische Wert der entsprechende Unicode ist.

    Dementsprechend gibt es auch String-Literale, die mit einem kleinen u oder einem großen U anfangen. Ein Stringliteral, was mit einem kleinen u anfängt, entspricht der UTF-16 Kodierung, weil der Compiler aus einem Zeichen auch ein Surrogate-Paar erzeugen darf. Ich schätze, es sind auch 32-bittige \x-Escapesequenzen zugelassen. Zusätzlich gibt es auch UTF-8-Literale, deren Präfix u8 ist. Allerdings gibt es hier keinen extra Zeichentypen; denn es kommt auch ein normales char-Array heraus, welches eine UTF-8 kodierte Version der Zeichenkette enthält. Komischerweise gibt es kein "UTF-8 Zeichenliteral" (was dann äquivalent zu ASCII sein sollte). Ich schätze mal, dass auf einer sehr komischen Plattform 'A' und u8"A"[0] zwei unterschiedliche Werte haben kann, da 'A' ein Wert eines systemspezifisches "excecution character set" ist und u8"A"[0] den Wert 65 haben müsste, weil das das erste Byte der UTF-8-Kodierung des Strings ist. Aber wenn man die 65 haben möchte, kann man natürlich auch einfach 65 hinschreiben oder static_cast<char>(65). 😉

    Ich habe mich nicht allzu intensiv mit Zeichensätzen und Literalen auseinandergesetzt. Vielleicht habe ich auch etwas falsch verstanden oder übersehen. Korrekturen sind willkommen.


Anmelden zum Antworten