wstring vs string - kurze Nachfrage



  • Hi,

    danke allerseits! Habe den ersten Artikel von theta komplett gelesen. wchar_t ist also UCS-2 = UTF-16. Da das eine Unicode-Art ist, kann man also durchaus sagen, dass C++ einen Teil des Unicodes unterstützt. Bietet irgendeine Bibliothek (boost oder so) denn eine UTF-8-Stringklasse an, auf die man mit [] korrekt zugreifen kann?

    pars0r:
    Eigentlich ist das fast alles nur im Bereich von Bit 0-127. Einzig dazu kommen die Währungszeichen Pfund und Euro.

    Insofern wäre eine eigene Codepage vielleicht gar nicht schlecht. Aber wstring erscheint mir gerade einfacher. Was spricht denn dagegen?



  • Ist richtig. Wo fange ich da am besten an? Gibt es da eine gute Seite, die auch die C++-Implementierung diskutiert?

    http://en.wikipedia.org/wiki/Code_page
    http://en.wikipedia.org/wiki/Utf8
    http://en.wikipedia.org/wiki/UTF-16
    http://en.wikipedia.org/wiki/Unicode
    http://msdn.microsoft.com/en-us/library/windows/desktop/dd317711%28v=vs.85%29.aspx
    http://msdn.microsoft.com/en-us/library/windows/desktop/dd317752%28v=vs.85%29.aspx

    Meine Frage, ob "wstring" seine Existenzberechtigung hat, rührt nämlich daher, dass ich zwar theoretisch weiß, was dahintersteckt, aber im Gedächtnis habe, dass hier vielfach gesagt wurde, dass string eigentlich genau so funktionieren kann (ich weiß nicht mehr wie, vll einfach durch zwei char pro Zeichen im string) und wstring daher unnötig ist.

    Wenn man es streng nimmt, ist dies Blödsinn. Schreibe mal in deinem String: "Schräglage: β = 1.5"

    Natürlich kann man std::string als einen String in einer speziellen Kodierung auffassen. Aber damit unterläuft man die eigentliche Bedeutung von std:string bzw. std::basic_string<char>.



  • Werner Salomon schrieb:

    Lt. Doku wird bei toStdString nach UTF-16 konvertiert

    Du meinst hier sicher toStdWString. Das gilt dann auch nur wenn wchar_t 2 Byte hat. Falls wchar_t 4 Byte hat wird ucs4 verwendet.





  • Eisflamme schrieb:

    pars0r:
    Eigentlich ist das fast alles nur im Bereich von Bit 0-127. Einzig dazu kommen die Währungszeichen Pfund und Euro.

    Insofern wäre eine eigene Codepage vielleicht gar nicht schlecht. Aber wstring erscheint mir gerade einfacher. Was spricht denn dagegen?

    du willst also jedem einzelnen zeichen, das von haus aus in ein byte passt, einen (mindestens) doppelt so großen (wenn nicht gar vierfachen) speicherplatz verschaffen, damit es ihm nicht so eng wird?
    🤡
    mal im ernst, was hättest du davon und was wäre dann einfacher?

    du willst parsen, aber nicht darstellen, richtig?
    wenn du darstellen müsstest, dann müsstest du je nach system die codepage(windows)/kodierung sowieso beachten. unter linux dagegen könntest du alles utf-8 kodiert mit cout raushauen, aber auch unter linux lässt sich die codepage setzen.



  • Ich moecht mich hier gleich mal anschießen und fragen wie man richtig von (windows) wchar_t zu utf-8 konvertiert.

    Ich bin mal ueber diesen Codeschnipsel gestolpert:

    namespace utf8 {
    
    std::string to(const std::wstring& data) {
    	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > c;
    	return c.to_bytes( data );
    }
    std::wstring from(const std::string& data) {
    	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > c;
    	return c.from_bytes( data);
    }
    
    }
    

    Ist das richtig soweit oder sollte man da was anderes benutzten?
    Gruessle



  • pars0r:
    Speicherplatz ist egal, die zu parsenden Teile sind nicht groß.

    Was ich davon hätte? Ich kann das Ding wie einen ganz normalen string nutzen. Bisher habe ich keinen Vorschlag gesehen, der einfacher wäre.



  • alles im qstring lassen?
    😕



  • Der Parser liegt im Backend, QT ist bei mir ausschließlich Frontend. Das Backend soll auch ohne QT funktionieren.



  • Eisflamme schrieb:

    Was ich davon hätte? Ich kann das Ding wie einen ganz normalen string nutzen. Bisher habe ich keinen Vorschlag gesehen, der einfacher wäre.

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



  • ...

    Und was ist daran einfacher?



  • Eisflamme schrieb:

    Und was ist daran einfacher? -.-

    Es ist genauso einfach, aber dafür korrekt.



  • stuxn schrieb:

    Ich moecht mich hier gleich mal anschießen und fragen wie man richtig von (windows) wchar_t zu utf-8 konvertiert.

    Unter Windows kann man (auch) die WinAPI dafür nehmen:

    #include <windows.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    wstring toWide(string in, UINT from)
    {
       int len = MultiByteToWideChar(from, 0, in.c_str(), -1, 0, 0);
    
       if(!len)
          cout << "Fehler toWide?!\n";
    
       WCHAR *res = new WCHAR[len];
    
       int result = MultiByteToWideChar(from, 0, in.c_str(), -1, res, len);
    
       if(result != len)
          cout << "Fehler toWide?!\n";
    
       wstring s(res);
    
       delete[] res;
    
       return s;
    }
    
    string toMultiByte(wstring in, UINT to)
    {
       const int len = WideCharToMultiByte(to, 0, in.c_str(), -1, 0, 0, 0, 0);
    
       if(!len)
          cout << "Fehler toMBCS 1?!\n";
    
       char *res = new char[len];
    
       int result = WideCharToMultiByte(to, 0, in.c_str(), -1, res, len, 0, 0);
    
       if(result != len)
          cout << "Fehler toMBCS2?!\n";
    
       string s(res);
    
       delete[] res;
    
       return s;
    }
    
    string AnsiToUTF8(const string &in)
    {
       wstring tmp = toWide(in, CP_ACP);
       string res = toMultiByte(tmp, CP_UTF8);
       return res;
    }
    
    string UTF8ToAnsi(const string &in)
    {
       wstring tmp = toWide(in, CP_UTF8);
       string res = toMultiByte(tmp, CP_ACP);
       return res;
    }
    
    int main()
    {
       string utf8 = AnsiToUTF8("äöÜ");
       string ansi = UTF8ToAnsi(utf8);
    
       cout << utf8;
       cerr << ansi;
    
    }
    

    Dein Codeschnipsel sieht weitaus einfacher aus, aber ob er korrekt ist, weiß ich nicht.



  • 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


Anmelden zum Antworten