Unicode und std::*string



  • Ich weiß, das wurde schoneinmal diskutiert. Aber trotzdem sind die beiden (per Suchfunktion) gefundenen Threads für mich nicht wirklich zufriedenstellend.
    Ich bin gerade dabei, ein Karaoke-Programm zu entwerfen. Die Darstellung, das Dateiformat (XML) und die Klassenorganisation sind (bisher) kein Problem, aber wie ich den Text intern speichere bereitet mir Kopfschmerzen. Zuerst dachte ich an UTF-16 mit std::wstring, musste aber feststellen, dass
    1. MingWs C++-Lib keine Unterstützung für wstring hat 😞
    2. wstring sowieso unpraktikabel für UTF-16 ist

    Da ich trotzdem gerne alle Unicode-Zeichen darstellen würde (wenigstens intern, die meisten Fonts werden sowieso nicht alle anzeigen können) und Speicherplatz bei relativ kurzen Songtexten wohl kein Problem ist, dachte ich als nächstes an UTF-32. Das hat ja meines Wissens IMMER 32-Bit pro Zeichen und ist deswegen einfach abzuzählen. 😃

    Nur kann die normale string-Klasse ja sowas nicht. Was für Strings sollte man denn verwenden, wenn man möglichst unkompliziert damit arbeiten möchte, am besten mit gewohntem Interface von std::string, und trotzdem alle Unicode-Zeichen speichern möchte? Ich möchte für ein paar chinesische Zeichen keine Verrenkungen machen, weil sie manchmal 2 oder 4 Bytes brauchen, während andere nur 1 Byte brauchen. Und ich möchte möglichst keine nicht-Standard-Bibliotheken verwenden.

    Könnte man mit std::basic_string sowas basteln? Oder muss man doch auf fremde Klassen zurückgreifen, die "echten" Unicode unterstützen? 😕
    geloescht



  • versuch mal std::wstring (das ist afaik die Unicode-Version von string, hat also auch das selbe Interface, arbeitet jedoch auf wchar_t)



  • @ CStoll er scheint das nicht haben zu wollen 😉

    geloescht schrieb:

    2. wstring sowieso unpraktikabel für UTF-16 ist

    @geloescht
    Man kann basic_string anpassen, dafür müsstest du std::char_traits für einen unsigned 32-Bit Typen ( uint32_t ) anpassen.
    Wenn du ausgaben via streams machen möchtest oder mit streams arbeiten möchtest musst du diese dann auch anpassen.



  • CStoll schrieb:

    versuch mal std::wstring (das ist afaik die Unicode-Version von string, hat also auch das selbe Interface, arbeitet jedoch auf wchar_t)

    Ist kein echtes Unicode, leider. Deshalb haben wxWidgets, GTKmm, MFC, Qt usw. alle eine eigene String-Klasse die sich um Unicode kümmert.

    wstring reicht einfach nur dafür, um wchar zu speichern, mehr auch nicht. Aber besser als nichts. 😉



  • Streams brauche ich nicht direkt, da das ganze ersteinmal ein Klassenpaket für die Speicherung und Berechnung von Karaoke-Daten werden soll. Die Darstellung (über SDL) soll davon entkoppelt sein.
    Leider weiß ich nicht, wie man char_traits benützt, aber ich google gerade ien bisschen rum. Auf deutsch scheint es wenig zu geben, aber ich suche auch mal in den englischen Seiten.
    geloescht

    EDIT: Für das einlesen brauche ich vielleicht doch Streams... Je nachdem, wie ich das mit dem einlesen von den XML-Dateien mache. libxml2 unterstützt doch Zeichensatzkonvertierung mit iconv, oder?



  • Soweit ich weis kann iconv Zeichensätze konvertieren. Ob libxml2 das verwendet weis ich nicht.

    char_traits müsstest du selber implementieren. Das enthält die nötige Basisfunktionalität von Strings je nach typ musst es halt anpassen. Bzw kopieren wenn man das so verwenden kann wie es für char oder wchar_t vorgesehen ist.



  • streams brauche ich nicht, libxml2 hat alles was ich brauche. kann man für UCS-4 einfach typedef myString basic_string<uint32_t> machen? falls dem so ist, wäre für mich persönlcih alles geklärt. 🙂
    geloeschr



  • du baust dir einfach nen std::basic_string<int,UTF32Traits> string;
    die UTF32Traits musste noch selbst zusammenbasteln(have fun). bei utf32 hat string keine probleme, da jedes zeichen gleich viel speicehr belegt...



  • Dass UTF-32 immer gleich viel Speicher belegt habe ich ja schon geschrieben. UCS-4 sollte ja gleich sein. Bloß wie ich so ein Traits baue weiß ich nicht.
    geloescht





  • Das ist zwar schön und gut, aber ich verstehe trotzdem ncith wies geht. Im Internet finde ich nirgends eine wirkliche Beschreibung, immer nur, wie CHaracter Traits aufgebaut sind, nicht wie man sie programmiert. Ich denke mir, dass das nicht allzu kompliziert ist, aber ich habe trotzdem keine Ahnung.
    Das fängt schon hier an:

    Int type
    X::int_type
    A type that is capable of representing every valid value of type char_type, and, additionally an end-of-file value. For char, for example, the int type may be int, and for wchar_t it may be wint_t.

    Was brauche ich hier für uint32_t (ist dieser name eigentlichtlich standard? ich lese das immer wieder und habe es so übernommen) Vielleicht ein long? Oder gibt es im Unicodestandard vielleicht schon ein EOF? Ich habe ein Zeichen namens "end" gefunden. Welchen Wert hat EOF überhaupt in der Regel?
    Gibts denn da nirgends eine Schritt-für-Schritt Erklärung?
    geloescht

    EDIT und PS: Ich habe eine Seite gefunden, die aufgrund des selben Problems, wie ich habe eine Alternative zu basic_string entwickelt: http://blogs.msdn.com/ryanmy/archive/category/7606.aspx
    Ich ziehe mir das mal rein...



  • Es gibt die Anforderung, dass EOF nicht in char_type darstellbar sein darf, sondern nur in int_type. Ansonsten sollen die Standard IOStreams wohl stellenweise merkwürdige Ergebnisse liefern (was ansich auch logisch ist).


Anmelden zum Antworten