2008-11-03 3 views
63

CString весьма удобен, а std::string более совместим с контейнером STL. Я использую hash_map. Однако hash_map не поддерживает CString как ключ, поэтому я хочу преобразовать CString в std::string.Как конвертировать CString и :: std :: string :: std :: wstring друг к другу?

Написание функции хеша 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 друг другу?

+3

Я бы этого не сделал ... Использование двух разных типов строк достаточно плохо, но нужно конвертировать каждый раз, когда вы что-то делаете с картой? Звучит ужасно. Просто будьте последовательны и используйте std :: string. Если по какой-то причине вы действительно думаете, что CString лучше, то определите хеш-функцию для него, чтобы ваш hash_map мог ее использовать, это намного лучше, чем удвоение запутанности в вашем коде. – GManNickG 2009-07-12 15:13:56

+2

На самом деле, если весь код написан сам, он будет последовательным, но есть некоторые проекты с открытым доступом, такие как freeimage sqlite. Я не могу изменить код. – user25749 2009-07-13 01:21:44

ответ

78

По 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).

Другими словами, углеродно специализации (из CStringT), т.е. CStringA, wchar_t -specilization CStringW и TCHAR -specialization CString могут быть построены либо из char или широкого характера, нулем (нуль-терминации очень важно здесь) Источники строк.
Althoug IInspectable вносит изменения в "нулевое окончание" часть in the comments:

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

+2

Errr ... приветствую :) Спасибо Сиддхартхе Рао за подробные объяснения. – VonC 2008-11-03 07:15:26

+0

Последний абзац не совсем корректен. `NUL`-term не требуется. [`CStringT`] (http://msdn.microsoft.com/en-us/library/cws1zdt8.aspx) имеет конструкторы преобразования, которые принимают аргумент длины длины. Это также означает, что вы можете создавать объекты `CStringT` из объектов` std :: string` со встроенными символами 'NUL`. – IInspectable 2013-10-28 20:25:16

+0

@ Отличная хорошая точка. Я включил ваш комментарий в ответ для большей наглядности. – VonC 2013-10-29 06:43:58

33

Решите, что с помощью std::basic_string<TCHAR> вместо std::string и он должен работать нормально, независимо от настройки вашего персонажа.

-1

Если вы хотите легко конвертировать между другими типами строк, возможно, класс _bstr_t будет более уместным? Он поддерживает конверсию между char, wchar_t и BSTR.

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

Это более эффективно для преобразования CString в std::string используя преобразование, где указанная длина.

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

В плотной петле это обеспечивает значительное улучшение производительности.

1

работает для меня:

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

Это следовать до ответа Сал, где он/она обеспечила решение:

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

Это полезно также при преобразовании нетипичного C -String to std :: string

В случае использования у меня был предварительно выделенный массив символов (например, C-String), но он не был завершен NUL. (т. е. переваривание SHA). В приведенном выше синтаксисе я могу указать длину дайджест SHA массива char, так что std :: string не нужно искать завершающий символ NUL, который может быть или не быть.

Такие, как:

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

Это прекрасно работает:

//Convert CString to std::string 
inline std::string to_string(const CString& cst) 
{ 
    return CT2A(cst.GetString()); 
} 
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 через конструктор.

0

Почему бы не просто отличить из CString в CStringA внутри a string конструктор?

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