Как преобразовать 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 друг с другом?

1349   13  

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-specilization CStringW и TCHARспециализации CString может быть построен из любого char или расширенных символов, значение null (нулевое завершение очень важно здесь) строке источников.
Хотя IInspectable вносит изменения в часть "null-termination"в комментариях:

NUL-завершение не требуется.
CStringT имеет конструкторы преобразования, которые принимают явный аргумент длины. Это также означает, что вы можете построить CStringT объекты std::string объекты со встроенными NUL символы.

решить эту проблему с помощью std::basic_string<TCHAR> вместо std::string и он должен работать нормально вне зависимости от параметров персонажа.

более эффективно конвертировать CString to 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);
}

Это продолжение ответа Сэла, где он / она предоставил решение:

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.

один интересный подход состоит в том, чтобы бросить CString to CStringA внутри string конструктор. В отличие от std::string s((LPCTSTR)cs); это будет работать даже если _UNICODE определяется. Однако, если это так, это будет выполнять преобразование из Unicode в ANSI, поэтому это небезопасно для более высоких значений Unicode за пределами набора символов ASCII. Такое преобразование подлежит _CSTRING_DISABLE_NARROW_WIDE_CONVERSION определения препроцессора. https://msdn.microsoft.com/en-us/library/5bzxfsea.aspx

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

Comments

    Ничего не найдено.