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 对彼此?

有帮助吗?

解决方案

根据 CodeGuru

CStringstd::string

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

LPCTSTR无法始终从LPSTR构建。即UNICODE版本的代码将失败。

由于LPCSTR只能从CT2CA / CStringT构造,使用VC ++ 7.x或更高版本的程序员可以使用char*等转换类作为中介。

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

wchar_t* to LPWSTR :(来自 Visual Studio的CString常见问题解答。 ..

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

CStringA可以从字符或宽字符串构造。即它可以从wchar_t(即CStringW)或TCHARchar)转换。

换句话说,char-specialization(NUL)即<=>,<=> - specilization <=>,<=> - specialization <=>可以从<=>或wide-构建character, null终止(null-termination在这里非常重要)字符串源。
Althoug IInspectable 修正了<!> quot; null-termination <!>;部分在评论中

  

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

其他提示

使用std::basic_string<TCHAR>代替std::string来解决这个问题,无论你的角色设置如何,它都应该可以正常工作。

使用指定长度的转换将CString转换为std::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);
}

(自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

这是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);

这很好用:

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

来自这篇文章(谢谢 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;
}

适合我:

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但我有<=>。

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

如果有<=>?

,如何调用它
std::string firstName = "First";
CString lastName = _T("Last");

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

请注意,最后一行不是直接类型转换,但我们正在创建一个无名的<=>对象,并通过其构造函数提供<=>。

有没有 任何 问题?

有几个问题:

  • CString 是一个模板特化 CStringT. 。取决于 基本类型 描述字符类型,有两个具体的专业化: 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/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() };
}

您可以使用 CT2CA

CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);

如果你想在其他字符串类型之间轻松转换,可能是 _bstr_t 类会更合适吗?它支持charwchar_tBSTR之间的转换。

一种有趣的方法是将CString转换为CStringAstring构造函数中。与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);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top