如何转换CString和::std:: std::wstring对彼此?

时间:2021-05-09 20:18:37

CString is quite handy, while std::string is more compatible with STL container. I am using hash_map. However, hash_map does not support CString as key, so I want to convert CString into std::string.

CString很方便,而std::string更适合STL容器。我用hash_map。然而,hash_map不支持CString作为键,所以我想将CString转换为std::string。

Writing a CString hash function seems to take a lot of time.

编写一个CString散列函数似乎要花很多时间。

CString -----> std::string

How can I do this?

我该怎么做呢?

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

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

Am I right?

我说的对吗?


EDIT:

编辑:

Here are more questions:

这里有更多的问题:

How can I convert wstring, CString to each other?

如何将wstring和CString相互转换?

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

Is there any problem?

有任何问题吗?

How can I convert std::wstring, std::string to each other?

如何转换std::wstring, std::string to each other?

10 个解决方案

#1


79  

According to CodeGuru:

根据CodeGuru:

CString to std::string:

装运箱std::string:

CString cs("Hello");
std::string s((LPCTSTR)cs);

BUT: std::string cannot always construct from a LPCTSTR. i.e. the code will fail for UNICODE builds.

但是:std: string不能总是从LPCTSTR构造。例如,UNICODE版本的代码将会失败。

As std::string can construct only from LPSTR / LPCSTR, a programmer who uses VC++ 7.x or better can utilize conversion classes such as CT2CA as an intermediary.

作为std::string只能从使用vc++ 7的程序员LPSTR / LPCSTR构造。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: (From Visual Studio's CString FAQs...)

从字符串到CString:(来自Visual Studio的CString FAQs…)

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

CStringT can construct from both character or wide-character strings. i.e. It can convert from char* (i.e. LPSTR) or from wchar_t* (LPWSTR).

CStringT可以从字符或宽字符字符串构造。例如,它可以从char*(即LPSTR)或wchar_t*(即LPWSTR)进行转换。

In other words, char-specialization (of CStringT) i.e. CStringA, wchar_t-specilization CStringW, and TCHAR-specialization CString can be constructed from either char or wide-character, null terminated (null-termination is very important here) string sources.
Althoug IInspectable amends the "null-termination" part in the comments:

换句话说,charc -特殊化(CStringT)也就是CStringA, wchar_t-特殊化CStringW和tcharc -特殊化CString可以从char或宽字符构造,空终止(null termination在这里非常重要)字符串源。Althoug IInspectable修改了注释中的“空终止”部分:

NUL-termination is not required.
CStringT has conversion constructors that take an explicit length argument. This also means that you can construct CStringT objects from std::string objects with embedded NUL characters.

NUL-termination不是必需的。CStringT具有接受显式长度参数的转换构造函数。这也意味着您可以从std::string对象中构造带有嵌入NUL字符的CStringT对象。

#2


33  

Solve that by using std::basic_string<TCHAR> instead of std::string and it should work fine regardless of your character setting.

通过使用std::basic_string 而不是std::string,它应该可以正常工作,无论您的角色设置如何。

#3


5  

It is more effecient to convert CString to std::string using the conversion where the length is specified.

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

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

In tight loop this makes a significant performance improvement.

在紧密循环中,这将显著提高性能。

#4


4  

If you want something more C++-like, this is what I use. Although it depends on Boost, that's just for exceptions. You can easily remove those leaving it to depend only on the STL and the WideCharToMultiByte() Win32 API call.

如果你想要更像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);
}

#5


1  

Works for me:

工作对我来说:

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();
}

#6


1  

This is a follow up to Sal's answer, where he/she provided the solution:

这是萨尔的回答的后续,他/她提供了解决方案:

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

This is useful also when converting a non-typical C-String to a std::string

这在将非典型的C-String转换为std::string时也很有用

A use case for me was having a pre-allocated char array (like C-String), but it's not NUL terminated. (i.e. SHA digest). The above syntax allows me to specify the length of the SHA digest of the char array so that std::string doesn't have to look for the terminating NUL char, which may or may not be there.

我的一个用例是有一个预先分配的char数组(如C-String),但是它不是NUL终止的。(即沙消化)。上面的语法允许我指定char数组的SHA摘要的长度,这样std::string就不必寻找终止的NUL char,它可能存在也可能不存在。

Such as:

如:

unsigned char hashResult[SHA_DIGEST_LENGTH];    
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);

#7


1  

This works fine:

这工作正常:

//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
    return CT2A(cst.GetString());
}

#8


0  

All other answers didn't quite address what I was looking for which was to convert CString on the fly as opposed to store the result in a variable.

所有其他答案都没有很好地说明我要寻找的是动态转换CString,而不是将结果存储在变量中。

The solution is similar to above but we need one more step to instantiate a nameless object. I am illustrating with an example. Here is my function which needs std::string but I have 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;
}

How to call it when you have a CString?

当你有一个CString时如何调用它?

std::string firstName = "First";
CString lastName = _T("Last");

writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );     

Note that the last line is not a direct typecast but we are creating a nameless std::string object and supply the CString via its constructor.

注意,最后一行不是直接的类型转换,但是我们正在创建一个无名的std::string对象,并通过它的构造函数提供CString。

#9


0  

Why not just cast from CString to CStringA inside a string constructor?

