Как преобразовать CString и:std:: string:std:: wstring друг в друга?
CString - Это довольно удобно, в то время как std::string более совместим с контейнером STL.
Я использую hash_map. Однако,hash_map не поддерживает CString как ключ, поэтому я хочу, чтобы преобразовать CString на std::string.
пишем CString хэш-функция, кажется, занимает много времени.
CString -----> std::string
как я могу это сделать?
std::string -----> CString:
inline CString toCString(std::string const& str)
{
return CString(str.c_str());
}
я прав?
EDIT:
вот еще вопросы:
как я могу конвертировать wstring,CString друг с другом?
//wstring -> CString,
std::wstring src;
CString result(src.c_str());
//CString->wstring.
CString src;
::std::wstring des(src.GetString());
здесь любой?
как я могу конвертировать std::wstring,std::string друг с другом?
13 ответов:
по данным CodeGuru:
CStringдоstd::string:CString cs("Hello"); std::string s((LPCTSTR)cs);но:
std::stringне всегда можно построить изLPCTSTR. т. е. код не будет работать для сборки UNICODE.как
std::stringможно построить только изLPSTR/LPCSTR, программист, который использует VC++ 7.x или лучше может использовать классы преобразования, такие какCT2CAкак посредник.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: (От CString Часто задаваемые вопросы Visual Studio...)std::string s("Hello"); CString cs(s.c_str());
CStringTможно построить как символа или символов. т. е. он может конвертировать изchar*(т. е.LPSTR) илиwchar_t*(LPWSTR).другими словами, char-специализация (of
CStringT), т. е.CStringA,wchar_t-specilizationCStringWиTCHARспециализацииCStringможет быть построен из любогоcharили расширенных символов,значение null (нулевое завершение очень важно здесь)строке источников.
Хотя IInspectable вносит изменения в часть "null-termination"в комментариях:NUL-завершение не требуется.
CStringTимеет конструкторы преобразования, которые принимают явный аргумент длины. Это также означает, что вы можете построитьCStringTобъектыstd::stringобъекты со встроеннымиNULсимволы.
решить эту проблему с помощью
std::basic_string<TCHAR>вместоstd::stringи он должен работать нормально вне зависимости от параметров персонажа.
более эффективно конвертировать
CStringtostd::stringиспользуя преобразование, в котором указана длина.CString someStr("Hello how are you"); std::string std(somStr, someStr.GetLength());в плотной петле это делает значительное улучшение производительности.
Если вы хотите что-то более C++ - как, это то, что я использую. Хотя это зависит от Boost, это только для исключений. Вы можете легко удалить те, оставляя его зависеть только от STL и
WideCharToMultiByte()вызов Win32 API.#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); }
Это продолжение ответа Сэла, где он / она предоставил решение:
CString someStr("Hello how are you"); std::string std(somStr, someStr.GetLength());это полезно также при преобразовании нетипичной C-строки в std:: string
вариант использования для меня имел предварительно выделенный массив символов (например, C-String), но он не завершается нулем. (т. е. ша переварить). Приведенный выше синтаксис позволяет мне указать длину дайджеста SHA массива char, чтобы std:: string не нужно было искать завершающий символ NUL, который может или может не быть там.
, например:
unsigned char hashResult[SHA_DIGEST_LENGTH]; auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);
Это прекрасно работает:
//Convert CString to std::string inline std::string to_string(const CString& cst) { return CT2A(cst.GetString()); }
С этого поста (спасибо Марк Рэнсом)
преобразовать CString в string (VC6)
Я проверил это, и он отлично работает.
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; }
(начиная с VS2012 ...и по крайней мере до VS2017 программы V15.8.1)
так как это проект MFC и CString является классом MFC, MS предоставляет техническое Примечание TN059: использование макросов преобразования MFC MBCS / Unicode и общие макросы преобразования:
A2CW (LPCSTR) -> (LPCWSTR) A2W (LPCSTR) -> (LPWSTR) W2CA (LPCWSTR) -> (LPCSTR) W2A (LPCWSTR) -> (LPSTR)использование:
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" ** }--
Примечания:
(1) для того, чтобы в макросах преобразования было место для хранения временной длины, необходимо объявить локальную переменную с именем
_convertэто делает это в каждой функции, которая использует макросы преобразования. Это делается путем вызоваUSES_CONVERSIONмакрос. В коде MFC VS2017 (atlconv.З) это выглядит так:#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
У меня работает:
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(); }
все остальные ответы не совсем касались того, что я искал, что нужно было конвертировать
CStringна лету, а не хранить результат в переменной.решение аналогично выше, но нам нужен еще один шаг, чтобы создать экземпляр безымянного объекта. Я иллюстрирую это примером. Вот моя функция, которая нуждается
std::stringно у меня есть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; }как это назвать, когда у вас есть
CString?std::string firstName = "First"; CString lastName = _T("Last"); writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );обратите внимание, что последняя строка не прямой типаж, но мы создаем безымянный
std::stringобъект и поставитьCStringчерез его конструктор.
здесь любой?
есть несколько вопросов:
CString- это шаблон специализации CStringT. В зависимости от BaseType описывая тип персонажа, есть две конкретные специализации:CStringA(черезchar) иCStringW(черезwchar_t).- пока
wchar_tна Windows повсеместно используется для хранения кодированных единиц кода UTF-16, используяcharнеоднозначно. Последний обычно хранит кодированные символы ANSI, но также может хранить ASCII, UTF-8 или даже двоичные данные.- мы не знаем кодировку символов (или даже тип символов)
CString(который управляется через_UNICODEсимвол препроцессора), что вопрос неоднозначный. Мы также не знаем желаемую кодировку символовstd::string.- преобразование между Unicode и ANSI по своей сути является потерями: кодировка ANSI может представлять только подмножество набора символов Unicode.
чтобы решить эти проблемы, я собираюсь предположить, что
wchar_tбудет хранить UTF-16 кодированных единиц кода, иcharбудет содержать последовательности октетов UTF-8. Это единственный разумный выбор, который вы можете сделать, чтобы гарантировать, что исходные и целевые строки сохраняют одну и ту же информацию, не ограничивая решение подмножеством исходных или целевых доменов.следующие реализации преобразуются между
CStringA/CStringWиstd::wstring/std::stringотображение из UTF-8 в UTF-16 и наоборот:#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 }; }оставшиеся две функции строят строковые объекты C++ из строк MFC, оставляя кодировку неизменной. Обратите внимание, что в то время как предыдущие функции не могут справиться со встроенными символами NUL, эти функции невосприимчивы к этому.
#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() }; }
если вы хотите легко конвертировать между другими типами строк, возможно,
_bstr_tкласс был бы более подходящим? Он поддерживает разговор междуchar,wchar_tиBSTR.
один интересный подход состоит в том, чтобы бросить
CStringtoCStringAвнутриstringконструктор. В отличие отstd::string s((LPCTSTR)cs);это будет работать даже если_UNICODEопределяется. Однако, если это так, это будет выполнять преобразование из Unicode в ANSI, поэтому это небезопасно для более высоких значений Unicode за пределами набора символов ASCII. Такое преобразование подлежит_CSTRING_DISABLE_NARROW_WIDE_CONVERSIONопределения препроцессора. https://msdn.microsoft.com/en-us/library/5bzxfsea.aspxCString s1("SomeString"); string s2((CStringA)s1);
Comments