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());
}
我是对的吗?
修改
以下是更多问题:
如何将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
互相转换?
答案 0 :(得分:84)
根据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
to CString
:(来自Visual Studio's CString FAQs...)
std::string s("Hello");
CString cs(s.c_str());
CStringT
可以从字符或宽字符串构造。即它可以从char*
(即LPSTR
)或wchar_t*
(LPWSTR
)转换。
换句话说,char-specialization(CStringT
)即CStringA
,wchar_t
- specilization CStringW
和TCHAR
- specialization {{1}可以从CString
或宽字符构造, null终止(此处为空终止非常重要)字符串源。
Althoug IInspectable修正了“无效终止”部分in the comments:
不需要NUL终止
char
具有采用显式长度参数的转换构造函数。这也意味着您可以使用嵌入了CStringT
个字符的CStringT
个对象构建std::string
个对象。
答案 1 :(得分:34)
使用std::basic_string<TCHAR>
代替std::string
来解决这个问题,无论你的角色设置如何,它都可以正常工作。
答案 2 :(得分:5)
使用指定长度的转化将CString
转换为std::string
效率更高。
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
在紧密循环中,这会显着提升性能。
答案 3 :(得分:4)
如果你想要更多类似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);
}
答案 4 :(得分:2)
(自VS2012起,至少直到VS2017 v15.8.1为止)
由于它是MFC项目,而CString是MFC类,因此MS提供了技术说明TN059: Using MFC MBCS/Unicode Conversion Macros和通用转换宏:
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
宏来完成的。在VS2017 MFC代码(atlconv.h)中,它看起来像这样:
#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
答案 5 :(得分:1)
这是Sal的回答,他/她提供了解决方案:
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
当将非典型的C-String转换为std :: string
时,这也很有用对我来说,一个用例是有一个预先分配的char数组(比如C-String),但它不是NUL终止的。 (即SHA摘要)。 上面的语法允许我指定char数组的SHA摘要的长度,这样std :: string就不必查找终止的NUL char,它可能存在也可能不存在。
如:
unsigned char hashResult[SHA_DIGEST_LENGTH];
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);
答案 6 :(得分:1)
这很好用:
//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
return CT2A(cst.GetString());
}
答案 7 :(得分:1)
此帖子的内容(谢谢Mark Ransom)
Convert CString to 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;
}
答案 8 :(得分:0)
适合我:
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();
}
答案 9 :(得分:0)
所有其他答案都没有完全解决我想要的问题,即动态转换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
。
答案 10 :(得分:0)
有任何问题吗?
有几个问题:
CString
是CStringT的模板专业化。根据描述字符类型的 BaseType ,有两个具体的专长:CStringA
(使用char
)和CStringW
(使用wchar_t
)。 wchar_t
普遍用于存储UTF-16编码的代码单元,但使用char
却模棱两可。后者通常存储ANSI编码的字符,但也可以存储ASCII,UTF-8甚至二进制数据。CString
的字符编码(甚至字符类型)(通过_UNICODE
预处理符号控制),这使问题变得模棱两可。我们还不知道std::string
所需的字符编码。为解决这些问题,我将假设wchar_t
将存储UTF-16编码的代码单元,而char
将保留UTF-8八位字节序列。这是确保源字符串和目标字符串保留相同信息而不会将解决方案限制到源域或目标域的子集的唯一合理选择。
以下实现从UTF-8映射到UTF-16,在CStringA
/ CStringW
和std::wstring
/ std::string
映射之间进行转换,反之亦然:
#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 };
}
其余两个函数从MFC字符串构造C ++字符串对象,而编码保持不变。请注意,尽管以前的功能无法应付嵌入的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() };
}
答案 11 :(得分:0)
您可以使用 CT2CA
CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);
答案 12 :(得分:0)
转换CString to std::string
。您可以使用这种格式。
std::string sText(CW2A(CSText.GetString(), CP_UTF8 ));
答案 13 :(得分:-1)
如果您希望在其他字符串类型之间轻松转换,那么_bstr_t
类可能更合适吗?它支持char
,wchar_t
和BSTR
之间的转换。
答案 14 :(得分:-1)
一种有趣的方法是在CString
构造函数中将CStringA
强制转换为string
。与std::string s((LPCTSTR)cs);
不同,即使定义了_UNICODE
,这也会有效。但是,如果是这种情况,这将执行从Unicode到ANSI的转换,因此对于ASCII字符集之外的更高Unicode值不安全。此类转换受_CSTRING_DISABLE_NARROW_WIDE_CONVERSION
预处理程序定义的约束。 https://msdn.microsoft.com/en-us/library/5bzxfsea.aspx
CString s1("SomeString");
string s2((CStringA)s1);
答案 15 :(得分:-1)
您可以将CString
随意投射到const char*
,然后将其分配给std::string
,如下所示:
CString cstring("MyCString");
std::string str = (const char*)cstring;