为什么不直接在字符串构造函数中从CString转换到CStringA呢?

        CString s1("SomeString");
        string s2((CStringA)s1);

#10


-1  

If you're looking to convert easily between other strings types, perhaps the _bstr_t class would be more appropriate? It supports converstion between char, wchar_t and BSTR.

如果您希望在其他字符串类型之间轻松地进行转换,那么应该使用_bstr_t类?它支持char、wchar_t和BSTR之间的对话。

#1


79  

According to CodeGuru:

根据CodeGuru:

CString to std::string:

装运箱std::string:

CString cs("Hello");
std::string s((LPCTSTR)cs);

BUT: std::string cannot always construct from a LPCTSTR. i.e. the code will fail for UNICODE builds.

但是:std: string不能总是从LPCTSTR构造。例如,UNICODE版本的代码将会失败。

As std::string can construct only from LPSTR / LPCSTR, a programmer who uses VC++ 7.x or better can utilize conversion classes such as CT2CA as an intermediary.

作为std::string只能从使用vc++ 7的程序员LPSTR / LPCSTR构造。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: (From Visual Studio's CString FAQs...)

从字符串到CString:(来自Visual Studio的CString FAQs…)

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

CStringT can construct from both character or wide-character strings. i.e. It can convert from char* (i.e. LPSTR) or from wchar_t* (LPWSTR).

CStringT可以从字符或宽字符字符串构造。例如,它可以从char*(即LPSTR)或wchar_t*(即LPWSTR)进行转换。

In other words, char-specialization (of CStringT) i.e. CStringA, wchar_t-specilization CStringW, and TCHAR-specialization CString can be constructed from either char or wide-character, null terminated (null-termination is very important here) string sources.
Althoug IInspectable amends the "null-termination" part in the comments:

换句话说,charc -特殊化(CStringT)也就是CStringA, wchar_t-特殊化CStringW和tcharc -特殊化CString可以从char或宽字符构造,空终止(null termination在这里非常重要)字符串源。Althoug IInspectable修改了注释中的“空终止”部分:

NUL-termination is not required.
CStringT has conversion constructors that take an explicit length argument. This also means that you can construct CStringT objects from std::string objects with embedded NUL characters.

NUL-termination不是必需的。CStringT具有接受显式长度参数的转换构造函数。这也意味着您可以从std::string对象中构造带有嵌入NUL字符的CStringT对象。

#2


33  

Solve that by using std::basic_string<TCHAR> instead of std::string and it should work fine regardless of your character setting.

通过使用std::basic_string 而不是std::string,它应该可以正常工作,无论您的角色设置如何。

#3


5  

It is more effecient to convert CString to std::string using the conversion where the length is specified.

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

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

In tight loop this makes a significant performance improvement.

在紧密循环中,这将显著提高性能。

#4


4  

If you want something more C++-like, this is what I use. Although it depends on Boost, that's just for exceptions. You can easily remove those leaving it to depend only on the STL and the WideCharToMultiByte() Win32 API call.

如果你想要更像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);
}

#5


1  

Works for me:

工作对我来说:

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();
}

#6


1  

This is a follow up to Sal's answer, where he/she provided the solution:

这是萨尔的回答的后续,他/她提供了解决方案:

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

This is useful also when converting a non-typical C-String to a std::string

这在将非典型的C-String转换为std::string时也很有用

A use case for me was having a pre-allocated char array (like C-String), but it's not NUL terminated. (i.e. SHA digest). The above syntax allows me to specify the length of the SHA digest of the char array so that std::string doesn't have to look for the terminating NUL char, which may or may not be there.

我的一个用例是有一个预先分配的char数组(如C-String),但是它不是NUL终止的。(即沙消化)。上面的语法允许我指定char数组的SHA摘要的长度,这样std::string就不必寻找终止的NUL char,它可能存在也可能不存在。

Such as:

如:

unsigned char hashResult[SHA_DIGEST_LENGTH];    
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);

#7


1  

This works fine:

这工作正常:

//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
    return CT2A(cst.GetString());
}

#8


0  

All other answers didn't quite address what I was looking for which was to convert CString on the fly as opposed to store the result in a variable.

所有其他答案都没有很好地说明我要寻找的是动态转换CString,而不是将结果存储在变量中。

The solution is similar to above but we need one more step to instantiate a nameless object. I am illustrating with an example. Here is my function which needs std::string but I have 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;
}

How to call it when you have a CString?

当你有一个CString时如何调用它?

std::string firstName = "First";
CString lastName = _T("Last");

writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );     

Note that the last line is not a direct typecast but we are creating a nameless std::string object and supply the CString via its constructor.

注意,最后一行不是直接的类型转换,但是我们正在创建一个无名的std::string对象,并通过它的构造函数提供CString。

#9


0  

Why not just cast from CString to CStringA inside a string constructor?

为什么不直接在字符串构造函数中从CString转换到CStringA呢?

        CString s1("SomeString");
        string s2((CStringA)s1);

#10


-1  

If you're looking to convert easily between other strings types, perhaps the _bstr_t class would be more appropriate? It supports converstion between char, wchar_t and BSTR.

如果您希望在其他字符串类型之间轻松地进行转换,那么应该使用_bstr_t类?它支持char、wchar_t和BSTR之间的对话。