web-dev-qa-db-fra.com

Comment convertir CString et :: std :: string :: std :: wstring l'un vers l'autre?

CString est assez pratique, alors que std::string est plus compatible avec le conteneur STL . J'utilise hash_map. Cependant, hash_map ne supporte pas CString en tant que clé, je souhaite donc convertir CString en std::string.

Écrire une fonction de hachage CString semble prendre beaucoup de temps.

CString -----> std::string

Comment puis-je faire ceci?

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

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

Ai-je raison?


EDIT:

Voici d'autres questions:

Comment puis-je convertir wstring, CString les uns aux autres?

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

Existe-t-il un problème?

Comment puis-je convertir std::wstring, std::string l'un à l'autre?

66
user25749

Selon CodeGuru :

CString à std::string:

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

BUT:std::string ne peut pas toujours construire à partir d'une LPCTSTR. c'est-à-dire que le code échouera pour les générations UNICODE.

Comme std::string ne peut construire que à partir de LPSTRLPCSTR, un programmeur qui utilise VC++ 7.x ou une version supérieure peut utiliser des classes de conversion telles que CT2CA en tant qu'intermédiaire.

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 : (De FAQ CString de Visual Studio ... )

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

CStringT peut construire à partir de chaînes de caractères ou de chaînes de caractères larges. il peut convertir à partir de char* (i.e. LPSTR) ou de wchar_t* (LPWSTR).

En d'autres termes, la spécialisation sur caractères (de CStringT), c'est-à-dire CStringA, wchar_t- specilization CStringW, et TCHAR- specialization CString peut être construite à partir de char ou de caractères larges, null terminé (la terminaison nulle est très importante ici) sources de chaîne.
Althoug Non respectable modifie la partie "null-termination" dans les commentaires :

_/NUL-terminaison n'est pas nécessaire.
CStringT a des constructeurs de conversion qui prennent un argument de longueur explicite. Cela signifie également que vous pouvez construire des objets CStringT à partir d'objets std::string avec des caractères NUL incorporés.

82
VonC

Résolvez cela en utilisant std::basic_string<TCHAR> au lieu de std::string et tout devrait bien se passer, quel que soit le réglage de votre personnage.

34
OJ.

Il est plus efficace de convertir CString en std::string en utilisant la conversion où la longueur est spécifiée.

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

En boucle serrée, cela améliore considérablement les performances.

5
Sal

Si vous voulez quelque chose de plus C++, c'est ce que j'utilise. Bien que cela dépende de Boost, ce n'est que des exceptions. Vous pouvez facilement supprimer ceux qui le laissent pour qu'ils ne dépendent que de la STL et de l'appel API Win32 WideCharToMultiByte().

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

Ceci est un suivi de la réponse de Sal, où il/elle a fourni la solution:

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

Ceci est utile également lors de la conversion d'une chaîne de caractères non typique en une chaîne std :: string

Un cas d'utilisation pour moi était d'avoir un tableau de caractères pré-alloué (comme C-String), mais il n'est pas terminé par NUL. (c'est-à-dire SHA digest) .. ... La syntaxe ci-dessus me permet de spécifier la longueur du résumé SHA du tableau de caractères afin que std :: string ne doive pas rechercher le NUL final char, qui peut ou peut ne pas être là.

Tel que:

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

de ce post (Merci Mark Ransom )

Convertit CString en chaîne (VC6)

J'ai testé cela et cela fonctionne 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;
}
1
Pat. ANDRIA

(Depuis VS2012 ... et au moins jusqu'à VS2017 v15.8.1)

Etant donné qu'il s'agit d'un projet MFC et que CString est une classe MFC, MS fournit une note technique TN059: Utilisation de macros de conversion MBCS/Unicode MFC et de macros de conversion génériques:

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

Utilisation:

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

-

Notes de bas de page:

(1) Pour que les macros de conversion disposent d'un espace pour stocker la longueur temporaire, il est nécessaire de déclarer une variable locale appelée _convert qui le fait dans chaque fonction utilisant les macros de conversion. Ceci est fait en appelant la macro USES_CONVERSION. Dans le code MFC VS2017 (atlconv.h), il se présente comme suit:

#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
1
Amit G.

Cela fonctionne bien:

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

Toutes les autres réponses n'abordaient pas tout à fait ce que je cherchais, à savoir convertir CString à la volée plutôt que de stocker le résultat dans une variable. 

La solution est similaire à celle décrite ci-dessus, mais nous avons besoin d’une étape supplémentaire pour instancier un objet sans nom. Je suis illustrant avec un exemple. Voici ma fonction qui a besoin de std::string mais j'ai 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;
}

Comment appeler quand vous avez une CString?

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

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

Notez que la dernière ligne n'est pas un transtypage direct, mais nous créons un objet sans nom std::string et fournissons la CString via son constructeur.

0
zar

Vous pouvez utiliser CT2CA

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

Travaille pour moi:

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