Pergunta

CString é bastante útil, enquanto std::string é mais compatível com o recipiente STL. Eu estou usando hash_map. No entanto, hash_map não suporta CString como chave, então eu quero CString converter em std::string.

Escrevendo uma função CString de hash parece ter um monte de tempo.

CString -----> std::string

Como posso fazer isso?

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

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

Am I certo?


EDIT:

Aqui estão mais perguntas:

Como posso converter wstring, CString entre si? ??

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

Existe qualquer problema?

Como posso converter std::wstring, std::string entre si? ??

Foi útil?

Solução

De acordo com a CodeGuru :

CString para std::string:

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

MAS: std::string nem sempre pode construir a partir de um LPCTSTR. ou seja, o código irá falhar para Unicode cria.

Como std::string pode construir somente a partir LPSTR / LPCSTR, um programador que utiliza 7.x VC ++ ou melhor pode utilizar classes de conversão tais como CT2CA como intermediário.

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 FAQs ... )

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

CStringT pode construir de ambos os caracteres ou de caracteres largos strings. isto é, pode converter de char* (isto é LPSTR) ou a partir de wchar_t* (LPWSTR).

Em outras palavras, char-especialização (de CStringT) ou seja CStringA, wchar_t CStringW-specilization, e TCHAR CString-especialização pode ser construído a partir de qualquer char ou de caracteres largos, terminada nula (null-término é muito importante aqui) fontes de cordas.
Althoug IInspectable altera parte "nulo-rescisão" nos comentários :?

NUL-terminação não é necessária .
CStringT tem construtores de conversão que levam um argumento comprimento explícito. Isto também significa que você pode construir objetos CStringT de objetos std::string com personagens NUL incorporados.

Outras dicas

Solve que usando std::basic_string<TCHAR> vez de std::string e ele deve funcionar bem, independentemente da sua definição dos caracteres.

É mais eficiente para converter CString para std::string usando a conversão onde o comprimento é especificado.

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

No circuito apertado este faz uma melhoria significativa do desempenho.

Se você quiser algo mais C ++ - como, este é o que eu uso. Embora depende Boost, que é apenas para exceções. Você pode facilmente remover os deixando-a depender apenas do STL ea WideCharToMultiByte() chamada de 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 ... e pelo menos até VS2017 v15.8.1)

Uma vez que é um projeto MFC e CString é uma classe MFC, MS fornece uma Nota Técnica TN059: Usando MFC MBCS / Unicode macros de conversão e genérico conversão macros:

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

Use:

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 de rodapé:

(1) Para a conversão-macros para ter espaço para armazenar o comprimento temporário, é necessário declarar uma variável local chamada _convert que faz isso em cada função que usa as macros de conversão. Isso é feito chamando o macro USES_CONVERSION. No código VS2017 MFC (Atlconv.h) parece que isso:

#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

Este é um acompanhamento para a resposta do Sal, onde ele / ela forneceu a solução:

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

Isto é útil também ao converter um não-típico C-String para um std :: string

Um caso para mim estava tendo uma matriz de char pré-alocada (como C-String) o uso, mas não é NUL encerrado. (Isto é, SHA digestão). A sintaxe acima me permite especificar o comprimento da SHA digest da matriz de char para que std :: string não tem que olhar para o caractere de terminação NUL, que pode ou não estar lá.

Tais como:

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

Esta multa funciona:

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

a partir deste post (obrigado Mark Ransom )

Converter CString para string (VC6)

Eu testei isso e ele funciona muito bem.

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 mim:

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 as outras respostas não chegou a abordar o que eu estava procurando, que era converter CString na mosca ao invés de armazenar o resultado em uma variável.

A solução é semelhante ao anterior, mas precisamos de mais um passo para instanciar um objeto sem nome. Estou ilustrando com um exemplo. Aqui é a minha função que precisa std::string mas tenho 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;
}

Como chamá-lo quando você tem um CString?

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

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

Note que a última linha não é um typecast direta, mas estamos criando um objeto sem nome std::string e fornecer o CString via seu construtor.

Existe qualquer problema?

Há várias questões:

  • CString é uma especialização de modelo de CStringT . Dependendo do BaseType que descreve o tipo de caractere, há duas especializações concretas:. CStringA (usando char) e CStringW (usando wchar_t)
  • Enquanto wchar_t no Windows é ubíqua usado para armazenar UTF-16 unidades de código codificado, usando char é ambíguo. O último comumente armazena ANSI codificado personagens, mas também pode armazenar ASCII, UTF-8, ou mesmo dados binários.
  • Não sabemos a codificação de caracteres (ou tipo personagem ainda) de CString (que é controlada através do símbolo pré-processador _UNICODE), tornando a questão ambígua. Nós também não sabemos o caractere desejado codificação de std::string.
  • Conversão entre Unicode e ANSI é inerentemente com perdas:. Codificação ANSI podem representar apenas um subconjunto do conjunto de caracteres Unicode

Para tratar dessas questões, eu vou assumir que wchar_t irá armazenar UTF-16 unidades de código codificados e char vai realizar seqüências de UTF-8 octeto. Essa é a única escolha razoável você pode fazer para garantir que as cordas de origem e destino manter a mesma informação, sem limitar a solução para um subconjunto dos domínios de origem ou de destino.

Os seguintes implementações converter entre CStringA / CStringW e std::wstring / std::string mapeamento de UTF-8 para UTF-16 e vice-versa:

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

O restante duas funções construção C ++ objectos cordas de cordas MFC, deixando o que codifica inalterada. Note-se que enquanto as funções anteriores não pode lidar com caracteres NUL embutidos, essas funções são imunes a isso.

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

Você pode usar CT2CA

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

Se você estiver olhando para converter facilmente entre outros tipos de cordas, talvez o _bstr_t classe seria mais apropriado? Ele suporta converstion entre char, wchar_t e BSTR.

Uma abordagem interessante é CString elenco para CStringA dentro de um construtor string. Ao contrário std::string s((LPCTSTR)cs); isso vai funcionar mesmo se _UNICODE está definida. No entanto, se for esse o caso, isso irá executar a conversão de Unicode para ANSI, por isso não é seguro para valores Unicode mais elevados para além do conjunto de caracteres ASCII. Tal conversão está sujeito à definição _CSTRING_DISABLE_NARROW_WIDE_CONVERSION pré-processador. https://msdn.microsoft.com/en-us/library/5bzxfsea. aspx

        CString s1("SomeString");
        string s2((CStringA)s1);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top