Jak przekonwertować CString i: std:: string: std:: wstring na siebie?
CString
jest bardzo poręczny, natomiast {[4] } jest bardziej kompatybilny z kontenerem STL.
Używam hash_map
. Jednak hash_map
nie obsługuje CString
jako klucza, więc chcę przekonwertować CString
na std::string
.
Napisanie CString
funkcji hash zajmuje dużo czasu.
CString -----> std::string
Jak mogę to zrobić?
std::string -----> CString:
inline CString toCString(std::string const& str)
{
return CString(str.c_str());
}
Mam rację?
EDIT:
Oto kolejne pytania:
Jak mogę przekonwertować wstring
, CString
do siebie?
//wstring -> CString,
std::wstring src;
CString result(src.c_str());
//CString->wstring.
CString src;
::std::wstring des(src.GetString());
Jest Jakiś problem?
Jak mogę przekonwertować std::wstring
, std::string
do siebie?
13 answers
Według CodeGuru :
CString
do std::string
:
CString cs("Hello");
std::string s((LPCTSTR)cs);
Ale: std::string
nie zawsze można konstruować z LPCTSTR
. tzn. kod nie powiedzie się dla kompilacji UNICODE.
Jako {[4] } można konstruować tylko z LPSTR
/ LPCSTR
, programista korzystający z VC++ 7.x lub lepiej może używać klas konwersji, takich jak CT2CA
jako pośrednika.
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
na CString
: (od Visual Studio ' S Cstrring FAQs...)
std::string s("Hello");
CString cs(s.c_str());
CStringT
can konstruuj z łańcuchów znaków lub szerokich znaków. tzn. może konwertować z char*
(tzn. LPSTR
) lub z wchar_t*
(LPWSTR
).
Innymi słowy, char-specjalizacja (z CStringT
), czyli CStringA
, wchar_t
-specilization CStringW
i TCHAR
-specialization CString
mogą być skonstruowane z char
lub szerokiego znaku, zakończonego znakiem null (zakończenie null jest tutaj bardzo ważne) źródeł łańcuchów.
Althoug IInspectable zmienia część " null-termination "W komentarze :
Nul-wypowiedzenie nie jest wymagane .
CStringT
ma konstruktory konwersji, które przyjmują jawny argument długości. Oznacza to również, że można konstruować obiektyCStringT
z obiektówstd::string
z osadzonymi znakamiNUL
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:25
Rozwiąż to używając std::basic_string<TCHAR>
zamiast std::string
i powinno działać dobrze niezależnie od ustawienia postaci.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 09:36:36
Bardziej efektywna jest konwersja CString
na std::string
przy użyciu konwersji, w której określona jest długość.
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
W ciasnej pętli powoduje to znaczną poprawę wydajności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-09 18:19:15
Jeśli chcesz coś bardziej C++ - like, to jest to, co używam. Chociaż zależy to od wzmocnienia, to tylko dla WYJĄTKÓW. Możesz łatwo usunąć te, które pozostawiają go w zależności tylko od STL i wywołania API WideCharToMultiByte()
Win32.
#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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-15 07:42:50
Jest to kontynuacja odpowiedzi Sal, w której podał rozwiązanie:]}
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
Jest to przydatne również podczas konwersji nietypowego ciągu C na std:: string
Przypadek użycia dla mnie miał wstępnie przydzieloną tablicę znaków( jak łańcuch C), ale nie jest zakończony znakiem NUL. (tj. SHA digest). Powyższa składnia pozwala mi określić długość skrótu SHA tablicy znaków, aby std:: string nie musiał szukać kończącego znaku NUL, który może być lub nie tam.
Takie jak:
unsigned char hashResult[SHA_DIGEST_LENGTH];
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-10 19:04:21
To działa dobrze:
//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
return CT2A(cst.GetString());
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-05 21:28:36
From this post (Thank you Mark Ransom )
Convert CString to string (VC6)
Przetestowałem to i działa dobrze.
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-21 08:55:32
(od VS2012 ...i przynajmniej do VS2017 v15. 8. 1)
Ponieważ jest to projekt MFC, a CString jest klasą MFC, MS dostarcza notatkę techniczną TN059: używanie makr konwersji MFC MBCS/Unicode i ogólnych makr konwersji:A2CW (LPCSTR) -> (LPCWSTR)
A2W (LPCSTR) -> (LPWSTR)
W2CA (LPCWSTR) -> (LPCSTR)
W2A (LPCWSTR) -> (LPSTR)
Użycie:
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" **
}
--
Przypisy:
(1) aby makra conversion-miały przestrzeń do przechowywania tymczasowej długości, konieczne jest zadeklarowanie zmiennej lokalnej o nazwie _convert
, która robi to w każdej funkcji, która wykorzystuje makra konwersji. Odbywa się to poprzez wywołanie makra USES_CONVERSION
. W kodzie VS2017 MFC (atlconv.h) wygląda tak:
#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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-21 11:28:38
Działa dla mnie:
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();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 10:10:29
Wszystkie inne odpowiedzi nie do końca odnosiły się do tego, czego szukałem, czyli do konwersji CString
w locie, a nie do przechowywania wyniku w zmiennej.
Rozwiązanie jest podobne do powyższego, ale potrzebujemy jeszcze jednego kroku, aby utworzyć instancję bezimiennego obiektu. Ilustruję przykładem. Oto moja funkcja, która potrzebuje std::string
, ale mam 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;
}
Jak to nazwać, gdy masz CString
?
std::string firstName = "First";
CString lastName = _T("Last");
writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );
Zauważ, że ostatnia linia nie jest typem bezpośrednim, ale tworzymy obiekt bezimienny std::string
i dostarcza CString
poprzez jego konstruktor.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-29 21:15:37
Czy jest jakiś problem?
Istnieje kilka kwestii:
-
CString
jest specjalizacją szablonu CStringT. W zależności od typu podstawowego opisującego typ znaku, istnieją dwie konkretne specjalizacje:CStringA
(za pomocąchar
) iCStringW
(za pomocąwchar_t
). - podczas gdy
wchar_t
w systemie Windows jest powszechnie używany do przechowywania jednostek kodowanych UTF-16, użyciechar
jest niejednoznaczne. Ten ostatni zwykle przechowuje kodowane ANSI znaków, ale może również przechowywać dane ASCII, UTF-8, a nawet binarne. - nie znamy kodowania znaków (ani nawet typu znaków)
CString
(które jest kontrolowane przez symbol preprocesora_UNICODE
), co sprawia, że pytanie jest niejednoznaczne. Nie znamy również pożądanego kodowania znakówstd::string
. - konwersja pomiędzy Unicode i ANSI jest z natury stratna: kodowanie ANSI może reprezentować tylko podzbiór zestawu znaków Unicode.
Aby rozwiązać te problemy, idę założenie, że wchar_t
będzie przechowywać jednostki kodowane UTF-16, A char
będzie przechowywać sekwencje oktetów UTF-8. Jest to jedyny rozsądny wybór, jaki można podjąć, aby zapewnić, że ciągi źródłowe i docelowe zachowują te same informacje, bez ograniczania rozwiązania do podzbioru domen źródłowych lub docelowych.
Następujące implementacje konwertują między CStringA
/CStringW
oraz std::wstring
/std::string
W przypadku UTF-8 do UTF-16 i odwrotnie:
#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 };
}
Pozostałe dwie funkcje konstruują C++ string objects from MFC strings, pozostawiając kodowanie bez zmian. Zauważ, że podczas gdy poprzednie funkcje nie radzą sobie z osadzonymi znakami NUL, funkcje te są na to Odporne.
#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() };
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 10:07:43
Jeśli chcesz łatwo konwertować między innymi typami łańcuchów, być może _bstr_t
zajęcia byłyby bardziej odpowiednie? Obsługuje konwersację pomiędzy char
, wchar_t
i BSTR
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-15 07:43:15
Ciekawym podejściem jest rzut CString
do CStringA
wewnątrz konstruktora string
. W przeciwieństwie do std::string s((LPCTSTR)cs);
to zadziała nawet jeśli _UNICODE
jest zdefiniowane. Jeśli jednak tak się stanie, spowoduje to konwersję z Unicode do ANSI, więc jest to niebezpieczne dla wyższych wartości Unicode poza zestawem znaków ASCII. Taka konwersja podlega definicji preprocesora _CSTRING_DISABLE_NARROW_WIDE_CONVERSION
. https://msdn.microsoft.com/en-us/library/5bzxfsea.aspx
CString s1("SomeString");
string s2((CStringA)s1);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 20:20:06