81

CString非常方便,同时std::string更兼容 STL 容器。我正在使用hash_map. 但是,hash_map不支持CStrings 作为键,所以我想将 s 转换CStringstd::string.

编写CString散列函数似乎需要很多时间。

CString -----> std::string

我怎样才能做到这一点?

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

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

我对吗?


编辑:

这里有更多问题:

我怎样才能从wstringto转换,CString反之亦然?

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

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

这有什么问题吗?

此外,我怎样才能从std::wstringto转换,std::string反之亦然?

4

16 回答 16

100

根据CodeGuru

CStringstd::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::stringCString:(来自Visual Studio 的 CString 常见问题解答...

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

CStringT可以从字符或宽字符串构造。ie 它可以从char*(ie LPSTR) 或wchar_t*( LPWSTR) 转换。

换句话说, char-specialization (of CStringT) 即CStringA-specilization和wchar_t-specialization可以由任一字符或宽字符构成,CStringWTCHARCStringchar空终止(空终止在这里非常重要)字符串来源。
Althoug IInspectable修改了评论中的“null-termination”部分:

不需要 NUL 终止
CStringT具有采用显式长度参数的转换构造函数。这也意味着您可以从具有嵌入字符CStringT的对象构造对象。std::stringNUL

于 2008-11-03T07:05:03.017 回答
36

通过使用std::basic_string<TCHAR>而不是解决这个问题,std::string无论您的角色设置如何,它都应该可以正常工作。

于 2008-11-03T09:36:36.503 回答
6

CString转换为std::string使用指定长度的转换更有效。

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

在一个紧密的循环中,这会显着提高性能。

于 2011-06-03T13:49:14.753 回答
5

如果你想要更多类似 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);
}
于 2009-07-12T15:05:24.737 回答
4

什么问题吗?

有几个问题:

  • CStringCStringT的模板特化。根据描述字符类型的BaseType,有两种具体的特化:CStringA(using char) 和CStringW(using 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/CStringWstd::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 };
}

其余两个函数从 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() };
}
于 2018-09-06T10:07:43.293 回答
3

(从 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宏来完成的。在 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
于 2018-08-21T09:14:40.077 回答
2

这工作正常:

//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
    return CT2A(cst.GetString());
}
于 2017-01-21T23:17:00.963 回答
2

转换CString to std::string。您可以使用这种格式。

std::string sText(CW2A(CSText.GetString(), CP_UTF8 ));
于 2019-10-24T04:51:55.817 回答
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);
于 2016-03-10T19:04:21.087 回答
1

来自这篇文章(谢谢Mark Ransom

将 CString 转换为字符串 (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;
}
于 2018-08-21T08:55:32.547 回答
1

您可以使用CT2CA

CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);
于 2019-04-19T17:31:11.603 回答
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();
}
于 2015-11-10T10:10:29.807 回答
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通过其构造函数提供。

于 2017-06-29T21:15:37.527 回答
0

CString如果您使用的是 Unicode,则具有GetString()返回类型的方法,否则。LPCWSTRLPCSTR

在 Unicode 情况下,您必须通过 a 传递它wstring

CString cs("Hello");
wstring ws = wstring(cs.GetString());
string s = string(ws.begin(), ws.end());

否则,您可以直接转换字符串:

CString cs("Hello");
string s = string(cs.GetString());
于 2021-09-22T13:23:25.877 回答
-1

如果您希望在其他字符串类型之间轻松转换,那么_bstr_t该类可能更合适?它支持char,wchar_t和之间的转换BSTR

于 2009-02-20T09:28:20.363 回答
-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);
于 2017-10-17T19:58:20.967 回答