كيفية تحويل CString و ::std::string ::std::wstring بعضهم البعض ؟

StackOverflow https://stackoverflow.com/questions/258050

  •  06-07-2019
  •  | 
  •  

سؤال

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

من هذا المنصب (شكرا لك مارك فدية )

تحويل 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 ولكن لدي 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);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top