Wie CString und :: std :: string :: std :: wstring miteinander konvertieren?
Frage
CString
ist ganz praktisch, während std::string
mehr kompatibel mit STL-Container ist.
Ich verwende hash_map
. Allerdings hash_map
nicht CString
als Schlüssel unterstützen, so möchte ich CString
in std::string
konvertieren.
Schreiben eine CString
Hash-Funktion scheint eine Menge Zeit in Anspruch nehmen.
CString -----> std::string
Wie kann ich das tun?
std::string -----> CString:
inline CString toCString(std::string const& str)
{
return CString(str.c_str());
}
Habe ich Recht?
EDIT:
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 jede Problem?
Wie kann ich konvertieren std::wstring
, std::string
miteinander?
Lösung
Nach MS-Office-:
CString
zu std::string
:
CString cs("Hello");
std::string s((LPCTSTR)cs);
ABER: std::string
kann aus einem LPCTSTR
nicht immer konstruieren. das heißt der Code für UNICODE nicht baut.
Als std::string
nur aus LPSTR
/ LPCSTR
konstruieren kann, ein Programmierer, die 7.x VC ++ verwendet oder besser kann Konvertierungsklassen nutzen wie CT2CA
als Vermittler auf.
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
CString
: (Von Visual Studio CString FAQs ... )
std::string s("Hello");
CString cs(s.c_str());
CStringT
kann sowohl von Zeichen oder Weitzeichenketten aufzubauen. das heißt, es kann von char*
zu konvertieren (das heißt LPSTR
) oder von wchar_t*
(LPWSTR
).
Mit anderen Worten: char-Spezialisierung (von CStringT
), dh CStringA
, wchar_t
-specilization CStringW
und TCHAR
-Spezialisierung CString
kann entweder char
oder Breitzeichen konstruiert werden, null beendet (Null-Terminierung ist sehr wichtig, hier) string Quellen.
Althoug IInspectable ändert die "Null-Terminierung" -Teil in den Kommentare :
NUL-Beendigung ist nicht erforderlich .
CStringT
hat Umwandlung Konstrukteuren, die eine explizite Länge Argument. Das bedeutet auch, dass SieCStringT
Objekte ausstd::string
Objekten mit eingebettetenNUL
Zeichen konstruieren können.
Andere Tipps
Lösen Sie, dass durch std::basic_string<TCHAR>
statt std::string
verwenden und es sollte unabhängig von Ihrem Charakter Einstellung funktionieren.
Es ist leistungsfähigere CString
zu konvertieren die Konvertierung std::string
mit denen die Länge angegeben ist.
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
In enger Schleife dies macht eine deutliche Leistungssteigerung.
Wenn Sie etwas mehr C ++ wollen - wie, das ist, was ich benutze. Obwohl es auf Boost-abhängig ist, ist das nur für Ausnahmen. Sie können diese leicht entfernen lassen nur auf der STL und der 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);
}
(Da VS2012 ... und zumindest bis VS2017 v15.8.1)
Da es ein MFC-Projekt ist & CString ist eine MFC-Klasse, bietet MS eine Technical Note
Dies ist eine zu Sal Antwort folgen, wo er / sie die Lösung zu finden: Dies ist nützlich, auch wenn ein nicht-typischen C-String in einem std :: string Umwandlung Ein Anwendungsfall für mich mit einem im Voraus zugewiesenen char-Array (wie C-String), aber es ist nicht NUL beendet. (D SHA Digest).
Die obige Syntax ermöglicht es mir, die Länge des SHA-Digest des char-Array angeben, so dass std :: string nicht für die abschließenden NUL Zeichen zu suchen hat, die nicht da sein kann. Wie zum Beispiel: CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
unsigned char hashResult[SHA_DIGEST_LENGTH];
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);
Dies funktioniert:
//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
return CT2A(cst.GetString());
}
von diesem Posten (Danke Mark Ransom )
Konvertieren CString string (VC6)
Ich habe das 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;
}
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();
}
Alle anderen Antworten nicht ganz Adresse, was ich für die suchte CString
on the fly zu konvertieren war im Gegensatz das Ergebnis in einer Variablen zu speichern.
Die Lösung ist ähnlich wie oben, aber wir brauchen einen weiteren Schritt ein namenlos Objekt zu instanziiert. Ich illustriert mit einem Beispiel. Hier ist meine Funktion, die std::string
braucht 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 es nennen, 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 und liefert die CString
über den Konstruktor zu schaffen.
Gibt es jede Problem?
Es gibt mehrere Probleme:
-
CString
ist eine Vorlage Spezialisierung der CStringT . Je nach der Basetype beschreibt den Zeichentyp gibt es zwei konkrete Spezialisierungen.CStringA
(mitchar
) undCStringW
(mitwchar_t
) - Während
wchar_t
auf Windows ubiquitär speichern UTF-16 codierten Codeeinheiten verwendet,char
Verwendung ist nicht eindeutig. Letztere häufig speichert ANSI-Zeichen codiert, kann aber auch speichern ASCII, UTF-8, oder auch binäre Daten. - Wir wissen nicht, die Zeichenkodierung (oder sogar Art Zeichen) von
CString
(die durch das_UNICODE
Präprozessorsymbol gesteuert wird), so dass die Frage nicht eindeutig. Wir wissen nicht, auch die gewünschte Zeichencodierung vonstd::string
. - Konvertierung zwischen Unicode und ANSI ist von Natur aus mit Verlust behaftete. ANSI-Codierung nur eine Teilmenge des Unicode-Zeichensatzes darstellen kann
Um diese Probleme zu adressieren, ich werde diesen wchar_t
anzunehmen, UTF-16 kodierte Codeeinheiten speichern und char
wird UTF-8-Oktett Sequenzen halten. Das ist die einzige vernünftige Wahl Sie sicherstellen, machen können, dass Quell- und Zielzeichenketten die gleichen Informationen behalten, ohne die Lösung zu einer Teilmenge der Quell- oder Zieldomänen zu begrenzen.
Die folgenden Umsetzungen wandeln zwischen CStringA
/ CStringW
und std::wstring
/ std::string
Abbildung von UTF-8 in 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 konstruieren C ++ String-Objekte aus MFC-Strings, so dass die Codierung unverändert. Beachten Sie, dass die bisherigen Funktionen können nicht mit eingebetteten NUL-Zeichen fertig zu werden, diese Funktionen zu, dass 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() };
}
Sie können mit CT2CA
CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);
Wenn Sie schauen einfach zwischen anderen Saiten-Typen konvertieren, vielleicht das _bstr_t
Klasse wäre besser geeignet sein? Es unterstützt converstion zwischen char
, wchar_t
und BSTR
.
Ein interessanter Ansatz ist CString
zu werfen in einem CStringA
Konstruktor string
. Im Gegensatz zu std::string s((LPCTSTR)cs);
wird dies funktionieren, selbst wenn _UNICODE
definiert ist. Wenn dies jedoch der Fall, so wird diese Umwandlung von Unicode in ANSI durchzuführen, so ist es für höhere Unicode-Werte über den ASCII-Zeichensatz unsicher. Eine solche Umwandlung ist auf die _CSTRING_DISABLE_NARROW_WIDE_CONVERSION
Präprozessordefinition Thema. https://msdn.microsoft.com/en-us/library/5bzxfsea. aspx
CString s1("SomeString");
string s2((CStringA)s1);