CString es muy útil, mientras que std::string es más compatible con el contenedor STL.
Estoy usando hash_map. Sin embargo, hash_map no admite CString como clave, así que quiero convertir CString en std::string.

Escribir un CString función hash parece tener una gran cantidad de tiempo.

CString -----> std::string

¿Cómo puedo hacer esto?

std::string -----> CString:

inline CString toCString(std::string const& str)
{
    return CString(str.c_str()); 
}

Estoy en lo cierto?


EDICIÓN:

Aquí hay más preguntas:

¿Cómo puedo convertir wstring, CString el uno al otro?

//wstring -> CString,
std::wstring src;
CString result(src.c_str());
//CString->wstring. 
CString src;
::std::wstring des(src.GetString());

Hay cualquier problema?

¿Cómo puedo convertir std::wstring, std::string el uno al otro?

  • Yo no haría esto… el Uso de dos cuerdas diferentes tipos es bastante malo, pero tener que convertir cada vez que haces algo con un mapa? Suena terrible. Acaba de ser coherente y usar std::string. Si por alguna razón usted realmente piensa de CString es mejor, a continuación, defina una función hash, por lo que su hash_map puede utilizar, esto es mucho mejor que la duplicación de la confusión en el código.
  • En realidad, Si todo el código está escrito por mí será consistente, pero hay algunos opensourced proyecto, tales como los de freeimage sqlite utilizado. No puedo modificar allí código.
  • Me respondió un contemporáneo de respuesta (VS2017 MFC …Desde VS2012)
InformationsquelleAutor user25749 | 2008-11-03

