2008-11-03 15 views
63

CString ist ziemlich praktisch, während std::string ist mehr kompatibel mit STL-Container. Ich verwende hash_map. hash_map unterstützt jedoch nicht CString als Schlüssel, daher möchte ich CString in std::string konvertieren.Wie CString und :: Std :: string :: std :: wstring miteinander zu konvertieren?

Schreiben einer CString Hash-Funktion scheint eine Menge Zeit zu dauern.

CString -----> std::string 

Wie kann ich das tun?

std::string -----> CString: 

inline CString toCString(std::string const& str) 
{ 
    return CString(str.c_str()); 
} 

Bin ich richtig?


EDIT:

Hier sind weitere Fragen:

Wie kann ich wstring, CString miteinander konvertieren?

//wstring -> CString, 
std::wstring src; 
CString result(src.c_str()); 
//CString->wstring. 
CString src; 
::std::wstring des(src.GetString()); 

Gibt es irgendein Problem?

Wie kann ich std::wstring, std::string miteinander konvertieren?

+3

Ich würde das nicht tun ... Die Verwendung von zwei verschiedenen Stringtypen ist schlimm genug, aber jedes Mal, wenn Sie etwas mit einer Karte machen, konvertieren müssen? Hört sich schrecklich an. Sei einfach konsistent und verwende std :: string. Wenn Sie aus irgendeinem Grund wirklich denken, CString ist besser, dann definieren Sie eine Hash-Funktion für sie, so dass Ihre hash_map es verwenden kann, das ist weit besser als die Verdoppelung in Ihrem Code zu verdoppeln. – GManNickG

+2

Eigentlich, wenn alles Code von mir selbst geschrieben wird, wird es konsistent sein, aber es gibt einige OpenSourced-Projekt wie freeimage SQLite verwendet. Ich kann den Code nicht ändern. – user25749

Antwort

78

Nach CodeGuru:

CString-std::string:

CString cs("Hello"); 
std::string s((LPCTSTR)cs); 

ABER:std::string kann aus einem LPCTSTR nicht immer konstruieren. d.h. der Code wird für UNICODE-Builds fehlschlagen.

Als std::string kann LPSTR/LPCSTR, ein Programmierer nur aus konstruieren, die 7.x oder besser VC++ verwendet, kann Konvertierungsklassen wie CT2CA als Vermittler nutzen.

CString cs ("Hello"); 
// Convert a TCHAR string to a LPCSTR 
CT2CA pszConvertedAnsiString (cs); 
// construct a std::string using the LPCSTR input 
std::string strStd (pszConvertedAnsiString); 

std::string to CString: (von Visual Studio's CString FAQs...)

std::string s("Hello"); 
CString cs(s.c_str()); 

CStringT kann sowohl von Zeichen oder Weitzeichenketten aufzubauen. Es kann von char* (d. h. LPSTR) oder von wchar_t* (LPWSTR) umgewandelt werden.

Mit anderen Worten: char-Spezialisierung (von CStringT), dh CStringA, wchar_t -specilization CStringW und TCHAR -specialization CString kann entweder char oder Breitzeichen, null beendet (Null-Terminierung ist sehr wichtig, hier gebaut werden) String-Quellen.IInspectable
Althoug ändert die "Null-Terminierung" Teil in the comments:

NUL-Terminierung ist nicht erforderlich.
CStringT hat Konvertierungskonstruktoren, die ein explizites Längenargument verwenden. Dies bedeutet auch, dass Sie CStringT Objekte aus std::string Objekte mit eingebetteten NUL Zeichen erstellen können.

+2

Errr ... sind herzlich willkommen :) Danke an Siddhartha Rao für die ausführlichen Erklärungen. – VonC

+0

