Pregunta

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 apoyo CString como clave, así que quiero convertir CString en std::string.

La escritura de un CString la función de 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?


EDITAR:

Aquí hay más preguntas:

¿Cómo puedo convertir wstring, CString para cada uno de los otros?

//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 para cada uno de los otros?

¿Fue útil?

Solución

De acuerdo a CodeGuru :

CString a std::string:

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

PERO: LPCTSTR no siempre se puede construir a partir de un LPSTR. es decir, el código fallará para las compilaciones de UNICODE.

Como LPCSTR solo puede construir a partir de CT2CA / CStringT, un programador que usa VC ++ 7.xo mejor puede utilizar clases de conversión como char* como 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);

wchar_t* a LPWSTR : (De Preguntas frecuentes sobre CString de Visual Studio. .. )

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

CStringA puede construir a partir de cadenas de caracteres o de caracteres anchos. es decir, puede convertir desde wchar_t (es decir, CStringW) o desde TCHAR (char).

En otras palabras, la especialización de caracteres (de NUL) es decir, <=>, <=> - especialización <=>, y <=> - especialización <=> puede construirse a partir de <=> o wide- carácter, nulo terminado (la terminación nula es muy importante aquí) fuentes de cadena.
Si bien IInspectable modifica la & Quot; terminación nula & Quot; parte en los comentarios :

  

No se requiere terminación NUL .
  <=> tiene constructores de conversión que toman un argumento de longitud explícita. Esto también significa que puede construir <=> objetos a partir de <=> objetos con <=> caracteres incrustados.

Otros consejos

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.

Es más eficiente convertir CString a std::string usando la conversión donde se especifica la longitud.

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

En un ciclo cerrado, esto mejora significativamente el rendimiento.

Si quieres algo más parecido a C ++, esto es lo que uso. Aunque depende de Boost, eso es solo para excepciones. Puede eliminar fácilmente aquellos que lo dejan para depender solo del STL y la WideCharToMultiByte() llamada a la API 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);
}

(desde VS2012 ... y al menos hasta VS2017 v15.8.1)

Dado que es un proyecto MFC & amp; CString es una clase MFC, MS proporciona una Nota técnica TN059: Uso de MFC MBCS / Unicode Macros de conversión y Macros de conversión genérica:

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 al pie:

(1) Para que las macros de conversión tengan espacio para almacenar la longitud temporal, es necesario declarar una variable local llamada _convert que hace esto en cada función que usa las macros de conversión. Esto se hace invocando la macro USES_CONVERSION. En el código MFC VS2017 (atlconv.h) se ve así:

#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

Esta es una continuación de la respuesta de Sal, donde él / ella proporcionó la solución:

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

Esto también es útil cuando se convierte una C-String no típica a std :: string

Un caso de uso para mí fue tener una matriz de caracteres preasignada (como C-String), pero no está terminada en NUL. (es decir, resumen de SHA). La sintaxis anterior me permite especificar la longitud del resumen SHA de la matriz de caracteres para que std :: string no tenga que buscar el carácter NUL de terminación, que puede o no estar allí.

Tales como:

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

Esto funciona bien:

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

de esta publicación (Gracias Mark Ransom )

Convertir CString en cadena (VC6)

He probado esto y funciona bien.

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

Funciona para mí:

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

Todas las otras respuestas no abordaron lo que estaba buscando, que era convertir CString sobre la marcha en lugar de 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 que necesita std::string pero tengo <=>.

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 llamarlo cuando tienes un <=>?

std::string firstName = "First";
CString lastName = _T("Last");

writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );     

Tenga en cuenta que la última línea no es un tipo de letra directo, pero estamos creando un objeto <=> sin nombre y suministramos el <=> a través de su constructor.

Hay cualquier problema?

Hay varias cuestiones:

  • CString es una especialización de plantilla de CStringT.Dependiendo de la BaseType describir el tipo de carácter, hay dos especializaciones concretas: CStringA (el uso de char) y CStringW (el uso de 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.
  • Conversión entre Unicode y ANSI es intrínsecamente con pérdida:Codificación ANSI sólo puede representar un subconjunto del conjunto de caracteres Unicode.

Para abordar estas cuestiones, voy a asumir que wchar_t va a la tienda con codificación UTF-16 unidades de código, y char tendrá 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 la 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 esto.

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

Puede usar CT2CA

CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);

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

Un enfoque interesante es lanzar CString a CStringA dentro de un constructor string. A diferencia de std::string s((LPCTSTR)cs); esto funcionará incluso si se define _UNICODE. Sin embargo, si ese es el caso, esto realizará la conversión de Unicode a ANSI, por lo que no es seguro para valores Unicode más altos más allá del conjunto de caracteres ASCII. Dicha conversión está sujeta a la definición del preprocesador _CSTRING_DISABLE_NARROW_WIDE_CONVERSION. https://msdn.microsoft.com/en-us/library/5bzxfsea. aspx

        CString s1("SomeString");
        string s2((CStringA)s1);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top