CString
ist sehr praktisch, während std::string
es besser mit STL-Container kompatibel ist. Ich benutze hash_map
. Allerdings hash_map
unterstützt nicht CString
als Schlüssel, so dass ich konvertieren wollen CString
in std::string
.
Das Schreiben einer CString
Hash-Funktion scheint viel Zeit in Anspruch zu nehmen.
CString -----> std::string
Wie kann ich das machen?
std::string -----> CString:
inline CString toCString(std::string const& str)
{
return CString(str.c_str());
}
Habe ich recht?
BEARBEITEN:
Hier sind weitere Fragen:
Wie kann ich konvertieren wstring
, CString
miteinander?
//wstring -> CString,
std::wstring src;
CString result(src.c_str());
//CString->wstring.
CString src;
::std::wstring des(src.GetString());
Gibt es ein Problem?
Wie kann ich konvertieren std::wstring
, std::string
miteinander?
Antworten:
Laut CodeGuru :
CString
zustd::string
:CString cs("Hello"); std::string s((LPCTSTR)cs);
ABER:
std::string
kann nicht immer aus a konstruierenLPCTSTR
. Das heißt, der Code schlägt für UNICODE-Builds fehl.Da
std::string
nur ausLPSTR
/ erstellt werden kannLPCSTR
, kann ein Programmierer, der VC ++ 7.x oder besser verwendet, Konvertierungsklassen verwenden, z. B.CT2CA
als Vermittler.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
zuCString
: (Aus den CString-FAQs von Visual Studio ... )std::string s("Hello"); CString cs(s.c_str());
CStringT
kann sowohl aus Zeichenfolgen als auch aus Zeichenfolgen mit breiten Zeichen bestehen. dh es kann vonchar*
(dhLPSTR
) oder vonwchar_t*
(LPWSTR
) konvertieren .Mit anderen Worten, char-Spezialisierung (von
CStringT
) , dhCStringA
,wchar_t
-specilizationCStringW
undTCHAR
-specializationCString
kann entweder konstruiert werdenchar
oder Breitzeichen,null terminiert (null terminierung ist hier sehr wichtig)String-Quellen.Trotzdem ändert IInspectable den Teil "Null-Kündigung" in den Kommentaren :
quelle
NUL
-Kündigung ist nicht erforderlich.CStringT
hat Konvertierungskonstruktoren, die ein explizites Längenargument verwenden. Dies bedeutet auch, dass SieCStringT
Objekte ausstd::string
Objekten mit eingebettetenNUL
Zeichen erstellen können .Lösen Sie das, indem Sie
std::basic_string<TCHAR>
anstelle von verwenden,std::string
und es sollte unabhängig von Ihrer Charaktereinstellung einwandfrei funktionieren.quelle
typedef std::basic_string<TCHAR> tstring
Es ist effizienter,
CString
aufstd::string
die Konvertierung zu konvertieren , bei der die Länge angegeben ist.CString someStr("Hello how are you"); std::string std(somStr, someStr.GetLength());
In einer engen Schleife führt dies zu einer signifikanten Leistungsverbesserung.
quelle
cannot convert parameter 1 from 'CString' to 'const std::basic_string<_Elem,_Traits,_Alloc> &'
Wenn Sie etwas C ++ - ähnlicheres wollen, verwende ich dieses. Obwohl es von Boost abhängt, gibt es nur Ausnahmen. Sie können diejenigen, die es verlassen, leicht entfernen, um nur von der STL und dem
WideCharToMultiByte()
Win32-API-Aufruf abhängig zu sein .#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); }
quelle
(Seit VS2012 ... und mindestens bis VS2017 v15.8.1)
Da es sich um ein MFC-Projekt handelt und CString eine MFC-Klasse ist, bietet MS einen technischen Hinweis TN059: Verwenden von MFC-MBCS / Unicode-Konvertierungsmakros und generischen Konvertierungsmakros:
Verwenden:
void Example() // ** UNICODE case ** { USES_CONVERSION; // (1) // CString to std::string / std::wstring CString strMfc{ "Test" }; // strMfc = L"Test" std::string strStd = W2A(strMfc); // ** Conversion Macro: strStd = "Test" ** std::wstring wstrStd = strMfc.GetString(); // wsrStd = L"Test" // std::string to CString / std::wstring strStd = "Test 2"; strMfc = strStd.c_str(); // strMfc = L"Test 2" wstrStd = A2W(strStd.c_str()); // ** Conversion Macro: wstrStd = L"Test 2" ** // std::wstring to CString / std::string wstrStd = L"Test 3"; strMfc = wstrStd.c_str(); // strMfc = L"Test 3" strStd = W2A(wstrStd.c_str()); // ** Conversion Macro: strStd = "Test 3" ** }
- -
Fußnoten:
(1) Damit die Konvertierungsmakros Platz zum Speichern der temporären Länge haben,
_convert
muss in jeder Funktion, die die Konvertierungsmakros verwendet , eine lokale Variable deklariert werden , die dies ausführt. Dies erfolgt durch Aufrufen desUSES_CONVERSION
Makros. Im VS2017-MFC-Code (atlconv.h) sieht es folgendermaßen aus:#ifndef _DEBUG #define USES_CONVERSION int _convert; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw; (_lpw); LPCSTR _lpa; (_lpa) #else #define USES_CONVERSION int _convert = 0; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw = NULL; (_lpw); LPCSTR _lpa = NULL; (_lpa) #endif
quelle
USES_CONVERSION
ist bei Verwendung von ATL 7.0- Zeichenfolgenkonvertierungsmakros nicht erforderlich . ATL 7.0 wird mit Visual Studio 2003 ausgeliefert.Es gibt mehrere Probleme:
CString
ist eine Vorlagenspezialisierung von CStringT . Abhängig vom BaseType , der den Zeichentyp beschreibt, gibt es zwei konkrete Spezialisierungen:CStringA
(usingchar
) undCStringW
(usingwchar_t
).wchar_t
unter Windows allgegenwärtig zum Speichern von UTF-16-codierten Codeeinheiten verwendet wird, ist die Verwendung nichtchar
eindeutig. Letzteres speichert üblicherweise ANSI-codierte Zeichen, kann aber auch ASCII-, UTF-8- oder sogar Binärdaten speichern.CString
(die über das_UNICODE
Präprozessorsymbol gesteuert wird ) nicht, was die Frage mehrdeutig macht. Wir kennen auch nicht die gewünschte Zeichenkodierung vonstd::string
.Um diese Probleme zu beheben, gehe ich davon aus, dass
wchar_t
UTF-16-codierte Codeeinheiten gespeichert werden undchar
UTF-8-Oktettsequenzen enthalten. Dies ist die einzig vernünftige Wahl, die Sie treffen können, um sicherzustellen, dass Quell- und Zielzeichenfolgen dieselben Informationen beibehalten, ohne die Lösung auf eine Teilmenge der Quell- oder Zieldomänen zu beschränken.Die folgenden Implementierungen konvertieren zwischen
CStringA
/CStringW
undstd::wstring
/std::string
Mapping von UTF-8 nach UTF-16 und umgekehrt:#include <string> #include <atlconv.h> std::string to_utf8(CStringW const& src_utf16) { return { CW2A(src_utf16.GetString(), CP_UTF8).m_psz }; } std::wstring to_utf16(CStringA const& src_utf8) { return { CA2W(src_utf8.GetString(), CP_UTF8).m_psz }; }
Die verbleibenden zwei Funktionen erstellen C ++ - Zeichenfolgenobjekte aus MFC-Zeichenfolgen, wobei die Codierung unverändert bleibt. Beachten Sie, dass die vorherigen Funktionen zwar nicht mit eingebetteten NUL-Zeichen umgehen können, diese Funktionen jedoch dagegen immun sind.
#include <string> #include <atlconv.h> std::string to_std_string(CStringA const& src) { return { src.GetString(), src.GetString() + src.GetLength() }; } std::wstring to_std_wstring(CStringW const& src) { return { src.GetString(), src.GetString() + src.GetLength() }; }
quelle
Dies ist eine Fortsetzung von Sal's Antwort, in der er / sie die Lösung lieferte:
CString someStr("Hello how are you"); std::string std(somStr, someStr.GetLength());
Dies ist auch nützlich, wenn ein nicht typischer C-String in einen std :: string konvertiert wird
Ein Anwendungsfall für mich war ein vorab zugewiesenes char-Array (wie C-String), das jedoch nicht NUL-beendet ist. (dh SHA Digest). Mit der obigen Syntax kann ich die Länge des SHA-Digests des char-Arrays angeben, damit std :: string nicht nach dem terminierenden NUL-Zeichen suchen muss, das möglicherweise vorhanden ist oder nicht.
Sowie:
unsigned char hashResult[SHA_DIGEST_LENGTH]; auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);
quelle
Das funktioniert gut:
//Convert CString to std::string inline std::string to_string(const CString& cst) { return CT2A(cst.GetString()); }
quelle
von diesem Beitrag (Danke Mark Ransom )
CString in String konvertieren (VC6)
Ich habe dies getestet und es funktioniert gut.
std::string Utils::CString2String(const CString& cString) { std::string strStd; for (int i = 0; i < cString.GetLength(); ++i) { if (cString[i] <= 0x7f) strStd.append(1, static_cast<char>(cString[i])); else strStd.append(1, '?'); } return strStd; }
quelle
Funktioniert bei mir:
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(); }
quelle
WStringToCString
schlägt für alle Nicht-ASCII-Zeichen in der Quellzeichenfolge fehl.CStringToWString
schlägt auch für Nicht-ASCII-Zeichen fehl und erzeugt ungültige UTF-16-Codeeinheiten. Ich verstehe, dass diese Lösung immer wieder auftaucht, aber sie war immer falsch und wird auch weiterhin falsch sein.Alle anderen Antworten haben nicht ganz das angesprochen, wonach ich gesucht habe, nämlich im laufenden Betrieb zu konvertieren
CString
, anstatt das Ergebnis in einer Variablen zu speichern.Die Lösung ist ähnlich wie oben, aber wir benötigen einen weiteren Schritt, um ein namenloses Objekt zu instanziieren. Ich illustriere mit einem Beispiel. Hier ist meine Funktion, die
std::string
aber ich braucheCString
.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 nennt man es, wenn man eine hat
CString
?std::string firstName = "First"; CString lastName = _T("Last"); writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );
Beachten Sie, dass die letzte Zeile keine direkte Typumwandlung ist, sondern dass wir ein namenloses
std::string
Objekt erstellen und dasCString
über seinen Konstruktor bereitstellen .quelle
Sie können CT2CA verwenden
CString datasetPath; CT2CA st(datasetPath); string dataset(st);
quelle
konvertieren
CString to std::string
. Sie können dieses Format verwenden.std::string sText(CW2A(CSText.GetString(), CP_UTF8 ));
quelle
CString
aufstd::string
Sie diese verwenden können:std::string sText(CW2A(CSText.GetString(), CP_UTF8 ));
.Wenn Sie problemlos zwischen anderen Zeichenfolgentypen konvertieren
_bstr_t
möchten , ist die Klasse möglicherweise besser geeignet. Es unterstützt converstion zwischenchar
,wchar_t
undBSTR
.quelle
CString
bereits alle von Ihnen benannten Konvertierungen durch. Und das auch vor 3 Jahren. Es macht keinen Sinn, einen Typ vorzuschlagen, der für die Verwendung in COM-Umgebungen vorgesehen ist.Ein interessanter Ansatz besteht darin
CString
,CStringA
in einenstring
Konstruktor zu werfen . Im Gegensatzstd::string s((LPCTSTR)cs);
dazu funktioniert dies auch dann, wenn_UNICODE
es definiert ist. In diesem Fall wird jedoch eine Konvertierung von Unicode nach ANSI durchgeführt, sodass höhere Unicode-Werte über den ASCII-Zeichensatz hinaus nicht sicher sind. Eine solche Konvertierung unterliegt der_CSTRING_DISABLE_NARROW_WIDE_CONVERSION
Präprozessordefinition. https://msdn.microsoft.com/en-us/library/5bzxfsea.aspxCString s1("SomeString"); string s2((CStringA)s1);
quelle
CString
verfügt über Konvertierungskonstruktoren, die das aktuelle Gebietsschema des aufrufenden Threads verwenden. Die Konvertierung ist verlustbehaftet, und Sie können ein Fenster mit einer Zeichenfolge öffnen, die nicht mehr die Quelle darstellt. Ja, es ist einfach und bequem. Aber auch falsch.(CStringA)s1
ist eine Besetzung in dem Sinne, dass es sich um eine explizite Konvertierung handelt. Ist das der Teil, den Sie hier für falsch halten? Wenn dies in bestimmten Anwendungsfällen funktioniert, was auch der Fall ist, kann es per Definition für diese Anwendungsfälle nicht falsch sein. Wenn es einfach und bequem ist, dann umso besser. Sie sagen also, dass das Umwandeln von CString in CStringA aufgrund des korrekten Gebietsschemas nicht immer zuverlässig ist? Ich habe speziell gefragt, "warum nicht ...", und ich bin interessiert, ob Sie Details angeben können. Ich werde entsprechend aktualisieren, aber würden Sie diesen Ansatz als falsch bezeichnen, solange die Einschränkungen verstanden werden?_CSTRING_DISABLE_NARROW_WIDE_CONVERSION
Präprozessorsymbols ist die sichere Option: Diese vorgeschlagene Lösung kann nicht kompiliert werden. Diese Lösung ist nicht einmal sicher, wenn alle Einschränkungen verstanden werden, da es keine Möglichkeit gibt, die Anforderungen durchzusetzen.Sie können
CString
frei werfenconst char*
und es dann einem solchen zuweisenstd::string
:CString cstring("MyCString"); std::string str = (const char*)cstring;
quelle