wstring vs string - kurze Nachfrage



  • Eisflamme schrieb:

    Lesen der Qt Dokumentation bedeutet auch, den "siehe auch" Links zu folgen!

    Genau, ich lese die gesamte QT Dokumentation durch und folge allen "siehe auch"-Links. Sorry, aber wenn Du weißt, was ich Deiner Meinung nach nachschlagen soll, dann sag es doch einfach statt einen minder sinnvollen Hinweis wie "Les die QT Dokumentation" zu geben... nett gemeint, danke, aber war für mich nicht hilfreich.

    War nur nicht hilfreich, weil du nicht fähig/willens(/...?) bist Dokumentation zu lesen.
    Ich meine hallo, wenn da steht "alles was QTextCodec::codecForCStrings() nicht konvertieren kann" (sinngemäss), dann ist logischerweise die nächste Frage "na was kann denn QTextCodec::codecForCStrings()?".
    Dann guckst du nach, siehst dass man da was umstellen kann und *schwupps* hättest du zum ersten mal nicht-trivialen Gebrauch einer Doku gemacht.

    Natürlich kannst du stattdessen auch alle Leute anpflaumen die dir nahelegen mal in der Doku nachzusehen. Dauert länger und du lernst nix dabei, aber naja ... ist deine Entscheidung.



  • hättest du zum ersten mal nicht-trivialen Gebrauch einer Doku gemacht.

    Na ja, wenn Du mir einfach Dinge unterstellst, kann ich Deine Kritik an meiner Kritik einer Antwort (was hier im Forum aber sowieso - sinnloserweise - kategorisch ein No-Go ist) nicht ernst nehmen, auch wenn da wahre Punkte dran sind.

    Zum Thema:
    Was ist an

    std::basic_string<wchar32_t> bzw. std::u32string

    korrekter? wstring ist meinem Verständnis nach die UTF-16-Enkodierung für Unicode, die valide und keineswegs inkorrekt ist. wchar32_t oder u32string zu verwenden nutzt immer noch nicht UTF-8 aus. Solange UTF-16 meine Sonderzeichen beinhaltet, erscheint mir das nach wie vor als einfachste (und gleichzeitig speicherschonenste) Variante meine Problemstellung zu lösen. Die optimale Lösung scheint es ja tatsächlich nicht zu geben.

    Auch ein Projekt, auf das in dem Artikel ( http://www.joelonsoftware.com/articles/Unicode.html ) verwiesen wird, fällt die Entscheidung auf UTF-16. Bestätigt doch, dass das valide ist, oder?



  • Eisflamme schrieb:

    wstring ist meinem Verständnis nach die UTF-16-Enkodierung für Unicode, ...

    Nein (s. mein erstes Posting in diesem Thread) - man kann wstring so 'missbrauchen', wenn man es darauf anlegt, aber so ist std::wstring nicht gemeint.

    .. vielleicht melde ich mich später noch mal.

    Gruß
    Werner



  • Echt? Dann hat mich der Artikel irregeführt:

    For the latest version of CityDesk, the web site management software published by my company, we decided to do everything internally in UCS-2 (two byte) Unicode, which is what Visual Basic, COM, and Windows NT/2000/XP use as their native string type. In C++ code we just declare strings as wchar_t ("wide char") instead of char and use the wcs functions instead of the str functions (for example wcscat and wcslen instead of strcat and strlen). To create a literal UCS-2 string in C code you just put an L before it as so: L"Hello".

    Hier wird das Problem nicht angesprochen. Dann muss ich wohl noch mehr Artikel lesen... Deinen Post auf S.1 habe ich auch nochmal gelesen. Das Problem ist, dass die jeweilige locale nicht 16 Bit enthalten muss (sondern weniger kann) oder wie?



  • Dieses UCS-2 ist mittlerweile veraltet. Der Artikel von Joel hat ein paar subtile Fehler, lies lieber http://www.utf8everywhere.org/.

    Werner Salomons Aussage ist, dass ein String kein Encoding enthalten sollte, sondern direkt die Codepoints speichern soll. Das ist so richtig, heisst aber in letzter Instanz Unicode <=> u32string und kein Unicode (z.B. das von Werner empfohlene Big5) <=> u16string. Mit wstring fangen die Probleme schon damit an, dass wchar_t signed sein kann und nicht klar ist, wie viel Bits mindestens aufgenommen werden können.



  • Hi,

    okay, habe "utf8everywhere" jetzt auch komplett gelesen.

    Der Autor empfiehlt ja einfach std::string zu nutzen und anzunehmen, dass einfach jeder UTF8 verwendet. Okay. Aber splits usw. werden dann doch außerordentlich gefährlich, wie bereits angemerkt, oder? Denn wenn char hinterlegt wird, entspricht ja jedes Zeichen einem 32-Bitter. Iterieren und []-Operator sollten dann doch wohl nicht funktionieren.

    Wieso löst u32string das Problem nicht? utf8everywhere sagt ja, dass die C++-Unicode-Implementierung Murks ist (also wohl auch u32string) und der Artikel wurde 2013 zuletzt überarbeitet.



  • std::string ist fuer den Umgang mit Unicode/UTF-8 ungeeignet, du wirst wohl auf eine Library zurueckgreifen muessen.

    Aber es gibt Hoffnung. Immerhin hat das Kommittee erkannt, dass ein Stringtyp, der Encoding nicht beruecksichtigt, ziemlich nutzlos ist, und es gibt sogar schon einen Proposal, der hoffentlich bis C++14 akzeptiert sein wird. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3572.html



  • Eisflamme schrieb:

    Hi,

    okay, habe "utf8everywhere" jetzt auch komplett gelesen.

    Der Autor empfiehlt ja einfach std::string zu nutzen und anzunehmen, dass einfach jeder UTF8 verwendet. Okay. Aber splits usw. werden dann doch außerordentlich gefährlich, wie bereits angemerkt, oder? Denn wenn char hinterlegt wird, entspricht ja jedes Zeichen einem 32-Bitter. Iterieren und []-Operator sollten dann doch wohl nicht funktionieren.

    Wieso löst u32string das Problem nicht? utf8everywhere sagt ja, dass die C++-Unicode-Implementierung Murks ist (also wohl auch u32string) und der Artikel wurde 2013 zuletzt überarbeitet.

    Kannst du ein konkretes Problem nennen das du mit UTF-8 hast und nicht nur theoretische Probleme, die unter diesen und jenen Umständen auftreten können?



  • Mein Ausgangsproblem war ja, dass ich EUR- und Pfundzeichen nicht habe. Die Lösung wstring zu verwenden wurde mir aber jetzt mehr als madig geredet (siehe letzten Seiten des Threads). Die Begründungen gegen wstring sind auf utf8everywhere ja erläutert.



  • Wenn ich dich richtig verstanden habe, hast Du lediglich ASCII und einige gängige Währungssymbole.
    Wenn Du das garantieren kannst, hast Du mit UTF-16 alles was Du brauchst. Alles befindet sich in der BMP und es können keine Surrogate in deinem Text auftauchen, d.h. jedes Zeichen ist in genau einem 16-Bit-Wert kodiert. (Entspricht dann UCS-2)



  • Okay. Aber da wstring das ja nicht anbietet, wie realisiere ich das dann gescheit?



  • Was bietet wstring nicht an?



  • UTF-16 wie auf den vorherigen Seiten diskutiert.



  • QString gibt dir auf Anfrage einen wstring in UTF-16 oder UCS-4, je nach Plattform. In beiden Fällen wird unter den o.g. Voraussetzungen jedes Zeichen in einem wchar_t abgebildet.

    • QString::toStdWString()
      Wenn Du willst kannst Du auch ein Array von unsigned short bekommen.
    • QString::utf16()


  • Eisflamme schrieb:

    hättest du zum ersten mal nicht-trivialen Gebrauch einer Doku gemacht.

    Na ja, wenn Du mir einfach Dinge unterstellst, kann ich Deine Kritik an meiner Kritik einer Antwort (was hier im Forum aber sowieso - sinnloserweise - kategorisch ein No-Go ist) nicht ernst nehmen, auch wenn da wahre Punkte dran sind.

    Denk mal drüber nach was du da schreibst geschrieben hast. Macht nämlich keinen Sinn.

    Und lies dir nochmal diese Aussage von dir durch:

    Genau, ich lese die gesamte QT Dokumentation durch und folge allen "siehe auch"-Links.

    Niemand hat von dir verlangt allen "siehe auch"-Links zu folgen.



  • Niemand hat von dir verlangt allen "siehe auch"-Links zu folgen.

    Damit wollte ich sagen: Präzisier den Hinweis bitte, sonst kannst Du ihn Dir auch sparen. "Lies die Doku" ist ein so allgemeiner Ratschlag, dass man ihn sich einfach sparen kann. Und ja, natürlich hätte ich toStdString() noch genauer durchlesen können, wenn ich mich besonders für QT interessiert hätte - im Fokus steht aber (siehe Threadtitel) die Variante ohne QT, dafür mit Standard.

    Macht nämlich keinen Sinn.

    Du unterstellst mir indirekt, ich hätte vorher noch nie nicht-trivialen Gebrauch von einer Doku gemacht. Oder bestreitest Du das?



  • Hallo Eisflamme und alle interessierten,

    ich denke man muss hier zwischen zwei Dingen ganz klar unterscheiden.

    Da ist zu einem mal das Coding von Zeichen, d.h. die Festlegung welche Zahl (oder Wert oder Code oder Codepoint) für welches Zeichen steht. Zum Beispiel die Zahl 65 (Hex: 0x41) steht für das große 'A' - das ist sowohl ASCII als auch Unicode. Diese Festlegung (65 := 'A') ist zunächst mal ziemlich unabhängig davon in welchem C++-Typ dieses Zeichen untergebracht wird und wie viel Speicherplatz er benötigt. Im Grunde legt der Unicode fest, was überhaupt ein Zeichen ist - das kann in einigen Fällen sehr knifflig werden (z.B.: toupper("Maße")); aber das ist hier gar nicht das Thema.

    Wenn da steht:

    std::string hello = "Hallo Welt!";
    

    so wird das im Allgemeinen immer (auch) Unicode sein. Alle von mir hier verwendeten Zeichen sind Unicode-Zeichen mit Werten <=0x7f. Somit kann sowohl ein std::string und erst recht ein std::wstring mit sizeof(wchar_t)==2 Texte mit Unicode-Zeichen enthalten - ohne jedes Encoding.

    Zum anderen geht es darum, auf welche Weise viele Zeichen (letztlich Texte, Dateien, Emails, usw. ) in Medien transportiert werden, wo die Byte-Größe beschränkt ist. Ich sage ganz bewusst 'Byte' und nicht 'Zeichen'. Das Euro-Zeichen hat den Unicode 8364 (Hex: 20AC) und das passt nun mal nicht in ein Byte von 8Bit - also braucht man mehr als eines. UTF-8 wäre eine Lösung; hier wird das Unicode-'€' als eine Folge von drei Byte dargestellt (0xE2 0x82 0xAC).
    Mag sein, das UTF-8&Co im Kontext und für Unicode entwickelt wurde. Aber es handelt sich um nichts anderes als eine Vorschrift eine Zahl im Bereich von 0 bis 0xFFFFFFFF in eine Bytefolge zu verpacken. Was diese Zahl dann bedeutet oder nicht ist davon zunächst mal völlig unabhängig.

    Ein std::basic_string<> - egal ob mit char oder wchar_t als Element-Typ - ist dafür gemacht, Zeichen zu enthalten, und keine Byte-Kopie einer Datei oder den Auswurf einer Socket-Schnittstelle.

    Nun ist es aber so, dass UTf-8/16 so designend ist, dass eine Folge von char, bei denen jedes <=0x7f ist, gleichzeitig Unicode und gültiges UTF-8 sei kann. Das gleiche gilt für eine String aus wchar_t mit sizeof(wchar_t)==2 mit Zeichen deren Code <=0x7fff; es kann gleichzeitig Unicode und gültiges UTF-16 sein kann. Das ist zum einen sehr praktisch, da die Information ob und welches Encoding vorliegt, i.a. außerhalb der Bytemenge (nicht!?) definiert ist (siehe aber BOM) und liest man es falsch, kommt trotzdem oft lesbarer Text heraus - ein paar Umlaute, die falsch dargestellt werden, stören nicht wirklich.
    Zum anderen wird beides aber auch oft verwechselt und in einen Topf geworfen.

    Das ist meines Erachtens auch der Grund warum QString::toStdWString folgendes tut: "The std::wstring is encoded in utf16 on platforms where wchar_t is 2 bytes wide" - in der Praxis ist das (meistens!) eh' das gleiche wie reiner Unicode da selbst chinesische Zeichen zum großen Teil im Bereich <=0x7fff liegen. Auf der anderen Seite geht aber keine Information verloren, wenn man wirklich Wert auf das 'letzte' Zeichen legt. Soll halt der Anwender damit klar kommen.

    Der Artikel http://www.utf8everywhere.org/ und insbesondere der Vorschlag http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3572.html unterscheiden nur wenig oder gar nicht.
    Was das Proposal ignoriert ist die Tatsache, dass der C++-Standard schon sehr genau zwischen externen Bytes (oder Words) und internen Zeichen unterscheidet. C++ tut dies in der Facette std::codecvt und in C++11 sind konkrete Derivate definiert, die die ganze UTF-Familie abdecken (z.B.: http://www.cplusplus.com/reference/codecvt/codecvt_utf8).
    Irritierender Weise erwähnt das Proposal das mit keinem Wort.

    Um auf das Problem von Eisflamme zurück zu kommen. Gäbe es die Möglichkeit, gänzlich auf String-Typen zu verzichten? Fange die Zeichen (meinetwegen als Typ wchar_t) da ab wo sie als Input anstehen und parse an einer std::basic_streambuf-Schnittstelle.
    Was wird denn eigentlich eingelesen? Also von welchem Typ sind die Objekte nach(!) den Parsen - sind dann noch Texte im Spiel?
    Gib' doch mal ein Beispiel.

    Gruß
    Werner



  • Hi,

    danke für diese sehr konstruktive und zum Thema gehörige Antwort. 🙂

    Also der Input kommt aus der Zwischenablage, die ich über QT verwende. Somit liegt der Input als QString vor. Wie QString aufgebaut ist, weiß ich nicht, daher weiß ich auch nicht, ob dort wirkliche Zeichen enthalten sind oder nur die Repräsentation in Bytes.

    Reales Beispiel würde wieder >200 Zeilen Erklärung benötigen. Nach dem Parsen steht eine listenartige Struktur aus, die hauptsächlich Zahlen und enums enthält. Es gibt dann noch ein paar Strings, aber deren Zeichen sind alle vom int-Wert <128, also unproblematisch. Erwähnenswerte könnte noch sein, dass Teile des Textes mit Gleichheit auf konstante Strings überprüft werden. Man muss also nach bestimmten konstanten Wörtern im Text suchen können oder diese auch ersetzen.

    Hilft das an Details weiter? Ich kann das gerade schlecht einschätzen, weil ich noch nicht weiß, worauf Du hinauswillst. 🙂

    Beste Grüße und danke!



  • an der Altlast wstring wird die Realität noch lange zu knappern haben
    Insbesondere gilt dies für Projekte welche in der Steinzeit mal meinten das sie alles oder primär genau so machen müssen wie Platformen die wstring (16bit) bevorzugt zur Textdarstellung verwenden.

    Qt, zum Beispiel und weil es im original Post erwähnt wurde, beginnt sich jedoch schon auf die Realität einzustellen.

    http://qt-project.org/forums/viewthread/17617

    http://www.macieira.org/blog/2012/05/source-code-must-be-utf-8-and-qstring-wants-it/



  • Eisflamme schrieb:

    Somit liegt der Input als QString vor. Wie QString aufgebaut ist, weiß ich nicht, daher weiß ich auch nicht, ob dort wirkliche Zeichen enthalten sind oder nur die Repräsentation in Bytes.

    RTFM

    Detailed Description

    The QString class provides a Unicode character string.

    QString stores a string of 16-bit QChars, where each QChar corresponds one Unicode 4.0 character. (Unicode characters with code values above 65535 are stored using surrogate pairs, i.e., two consecutive QChars.)


Anmelden zum Antworten