كيفية تحويل CString و ::std::string ::std::wstring بعضهم البعض ؟
سؤال
CString
هو مفيد جدا ، في حين std::string
هو أكثر توافقا مع المحكمة الخاصة بلبنان الحاوية.أنا باستخدام 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:
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
:(من Visual Studio CString أسئلة وأجوبة...)
std::string s("Hello");
CString cs(s.c_str());
CStringT
يمكن بناء من كل حرف أو واسعة سلاسل الأحرف.أيفإنه يمكن تحويل من char*
(أي LPSTR
) أو من wchar_t*
(LPWSTR
).
وبعبارة أخرى ، شار-التخصص (من CStringT
) أي CStringA
, wchar_t
-specilization CStringW
, ، TCHAR
-التخصص CString
يمكن بناؤها من أي char
أو واسعة الحرف ، null إنهاء (null-إنهاء مهم جدا هنا) سلسلة المصادر.
Althoug IInspectable يعدل "null-إنهاء" جزء في التعليقات:
NUL-إنهاء غير مطلوب.
CStringT
وقد التحويل المنشئات التي تأخذ صريح طول الحجة.وهذا يعني أيضا أنه يمكنك بناءCStringT
الكائنات منstd::string
الكائنات المضمنةNUL
الأحرف.
نصائح أخرى
حل هذه باستخدام std::basic_string<TCHAR>
بدلا من std::string
وينبغي أن تعمل بشكل جيد بغض النظر الطابع الخاص بك الإعداد.
هو أكثر كفاءة تحويل CString
إلى std::string
باستخدام التحويل حيث الطول المحدد.
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
في حلقة ضيقة وهذا يجعل مهمة تحسين الأداء.
إذا كنت تريد شيئا أكثر C++مثل هذا هو ما يمكنني استخدام.على الرغم من أنه يعتمد على تعزيز هذا مجرد استثناءات.يمكنك بسهولة إزالة تلك تاركة تعتمد فقط على المحكمة الخاصة بلبنان ، 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.ح) يبدو مثل هذا:
#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
هذا هو متابعة سال الجواب ، حيث انه/انها قدمت الحل:
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
وهذا مفيد أيضا عند تحويل غير نموذجي C-سلسلة إلى std::string
استخدام القضية بالنسبة لي وجود المخصص قبل char array (مثل C-String), لكنه لا NUL إنهاء.(أيإن شاء هضم).سبق جملة يسمح لي أن تحديد طول شاء هضم من شار مجموعة بحيث 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());
}
من هذا المنصب (شكرا لك مارك فدية )
لقد اختبرت هذا وأنه يعمل بشكل جيد.
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
ولكن لدي 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
على ويندوز والذي يستخدم لتخزين ترميز 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() };
}
يمكنك استخدام CT2CA
CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);
إذا كنت تبحث عن تحويل بسهولة بين السلاسل الأخرى أنواع ، ولعل _bstr_t
الفئة سيكون أكثر ملائمة ؟ وهو يدعم converstion بين char
, wchar_t
و BSTR
.
واحد النهج المثير للاهتمام هو أن يلقي CString
إلى 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);