14 Comentarios

  1. 85

    Según CodeGuru:

    CString a std::string:

    CString cs("Hello");
    std::string s((LPCTSTR)cs);

    PERO: std::string no siempre se puede construir a partir de un LPCTSTR. es decir, el código no funcionará para UNICODE generaciones.

    Como std::string puede construir sólo de LPSTR /LPCSTR, un programador que utiliza VC++ 7.x o mejor puede utilizar la conversión de las clases, tales como CT2CA como un intermediario.

    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 para CString: (De Visual Studio CString preguntas frecuentes…)

    std::string s("Hello");
    CString cs(s.c_str());

    CStringT puede construir a partir de caracteres o cadenas de caracteres anchos. Es decir, que se puede convertir de char* (es decir,LPSTR) o de wchar_t* (LPWSTR).

    En otras palabras, char-especialización (de CStringT), es decir,CStringA, wchar_t– specilization CStringW, y TCHAR-especialización CString puede ser construido a partir de cualquiera de char de caracteres anchos o, terminada en null (nulo de terminación es muy importante aquí) string fuentes.

    Pero IInspectable modifica el «nulo de terminación» parte en los comentarios:

    NUL-la terminación no es necesario.

    CStringT ha conversión de los constructores que tomar una longitud explícita argumento. Esto también significa que usted puede construir CStringT objetos de std::string objetos incrustados NUL caracteres.

    • Errr… eres bienvenido 🙂 Gracias a Siddhartha Rao por las explicaciones detalladas.
    • El último párrafo no es del todo correcto. NUL-terminación no es necesario. CStringT se ha conversión de los constructores que tomar una longitud explícita argumento. Esto también significa que usted puede construir CStringT objetos de std::string objetos incrustados NUL caracteres.
    • buen punto. He incluido tu comentario en la respuesta para obtener más visibilidad.
    • Pero la declaración fue muy útil para mí 😀
    • Esta respuesta es muy útil y explicativo, pero DO de la respuesta es una alternativa más sencilla.
  2. 34

    Resolver mediante el uso de std::basic_string<TCHAR> en lugar de std::string y debería funcionar bien, independientemente de su carácter configuración.

    • Este método es más simple
    • Me gusta typedef para la comodidad y la familiaridad: typedef std::basic_string<TCHAR> tstring
  3. 5

    Es más eficiente para convertir CString a std::string mediante la conversión de la longitud especificada.

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

    En apretado lazo esto hace que una mejora significativa del rendimiento.

    • Tengo un error al usar este: cannot convert parameter 1 from 'CString' to 'const std::basic_string<_Elem,_Traits,_Alloc> &'
  4. 4

    Si quieres algo más de C++como, esto es lo que yo uso. Aunque depende de Boost, que es sólo para las excepciones. Usted puede quitar fácilmente de aquellos dejando que sólo dependen de la STL y el WideCharToMultiByte() llamada de API de 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);
    }
    • El CW2AEX de la clase que hace todo esto para usted ya.
  5. 2

    (Desde VS2012 …y al menos hasta VS2017 v15.8.1)

    Ya que es un proyecto MFC & CString es una clase MFC, MS proporciona una Nota Técnica TN059: el Uso de MFC MBCS/Conversión de Unicode Macros y Genérico de Conversión de Macros:

    A2CW      (LPCSTR)  -> (LPCWSTR)  
    A2W       (LPCSTR)  -> (LPWSTR)  
    W2CA      (LPCWSTR) -> (LPCSTR)  
    W2A       (LPCWSTR) -> (LPSTR)  

    Uso:

    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" **
    }

    Notas a pie de página:

    (1) para la conversión de macros para tener espacio para almacenar el temporal de longitud, es necesario declarar una variable local llamada _convert que hace esto en cada función que utiliza la conversión de macros. Esto se realiza mediante la invocación de la USES_CONVERSION macro. En VS2017 código de MFC (atlconv.h) se parece a esto:

    #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
  6. 1

    Este es un seguimiento a la Sal de la respuesta, en la que él/ella proporciona la solución:

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

    Esto es útil cuando la conversión de un no-típico de C-String a un std::string

    Un caso de uso para mí fue tener un pre-asignados matriz de char (como el C-String), pero no NUL terminado. (es decir, SHA digerir).
    La sintaxis anterior me permite especificar la longitud de la SHA resumen de la matriz de char para que std::string no tiene que buscar la terminación NULL char, que puede o no puede estar allí.

    Tales como:

    unsigned char hashResult[SHA_DIGEST_LENGTH];    
    auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);
    • Tal vez, sería mejor si usted editado Sal de la respuesta con su enmienda adjunta o un comentario en Sal de la respuesta?
    • He intentado… pero stackoverflow no se me concedió la capacidad para hacer y editar.
  7. 1

    Esto funciona bien:

    //Convert CString to std::string
    inline std::string to_string(const CString& cst)
    {
        return CT2A(cst.GetString());
    }
  8. 0

    Me funciona:

    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();
    }
    • Las obras, hasta que se produce un error. WStringToCString se producirá por alguna de caracteres no-ASCII en la cadena de origen. CStringToWString se producirá por alguna de caracteres no-ASCII así, la producción no válido código UTF-16 unidades. Entiendo que esta solución sigue apareciendo cada vez, pero siempre ha sido malo, y seguirá siendo malo.
  9. 0

    Todas las otras respuestas no estaba a la dirección de lo que yo estaba buscando, que era convertir a CString sobre la marcha frente a almacenar el resultado en una variable.

    La solución es similar a la anterior pero necesitamos un paso más para crear una instancia de un objeto sin nombre. Estoy ilustrando con un ejemplo. Aquí está mi función de las necesidades de std::string pero tengo 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;
    }

    Cómo llamar cuando se tiene una CString?

    std::string firstName = "First";
    CString lastName = _T("Last");
    
    writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );     

    Nota de que la última línea no es un directo encasillado, pero estamos creando un sin nombre std::string objeto y el suministro de los CString a través de su constructor.

  10. 0

    Hay cualquier problema?

    Hay varias cuestiones:

    • CString es una especialización de plantilla de CStringT. Dependiendo de la BaseType que describe el tipo de carácter, hay dos especializaciones concretas: CStringA (utilizando char) y CStringW (utilizando wchar_t).
    • Mientras wchar_t en Windows se utiliza constantemente para almacenar codificación UTF-16 unidades de código, utilizando char es ambiguo. El último comúnmente tiendas ANSI caracteres codificados, pero también puede almacenar ASCII, UTF-8, o incluso de datos binarios.
    • No sabemos la codificación de caracteres (o incluso de tipo carácter) de CString (el cual es controlado a través de la _UNICODE símbolo de preprocesador), haciendo la pregunta ambigua. Tampoco sabemos el carácter deseado de la codificación de std::string.
    • Convertir entre Unicode y ANSI es intrínsecamente con pérdida: la codificación ANSI sólo puede representar un subconjunto del conjunto de caracteres Unicode.

    Para abordar estas cuestiones, voy a asumir que wchar_t almacenará la codificación UTF-16 unidades de código, y char celebrará UTF-8 octeto secuencias. Esa es la única opción razonable que usted puede hacer para asegurarse de que la fuente y el destino cadenas de conservar la misma información, sin perjuicio de la solución a un subconjunto de la fuente o el destino de los dominios.

    Las siguientes implementaciones convertir entre CStringA/CStringW y std::wstring/std::string asignación de la codificación UTF-8, UTF-16 y viceversa:

    #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 };
    }

    Los dos restantes funciones de construcción C++ objetos de cadena de MFC cadenas, dejando la codificación sin cambios. Tenga en cuenta que mientras que las funciones anteriores, no puede hacer frente con la inserción de caracteres NUL, estas funciones son inmunes a eso.

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

    Si usted está buscando para convertir fácilmente entre otras cadenas de tipos, tal vez el _bstr_t clase sería más apropiado? Es compatible con converstion entre char, wchar_t y BSTR.

    • -1 CString ya no todas las conversiones que nombre. Y lo hizo hace 3 años así. No hay punto en el que sugiere un tipo que está destinado para su uso en COM entornos.
  12. -1

    Una aproximación interesante es que dejen de CString a CStringA dentro de un string constructor. A diferencia de std::string s((LPCTSTR)cs); esto funcionará incluso si _UNICODE está definido. Sin embargo, si ese es el caso, esto va a llevar a cabo la conversión de Unicode a ANSI, por lo que no es seguro para los más altos valores Unicode más allá del conjunto de caracteres ASCII. Esta conversión está sujeto a la _CSTRING_DISABLE_NARROW_WIDE_CONVERSION definición de preprocesador. https://msdn.microsoft.com/en-us/library/5bzxfsea.aspx

            CString s1("SomeString");
            string s2((CStringA)s1);
    • Eso no es un yeso. Es una conversión. CString ha de conversión de constructores, mediante el subproceso de llamada de la configuración regional actual. La conversión es con pérdidas, y puede que la ventana con una cuerda que ya no representa la fuente. Sí, es fácil, cómodo. Pero también mal.
    • es un yeso en el sentido de que es una conversión explícita. Es que la parte que se considere mal aquí? Si esto funciona en casos de uso específicos, lo que se hace, entonces, por definición, no puede ser malo para los casos de uso. Si es fácil y conveniente, entonces mejor que mejor. Entonces estás diciendo que la conversión de CString a CStringA no siempre es confiable debido a la configuración regional correcta? Yo pedí específicamente que «¿por qué no…» sospechar como mucho, y me interesa si usted puede proporcionar más detalles. Voy a actualizar de acuerdo, pero habría que llamar a este enfoque equivocado tan larga como las limitaciones se entiende?
    • La configuración regional de un limitación. El más fatal de un ser, que la codificación ANSI no puede representar todos los puntos de código disponible en la especificación Unicode. Que la conversión es la pérdida de información. Inevitablemente, vamos a perder la información. La definición de la _CSTRING_DISABLE_NARROW_WIDE_CONVERSION símbolo de preprocesador es la opción segura: será causa de esta propuesta de solución a un error de compilación. Esta solución no es segura, incluso si todas las limitaciones se entiende, ya que no hay forma de hacer cumplir los requisitos.

Dejar respuesta

Please enter your comment!
Please enter your name here