string und wstring ineinander umwandeln



  • Wie das unter Windows geht, weiß ich schon, doch nun würde mich mal interessieren: Wie wandle ich mit Standard-C++ einen std::string in einen std::wstring um und umgekehrt?



  • Hier wurde mal ein wunderbarer Codeschnippsel gepostet:

    /* string2wstring.h */
     #pragma once
    
     #include <string>
     #include <vector>
     #include <locale>
     #include <functional>
     #include <iostream>
    
     // Put this class in your personal toolbox...
     template<class E,
     class T = std::char_traits<E>,
     class A = std::allocator<E> >
    
     class Widen : public std::unary_function<
         const std::string&, std::basic_string<E, T, A> >
     {
         std::locale loc_;
         const std::ctype<E>* pCType_;
    
         // No copy-constructor, no assignment operator...
         Widen(const Widen&);
         Widen& operator= (const Widen&);
    
     public:
         // Constructor...
         Widen(const std::locale& loc = std::locale()) : loc_(loc)
         {
     #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6.0...
             using namespace std;
             pCType_ = &_USE(loc, ctype<E> );
     #else
             pCType_ = &std::use_facet<std::ctype<E> >(loc);
     #endif
         }
    
         // Conversion...
         std::basic_string<E, T, A> operator() (const std::string& str) const
         {
             typename std::basic_string<E, T, A>::size_type srcLen =
                 str.length();
             const char* pSrcBeg = str.c_str();
             std::vector<E> tmp(srcLen);
    
             pCType_->widen(pSrcBeg, pSrcBeg + srcLen, &tmp[0]);
             return std::basic_string<E, T, A>(&tmp[0], srcLen);
         }
     };
    
     // How to use it...
     int main()
     {
     Widen<wchar_t> to_wstring;
     std::string s = "my test string";
     std::wstring w = to_wstring(s);
     std::wcout << w << L"\n";
     }
    

    grüße



  • Das ist nicht Dein Ernst, oder? Es muß doch eine Möglichkeit geben, das ganze umzuwandeln, ohne dieses ganze Zeug da zu machen und eine komplett neue Klasse zu benutzen. Ist das wirklich derartig kompliziert?



  • Hier und da könnte man das evtl etwas vereinfachen. Aber im Grund bleibt es sich gleich. Unicode ist halt kein einfaches Thema und einfach von char zu wchar_t casten reicht eben nicht aus.



  • steht in der FAQ 🙄



  • Was stört dich denn an der Methode? 😕 Nur weil du die Implementierung siehst, findest du sie nicht ernsthaft? Wer sagt dir denn, das andere Konvertierungen, wo du die Implementierungen nicht siehst, besser sind???

    Leg die string2wstring.h in dein Library-Verzeichnis, und schon kannst du es wie jede andere Library einfach benutzen. Die Benutzung beschränkt sich nur auf ZWEI Zeilen!!! Und das ist nicht aufwändig. Oder glaubst du, das cout << "Hallo" auch kurz ist? Du kennst nur die Implementierung nicht. SOnst würdest du dich auch ganz schön wundern, was alles im Hintergrund passiert, bis dein Hallo in der Windows- oder Linux-Konsole erscheint.



  • #include <iostream>
    #include <string>
    #include <vector>
    #include <locale>
    
    std::wstring convertStringToWstring(const std::string& str) 
    { 
    	const std::ctype<wchar_t>& CType = std::use_facet<std::ctype<wchar_t> >(std::locale());
    	std::vector<wchar_t> wideStringBuffer(str.length()); 
    	CType.widen(str.data(), str.data() + str.length(), &wideStringBuffer[0]);
    	return std::wstring(&wideStringBuffer[0], wideStringBuffer.size());
     }
    
    int main() 
    {
    	std::wcout << convertStringToWstring("my test string") << L"\n"; 
    }
    


  • #include <string>
    using namespace std;
    
    int main()
    {
        wstring a(L"Hello String!");
        wstring c;
        string b;
        const char* s = (const char*)a.c_str();
        // Konvertieren von wstring nach string(a nach b)     
            for (int i = 0; *(s+i); i+=2) 
                    b += *(s+i);
    
        const char* y = b.c_str();
        wchar_t x;    
        // Konvertieren von string nach wstring(b nach c)
            for (int i = 0; *(y+i); i++){
                    x = (wchar_t)*(y+i);
                    c += x;
            }
            return 0;
    }
    

    :xmas1:



  • balduin schrieb:

    #include <string>
    using namespace std;
    
    int main()
    {
        wstring a(L"Hello String!");
        wstring c;
        string b;
        const char* s = (const char*)a.c_str();
        // Konvertieren von wstring nach string(a nach b)     
            for (int i = 0; *(s+i); i+=2) 
                    b += *(s+i);
        
        const char* y = b.c_str();
        wchar_t x;    
        // Konvertieren von string nach wstring(b nach c)
            for (int i = 0; *(y+i); i++){
                    x = (wchar_t)*(y+i);
                    c += x;
            }
            return 0;
    }
    

    :xmas1:

    nö! Das ist unportabler Blödsinn!



  • balduin schrieb:

    #include <string>
    using namespace std;
    
    int main()
    {
        wstring a(L"Hello String!");
        wstring c;
        string b;
        const char* s = (const char*)a.c_str();
        // Konvertieren von wstring nach string(a nach b)     
            for (int i = 0; *(s+i); i+=2) 
                    b += *(s+i);
        
        const char* y = b.c_str();
        wchar_t x;    
        // Konvertieren von string nach wstring(b nach c)
            for (int i = 0; *(y+i); i++){
                    x = (wchar_t)*(y+i);
                    c += x;
            }
            return 0;
    }
    

    :xmas1:

    das ist schrecklich und unportabel. Immerhin,wenn man tatsächlich weiß, dass der betreffende Wertebereich zwischen 0 und 127 liegt und es um eine Konvertierung ASCII <-> UNICODE geht (in diesem Bereich spielen locales keine Rolle), kann man das ganze vereinfachen:

    #include <string>
    using namespace std;
    
    int main()
    {
        wstring a(L"Hello String!");
        string b(a.begin(),a.end());
        wstring c(b.begin(),b.end());
    }
    

    Das ist in etwa, was man naiverweise erwartet. In der Praxis ist das allerdings völlig unzureichend. Das unschöne an der gezeigten Lösung von David_pb ff. ist, dass sie in jedem Falle Kopien anlegt, abwohl bei vielen (den meisten?) Implementationen string seine Daten in einem Array speichert und data() und c_str() nur pointer auf diesen Datenbereich zurückgeben. Wenn man dies voraussetzen kann, lassen sich diese Kopien vermeiden. Es dürfte allerdings keinen portablen Weg geben, dieses Verhalten bereits beim Compilieren festzustellen, während der Laufzeit allerdings ist das möglich: da op[] ein echte Referenz zurückgeben muss, brauchen wir nur &s[0] mit data() vergleichen. Sind sie gleich, können wir auf einen eigenen Vektor zum zwischenspeichern verzichten.

    template<class E, class T = std::char_traits<E>, class A = std::allocator<E> >
    class Widen : public std::unary_function< const std::string&, std::basic_string<E, T, A> >
    {
        const std::ctype<E>& ctype_;
        Widen(Widen&);
    public:
        typedef std::basic_string<E, T, A> > str_type;
        Widen(const std::locale& loc = std::locale())
            : ctype_(std::use_facet<std::ctype<E> >(loc))
        {}
    
        // Conversion...
        str_type operator()(const std::string& str) const
        {
            // kl. Quizfrage: was machen wir, wenn string::size_type
            // und str_type::size_type verschieden sind ? :)
            typename str_type::size_type src_len = str.length();
            const char* src_data = str.data();
            if ( src_data == &str[0] )
            {
                str_type result( src_len, E() );
                const E* p = result.data();
                if ( p == &result[0] )
                {
                    ctype_.widen(src_data, src_data + src_len, &result[0]);
                    return result;
                }
            }
            // hier kann man noch weiter optimieren indem man etwa für
            // hinreichend kleine strings ein array auf dem stack benutzt
            std::vector<E> tmp(src_len);
            ctype_.widen(src_data, src_data + src_len, &tmp[0]);
            return str_type(&tmp[0], srcLen);
         }
    };
    


  • Was stört dich denn an der Methode? Nur weil du die Implementierung siehst, findest du sie nicht ernsthaft?

    Nein, mich störte an der Methode lediglich, daß man erst so einen riesigen Aufwand betreiben muß, um diese Konvertierung vorzunehmen.

    Leg die string2wstring.h in dein Library-Verzeichnis, und schon kannst du es wie jede andere Library einfach benutzen. Die Benutzung beschränkt sich nur auf ZWEI Zeilen!!! Und das ist nicht aufwändig.

    Ich bin nicht der Typ, der irgendwelche fremden Funktionen ins Projekt einbindet und sich dann darüber freut, wie toll doch sein Programm funktioniert. Ich will die Funktionen auch verstehen und danach mit meinem eigenen Programmierstil selbst nochmal neu schreiben. (Das bezieht sich natürlich nicht auf vom Standard vorgegebene Dinge, wie cout, oder auf Funktionen von kompletten Frameworks, wie der WinAPI, aber durchaus auf alles selbst gemachte, das ich irgendwo im Internet aufgeschnappt habe und in meinen Programmen tatsächlich verwenden will.)

    Aber da habe ich wohl wieder den C++-Standard überschätzt, von dem ich glaubte, daß er eine Möglichkeit bietet, so eine Konvertierung schnell mit vorgefertigten Funktionen zu realisieren, ohne da eine Doktorarbeit draus zu machen. (Ich finde, sowas sollte zu den Grundfunktionalitäten gehören: ANSI-Strings in Unicode umwandeln und umgekehrt.)



  • Ich finde, sowas sollte zu den Grundfunktionalitäten gehören: ANSI-Strings in Unicode umwandeln und umgekehrt.

    Wird so gut wie nie gebraucht.



  • NES-Spieler schrieb:

    Leg die string2wstring.h in dein Library-Verzeichnis, und schon kannst du es wie jede andere Library einfach benutzen. Die Benutzung beschränkt sich nur auf ZWEI Zeilen!!! Und das ist nicht aufwändig.

    Ich bin nicht der Typ, der irgendwelche fremden Funktionen ins Projekt einbindet und sich dann darüber freut, wie toll doch sein Programm funktioniert. Ich will die Funktionen auch verstehen und danach mit meinem eigenen Programmierstil selbst nochmal neu schreiben. (Das bezieht sich natürlich nicht auf vom Standard vorgegebene Dinge, wie cout, oder auf Funktionen von kompletten Frameworks, wie der WinAPI, aber durchaus auf alles selbst gemachte, das ich irgendwo im Internet aufgeschnappt habe und in meinen Programmen tatsächlich verwenden will.)

    Benutzt du boost oder SDL? Ich verstehe dieses ewige "Ich-muss-alles-selber-screiben-Mentalität" einfach nicht. Was ist daran schlecht Funktionen zu nutzen, die Menschen geschrieben, die sich mit dem Thema besser auskennen und diese Funktionen auch getestet haben. Dann kann ich mich wieder um meinen Kram kümmern. Das versteh ich auch ein bisschen unter OOP. Dinge wiederzuverwenden, die andere bereits geschrieben haben.

    chrische



  • Benutzt du boost oder SDL?

    Nein, wieso?

    Ich verstehe dieses ewige "Ich-muss-alles-selber-screiben-Mentalität" einfach nicht. Was ist daran schlecht Funktionen zu nutzen, die Menschen geschrieben, die sich mit dem Thema besser auskennen und diese Funktionen auch getestet haben. Dann kann ich mich wieder um meinen Kram kümmern.

    Stell Dir vor, ich habe vor kurzem ein Spiel programmiert: Für die Grafikausgabe hab ich eine Library genommen, die irgendjemand im Internet zum Download gestellt hat. Für den Sound das gleiche. Die Tastatureingabe konnte ich unmittelbar realisieren, nachdem ich mir ein paar Quellcodes von diversen Foren zusammenkopiert hatte. Die Kollisionsabfrage gibt es auf der und der Seite fertig zum Download. Die Sprites habe ich von einer Clipart-Seite und die Spielidee ist von einem Klassiker aus den 80ern. Ich bin der Meisterprogrammierer.
    Es geht mir einfach darum, daß das Programm, das ich da schreibe, wirklich meins ist. Klar, ich laß mir gern von anderen was beibringen, so daß ich es selbst anwenden kann. Aber ich klatsche nicht einfach eine fremde Header-Datei in mein Programm. Es sollte nicht darum gehen, seine Programme per Copy & Paste zusammenzubasteln, sondern darum, zu lernen, was dahintersteckt. Klar, wenn es ein komplexes Framework, wie die MFC, OpenGL oder Boost ist, dann kann man das natürlich benutzen. Aber so einen kleinen Algorithmus, den liest man sich entweder durch und versteht ihn und ist dann auch in der Lage, ihn selbst zu programmieren, oder man läßt es bleiben. Aber mein Programm aus 100 winzigen Header-Dateien von 100 verschiedenen Quellen bestehen zu lassen, ist einfach nicht mein Stil.



  • NES-Spieler schrieb:

    ...Ich bin der Meisterprogrammierer.
    Es geht mir einfach darum, daß das Programm, das ich da schreibe, wirklich meins ist....ist einfach nicht mein Stil.

    Schön, wenn Du gut damit klarkommst.
    Es kommt allerdings im Leben auch manchmal darauf an, in möglichst wenig Zeit ein möglichst gutes Ergebnis zu erzielen. Und dann wird es schnell eng mit dem "Alles selbst schreiben"-Ansatz.
    Wenn ich bei meinem letzten größeren Projekt nicht vorgefertiges Persistenzframework, Corba-Umgebung, SAP-, MQSeries-, Kryptohardware- und X25-Libs hätte verwenden können, wäre es niemals zustande gekommen (von einer ewig langen Test-/Fehlerkorrekturphase ganz abgesehen).

    Gut, wenn man beides beherrscht.

    Gruß,

    Simon2.



  • @NES-Spieler:
    Äh. Dann vergiss das mit der char <-> wchar_t Umwandlung mal schnell wieder, denn das wirst du dir so schnell nicht selbst programmieren. Verwende es einfach so wie es in Windows bzw. der C++ Lib implementiert ist, und sei froh dass es sowas gibt.



  • Es kommt allerdings im Leben auch manchmal darauf an, in möglichst wenig Zeit ein möglichst gutes Ergebnis zu erzielen. Und dann wird es schnell eng mit dem "Alles selbst schreiben"-Ansatz.

    Ja, klar, wenn man das in möglichst wenig Zeit machen soll, sieht es auch wieder anders aus. Wobei das bei mir ja eigentlich nur vorkommen kann, wenn ich etwas in der Firma schreibe. Und da sieht die Sache sowieso wieder etwas anders aus: Da das dann nicht wirklich "mein" Programm ist, sondern das der Firma, hätte ich da auch weniger Probleme, mal irgendwas anderes einzubinden, wenn mein Auftraggeber das gutheißt. Hier habe ich allerdings von privaten Programmen gesprochen, die ich so erstelle. Und da will ich nicht Programmteile von Hinz und Kunz drin haben. (Wie gesagt: Wenn ich mir Codes ansehe, sie verstehe und den generellen Algorithmus mit meinem eigenen Schreibstil neu schreibe, ist das was anderes. Aber mir geht es darum, Vorgefertigtes nicht einfach einzufügen.)

    Wenn ich bei meinem letzten größeren Projekt nicht vorgefertiges Persistenzframework, Corba-Umgebung, SAP-, MQSeries-, Kryptohardware- und X25-Libs hätte verwenden können, wäre es niemals zustande gekommen (von einer ewig langen Test-/Fehlerkorrekturphase ganz abgesehen).

    Ich sagte ja auch: Gegen fertige Frameworks hab ich nichts. Ich sträube mich aber dagegen, einen 30 Zeilen langen Codeschnipsel von irgendwem per Copy & Paste in mein Programm zu übernehmen und dann damit zu arbeiten, ohne selbst zu kapieren, wie das nun geht. Und das bezieht sich auch nur auf private Programme von mir. In der Firma ist mir das relativ egal, wenn die Firma selbst kein Problem damit hat. Da richte ich mich nach denen.



  • Hallo

    NES-Spieler schrieb:

    Benutzt du boost oder SDL?

    Nein, wieso?

    Weil das ja auch Bibliotheken sind und somit nicht von dir geschrieben.

    NES-Spieler schrieb:

    Ich verstehe dieses ewige "Ich-muss-alles-selber-screiben-Mentalität" einfach nicht. Was ist daran schlecht Funktionen zu nutzen, die Menschen geschrieben, die sich mit dem Thema besser auskennen und diese Funktionen auch getestet haben. Dann kann ich mich wieder um meinen Kram kümmern.

    Stell Dir vor, ich habe vor kurzem ein Spiel programmiert: Für die Grafikausgabe hab ich eine Library genommen, die irgendjemand im Internet zum Download gestellt hat. Für den Sound das gleiche. Die Tastatureingabe konnte ich unmittelbar realisieren, nachdem ich mir ein paar Quellcodes von diversen Foren zusammenkopiert hatte. Die Kollisionsabfrage gibt es auf der und der Seite fertig zum Download. Die Sprites habe ich von einer Clipart-Seite und die Spielidee ist von einem Klassiker aus den 80ern. Ich bin der Meisterprogrammierer.

    1. Ich halte es für einen Anfänger auch dann noch für schwierig selbst Dinge wie Tetris zu proggen. Dazu gehört schon ein bisschen mehr, als nur Bibliotheken zu linken. Zumindest ist das bei mir so.

    2. Kann man mit dieser Methode viel machen und bleibt eventuell auch länger am Ball. Wenn man besser ist, kann man ja schrittweise selber Dinge einfleissen lassen. Ich bin aber noch der Meinung, dass die Idee und die Umsetzung wichtiger sein sollten, als das selbstständige Schreiben einer Garfikausgabe, die man auch dem Netz hätte nehmen können.

    NES-Spieler schrieb:

    Aber so einen kleinen Algorithmus, den liest man sich entweder durch und versteht ihn und ist dann auch in der Lage, ihn selbst zu programmieren, oder man läßt es bleiben.

    Ich frage mich, nach welchen Kriterien du auswählst, was du benutzt und was nicht. Und zweitens frage ich mich, ob du verstanden hast, warum man Header und Sourcedateien überhaupt verwendet. Eben um nur die Scnittstelle und nicht den ganzen Hokuspokus dahinter zu kennen. Ich sage nicht, dass das immer unwichtig ist, aber warum alles 100% verstehen wollen, wenn es auch so klappt. Wie machst du das im Alltag. Kaufst du dir einen CD-Player oder baust du selber einen? 😉

    chrische



  • alter, wenn du weiter so ne fragen stellst, dann reiss ich dir deinen verfluchten arsch auf



  • NES-Spieler! Dann mußt du aber auch so konsequent sein, und auch die locale facets implementieren. Ich sage da nur eines: Viieeeel Spaß!!! 😃 Also ich bin froh, wenn ich nicht wissen muß, wie ich italienische, griechische, ungarische, polnische, französische, bulgarische, spanische...... *schnarsch* locales implementieren muß. Nein, ich bin froh, das es die Std-Lib erledigt und ich keinen blassen schimmer habe, wie die ganzen lokalen Gegebenheiten für Spezialitäten haben. Nun frage ich dich: hast du das auch vor zu implementieren??? Das wirst du nämlich müssen, wenn du alles selber verstehen willst. Wo ist die Grenze???

    Und wenn du Grafikprogrammierung machst, weißt du auch wie man einen 3D-Chip programmiert? Sach schon??? Warum benutzt du OpenGL??? Wenn du OpenGL benutz, hast du noch lange nicht die Implementierung von OpenGL und die eines Grafikchips verstanden. Du benutzt dann praktisch auch nur das, was wir die hier gepostet haben: ein string2wstring.h!!!

    Und noch was: wenn dir jemand eine Lösung postet, die auch noch funktioniert, ist es das Letzte, ihn dumm anzumachen. Ich hätte es ja verstanden, wenn es eine falsche Lösung wäre (Thema verfehlt) oder es fehlerhaft wäre, das man es nicht gebrauchen könnte. Aber so? So sage ich aber nur eines: warum fragst du erst, wenn du es eh nicht selbst versucht hast? Warum hast du es nicht selbst versucht?