Der letzte Absatz ist nicht ganz korrekt. 'NUL'-Kündigung ist nicht erforderlich. ['CStringT'] (http://msdn.microsoft.com/en-us/library/cws1zdt8.aspx) verfügt über Konvertierungskonstruktoren, die ein explizites Längenargument verwenden. Dies bedeutet auch, dass Sie 'CStringT'-Objekte aus' std :: string'-Objekten mit eingebetteten 'NUL'-Zeichen konstruieren können. – IInspectable

+0

@Intspectable guter Punkt. Ich habe Ihren Kommentar in die Antwort für mehr Sichtbarkeit aufgenommen. – VonC

33

dass Lösen von std::basic_string<TCHAR> statt std::string verwenden und es sollte unabhängig von Ihrem Charakter Einstellung funktionieren.

+2

Diese Methode ist einfacher – user25749

+5

Ich mag Typedef, dass für Bequemlichkeit und Vertrautheit: 'typedef std :: basic_string tstring' –

-1

Wenn Sie einfach zwischen anderen Stringtypen konvertieren möchten, wäre vielleicht die _bstr_t Klasse besser geeignet? Es unterstützt die Umwandlung zwischen char, wchar_t und BSTR.

+1

-1' CString' bereits alle Konvertierungen, die Sie nennen. Und es hat vor 3 Jahren auch gemacht. Kein Grund, einen Typ vorzuschlagen, der für die Verwendung in COM-Umgebungen gedacht ist. – IInspectable

4

Wenn Sie etwas mehr C++ - wie, möchte ich das verwenden. Obwohl es auf Boost ankommt, ist das nur für Ausnahmen. Sie können diese einfach entfernen, sodass sie nur vom STL- und WideCharToMultiByte() Win32-API-Aufruf abhängig ist.

#include <string> 
#include <vector> 
#include <cassert> 
#include <exception> 

#include <boost/system/system_error.hpp> 
#include <boost/integer_traits.hpp> 

/** 
* Convert a Windows wide string to a UTF-8 (multi-byte) string. 
*/ 
std::string WideStringToUtf8String(const std::wstring& wide) 
{ 
    if (wide.size() > boost::integer_traits<int>::const_max) 
     throw std::length_error(
      "Wide string cannot be more than INT_MAX characters long."); 
    if (wide.size() == 0) 
     return ""; 

    // Calculate necessary buffer size 
    int len = ::WideCharToMultiByte(
     CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), 
     NULL, 0, NULL, NULL); 

    // Perform actual conversion 
    if (len > 0) 
    { 
     std::vector<char> buffer(len); 
     len = ::WideCharToMultiByte(
      CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), 
      &buffer[0], static_cast<int>(buffer.size()), NULL, NULL); 
     if (len > 0) 
     { 
      assert(len == static_cast<int>(buffer.size())); 
      return std::string(&buffer[0], buffer.size()); 
     } 
    } 

    throw boost::system::system_error(
     ::GetLastError(), boost::system::system_category); 
} 
5

Es ist leistungsfähigere CString-std::string mit der Umwandlung zu konvertieren, wobei die Länge angegeben wird.

In engen Schleife macht dies eine deutliche Leistungsverbesserung.

+1

Ich habe einen Fehler mit diesem: 'kann nicht konvertieren Parameter 1 von 'CString' zu 'const std :: basic_string <_Elem, _Traits, _Alloc> &'" –

1

Werke für mich:

std::wstring CStringToWString(const CString& s) 
{ 
    std::string s2; 
    s2 = std::string((LPCTSTR)s); 
    return std::wstring(s2.begin(),s2.end()); 
} 

CString WStringToCString(std::wstring s) 
{ 
    std::string s2; 
    s2 = std::string(s.begin(),s.end()); 
    return s2.c_str(); 
} 
1

Dies ist ein folgen zu Sal Antwort auf, wo er/sie die Lösung zur Verfügung gestellt:

CString someStr("Hello how are you"); 
std::string std(somStr, someStr.GetLength()); 

Dies ist nützlich, auch wenn ein nicht-typische C Umwandlung -String to a std :: string

Ein Anwendungsfall für mich war eine vor-zugewiesene Char-Array (wie C-String), aber es ist nicht NUL terminiert. (d. h. SHA-Verdau). Die obige Syntax ermöglicht es mir, die Länge des SHA-Digest des Char-Array anzugeben, so dass std :: string nicht nach dem abschließenden NUL-Zeichen suchen muss, das da sein kann oder nicht.

wie:

unsigned char hashResult[SHA_DIGEST_LENGTH];  
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH); 
+0

Vielleicht wäre es besser, wenn Sie Sal Antwort mit Ihrem Änderungsantrag als Anhang bearbeitet oder Sals Antwort kommentiert? – Kmeixner

+0

Ich habe versucht ... aber stackoverflow hat mir nicht die Möglichkeit zu tun und zu bearbeiten. – Neil

1

Dies funktioniert:

//Convert CString to std::string 
inline std::string to_string(const CString& cst) 
{ 
    return CT2A(cst.GetString()); 
} 
0

Alle anderen Antworten nicht ganz Adresse, was ich suchte, für die war CString on the fly zu konvertieren, im Gegensatz zu speichern das Ergebnis in einer Variablen.

Die Lösung ist ähnlich wie oben, aber wir brauchen einen weiteren Schritt, um ein namenloses Objekt zu instanziieren. Ich illustriere mit einem Beispiel. Hier ist meine Funktion, die std::string benötigt, aber ich habe CString.

void CStringsPlayDlg::writeLog(const std::string &text) 
{ 
    std::string filename = "c:\\test\\test.txt"; 

    std::ofstream log_file(filename.c_str(), std::ios_base::out | std::ios_base::app); 

    log_file << text << std::endl; 
} 

Wie man es nennt, wenn Sie eine CString haben?

std::string firstName = "First"; 
CString lastName = _T("Last"); 

writeLog(firstName + ", " + std::string(CT2A(lastName)));  

Beachten Sie, dass die letzte Zeile nicht eine direkte Typumwandlung ist, aber wir sind ein namenlos std::string Objekt erstellt und die CString über den Konstruktor.

0

Warum nicht einfach von CString auf CStringA innerhalb eines string Konstruktors?

 CString s1("SomeString"); 
     string s2((CStringA)s1); 
Verwandte Themen