Como converter wstring em string?

A questão é como converter wstring em string?

Eu tenho o próximo exemplo:

#include  #include  int main() { std::wstring ws = L"Hello"; std::string s( ws.begin(), ws.end() ); //std::cout <<"std::string = "<<s<<std::endl; std::wcout<<"std::wstring = "<<ws<<std::endl; std::cout <<"std::string = "<<s<<std::endl; } 

a saída com a linha comentada é:

 std::string = Hello std::wstring = Hello std::string = Hello 

mas sem é apenas:

 std::wstring = Hello 

Tem alguma coisa errada no exemplo? Posso fazer a conversão como acima?

EDITAR

Novo exemplo (levando em conta algumas respostas) é

 #include  #include  #include  #include  int main() { setlocale(LC_CTYPE, ""); const std::wstring ws = L"Hello"; const std::string s( ws.begin(), ws.end() ); std::cout<<"std::string = "<<s<<std::endl; std::wcout<<"std::wstring = "<<ws<<std::endl; std::stringstream ss; ss << ws.c_str(); std::cout<<"std::stringstream = "<<ss.str()<<std::endl; } 

A saída é:

 std::string = Hello std::wstring = Hello std::stringstream = 0x860283c 

portanto, o stringstream não pode ser usado para converter wstring em string.

    Aqui está uma solução elaborada com base nas outras sugestões:

     #include  #include  #include  #include  #include  int main() { std::setlocale(LC_ALL, ""); const std::wstring ws = L"ħëłlö"; const std::locale locale(""); typedef std::codecvt converter_type; const converter_type& converter = std::use_facet(locale); std::vector to(ws.length() * converter.max_length()); std::mbstate_t state; const wchar_t* from_next; char* to_next; const converter_type::result result = converter.out(state, ws.data(), ws.data() + ws.length(), from_next, &to[0], &to[0] + to.size(), to_next); if (result == converter_type::ok or result == converter_type::noconv) { const std::string s(&to[0], to_next); std::cout < <"std::string = "< 

    Isso geralmente funcionará para o Linux, mas criará problemas no Windows.

    Como Cubbi apontou em um dos comentários, std::wstring_convert (C ++ 11) fornece uma solução simples (você precisa #include e ):

     wstring string_to_convert; //setup converter using convert_type = std::codecvt_utf8; std::wstring_convert converter; //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr) std::string converted_str = converter.to_bytes( string_to_convert ); 

    Eu estava usando uma combinação de wcstombs e tediosa alocação / desalocação de memory antes de me deparar com isso.

    http://en.cppreference.com/w/cpp/locale/wstring_convert

    atualização (2013.11.28)

    Um forro pode ser declarado assim (Obrigado Guss pelo seu comentário):

     std::wstring str = std::wstring_convert>().from_bytes("some string"); 

    As funções do wrapper podem ser declaradas assim: (Obrigado ArmanSchwarz pelo seu comentário)

     wstring s2ws(const std::string& str) { using convert_typeX = std::codecvt_utf8; std::wstring_convert converterX; return converterX.from_bytes(str); } string ws2s(const std::wstring& wstr) { using convert_typeX = std::codecvt_utf8; std::wstring_convert converterX; return converterX.to_bytes(wstr); } 

    Nota: há alguma controvérsia sobre se string / wstring deve ser passada para funções como referências ou como literais (devido a C ++ 11 e atualizações do compilador). Vou deixar a decisão para a pessoa implementar, mas vale a pena conhecer.

    Nota: Estou usando o std::codecvt_utf8 no código acima, mas se você não estiver usando o UTF-8, precisará alterar isso para a codificação apropriada que está usando:

    http://en.cppreference.com/w/cpp/header/codecvt

    Solução de: http://forums.devshed.com/c-programming-42/wstring-to-string-444006.html

     std::wstring wide( L"Wide" ); std::string str( wide.begin(), wide.end() ); // Will print no problemo! std::cout < < str << std::endl; 

    Esteja ciente de que não há nenhuma conversão de conjunto de caracteres acontecendo aqui. O que isto faz é simplesmente atribuir cada wchar_t iterado a um char - uma conversão de truncamento. Ele usa o ctor std :: string :

     template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() ); 

    Como afirmado nos comentários:

    valores 0-127 são idênticos em praticamente todas as codificações, portanto, truncar valores que são todos menores que 127 resulta no mesmo texto. Coloque em um caractere chinês e você verá o fracasso.

    -

    os valores 128-255 da página de códigos do Windows 1252 (o padrão do Windows em Inglês) e os valores 128-255 do unicode são praticamente os mesmos, portanto, se a página de código estiver sendo usada, a maioria desses caracteres deve ser truncada para os valores corretos. (Eu esperava totalmente que á e para o trabalho, eu sei que nosso código no trabalho depende disso para é, o que eu logo consertarei)

    E observe que os pontos de código no intervalo 0x80 - 0x9F no Win1252 não funcionará. Isso inclui , œ , ž , Ÿ , ...

    Em vez de include o locale e todas aquelas coisas extravagantes, se você sabe, para FACT, que sua string é conversível, faça o seguinte:

     #include  #include  using namespace std; int main() { wstring w(L"bla"); string result; for(char x : w) result += x; cout < < result << '\n'; } 

    Exemplo vivo aqui

    Eu acredito que a maneira oficial ainda é ir através de facetas codecvt (você precisa de algum tipo de tradução local), como em

     resultCode = use_facet >(locale). in(stateVar, scratchbuffer, scratchbufferEnd, from, to, toLimit, curPtr); 

    ou algo assim, eu não tenho código de trabalho por aí. Mas eu não tenho certeza de quantas pessoas hoje em dia usam essa máquina e quantas simplesmente pedem pointers para a memory e deixam a UTI ou alguma outra biblioteca lidar com detalhes sangrentos.

    Você também pode usar diretamente o método estreito da faceta ctype:

     #include 
     #include 
     #include 
     #include 
    
     inline std :: string estreito (std :: wstring const & texto)
     {
         std :: locale const loc ("");
         wchar_t const * from = text.c_str ();
         std :: size_t const len ​​= text.size ();
         std :: vector  buffer (len + 1);
         std :: use_facet > (loc) .narrow (de, de + len, '_', & buffer [0]);
         return std :: string (& buffer [0], & buffer [len]);
     }
    

    No momento em que escrevo esta resposta, a pesquisa número um do Google por “converter string de string” pode direcionar você a esta página. Minha resposta mostra como converter string em wstring, embora essa NÃO seja a pergunta real, e eu provavelmente deveria deletar essa resposta, mas isso é considerado uma forma ruim. Você pode pular para essa resposta do StackOverflow , que agora está mais bem classificada do que esta página.


    Aqui está uma maneira de combinar string, wstring e constantes de string mistas a wstring. Use a class wstringstream.

     #include  std::string narrow = "narrow"; std::wstring wide = "wide"; std::wstringstream cls; cls < < " abc " << narrow.c_str() << L" def " << wide.c_str(); std::wstring total= cls.str(); 

    Existem dois problemas com o código:

    1. A conversão em const std::string s( ws.begin(), ws.end() ); não é necessário mapear corretamente os caracteres amplos para suas contrapartes estreitas. O mais provável é que cada caractere amplo seja apenas convertido para char .
      A resolução para esse problema já é dada na resposta por kem e envolve a function narrow da faceta ctype do ctype de idioma.

    2. Você está escrevendo a saída para std::cout e std::wcout no mesmo programa. Ambas cout e wcout são associadas ao mesmo stream ( stdout ) e os resultados do uso do mesmo stream, tanto como um stream orientado por byte (como o cout faz), quanto um stream orientado por largura (como o wcout ) não são definidos.
      A melhor opção é evitar misturar a saída estreita e ampla ao mesmo stream (subjacente). Para stdout / cout / wcout , você pode tentar mudar a orientação do stdout ao alternar entre saída ampla e estreita (ou vice-versa):

       #include  #include  #include  int main() { std::cout < < "narrow" << std::endl; fwide(stdout, 1); // switch to wide std::wcout << L"wide" << std::endl; fwide(stdout, -1); // switch to narrow std::cout << "narrow" << std::endl; fwide(stdout, 1); // switch to wide std::wcout << L"wide" << std::endl; } 

    No meu caso, eu tenho que usar o caractere multibyte (MBCS), e eu quero usar std :: string e std :: wstring. E não posso usar o c ++ 11. Então eu uso mbstowcs e wcstombs.

    Eu faço a mesma function usando new, delete [], mas é mais lento que isso.

    Isso pode ajudar Como: Converter entre vários tipos de seqüência de caracteres

    EDITAR

    No entanto, no caso de converter para wstring e string de origem não é uma seqüência de alfabeto e multi byte, não está funcionando. Então eu mudo wcstombs para WideCharToMultiByte.

     #include  std::wstring get_wstr_from_sz(const char* psz) { //I think it's enough to my case wchar_t buf[0x400]; wchar_t *pbuf = buf; size_t len = strlen(psz) + 1; if (len >= sizeof(buf) / sizeof(wchar_t)) { pbuf = L"error"; } else { size_t converted; mbstowcs_s(&converted, buf, psz, _TRUNCATE); } return std::wstring(pbuf); } std::string get_string_from_wsz(const wchar_t* pwsz) { char buf[0x400]; char *pbuf = buf; size_t len = wcslen(pwsz)*2 + 1; if (len >= sizeof(buf)) { pbuf = "error"; } else { size_t converted; wcstombs_s(&converted, buf, pwsz, _TRUNCATE); } return std::string(pbuf); } 

    EDITAR para usar ‘MultiByteToWideChar’ em vez de ‘wcstombs’

     #include  #include  #include "string_util.h" std::wstring get_wstring_from_sz(const char* psz) { int res; wchar_t buf[0x400]; wchar_t *pbuf = buf; boost::shared_ptr shared_pbuf; res = MultiByteToWideChar(CP_ACP, 0, psz, -1, buf, sizeof(buf)/sizeof(wchar_t)); if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { res = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0); shared_pbuf = boost::shared_ptr(new wchar_t[res]); pbuf = shared_pbuf.get(); res = MultiByteToWideChar(CP_ACP, 0, psz, -1, pbuf, res); } else if (0 == res) { pbuf = L"error"; } return std::wstring(pbuf); } std::string get_string_from_wcs(const wchar_t* pcs) { int res; char buf[0x400]; char* pbuf = buf; boost::shared_ptr shared_pbuf; res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, buf, sizeof(buf), NULL, NULL); if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, NULL, 0, NULL, NULL); shared_pbuf = boost::shared_ptr(new char[res]); pbuf = shared_pbuf.get(); res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, pbuf, res, NULL, NULL); } else if (0 == res) { pbuf = "error"; } return std::string(pbuf); } 

    Esta solução é inspirada na solução do dk123, mas use a faceta codecvt dependente do local. O resultado está na cadeia codificada localmente em vez de utf8 (se não estiver definida como localidade):

     std::string w2s(const std::wstring &var) { static std::locale loc(""); auto &facet = std::use_facet>(loc); return std::wstring_convert::type, wchar_t>(&facet).to_bytes(var); } std::wstring s2w(const std::string &var) { static std::locale loc(""); auto &facet = std::use_facet>(loc); return std::wstring_convert::type, wchar_t>(&facet).from_bytes(var); } 

    Eu estava procurando por isso, mas não consigo encontrá-lo. Finalmente, descobri que posso obter a faceta direita de std :: locale usando a function std :: use_facet () com o typename direito. Espero que isto ajude.

    No caso de alguém mais estar interessado: eu precisava de uma class que pudesse ser usada de forma intercambiável onde quer que uma string ou uma string fosse esperada. A seguinte class convertible_string , baseada na solução do dk123 , pode ser inicializada com uma string , char const* , wstring ou wchar_t const* e pode ser atribuída ou implicitamente convertida em uma string ou wstring (portanto, pode ser passada para uma function que levam também).

     class convertible_string { public: // default ctor convertible_string() {} /* conversion ctors */ convertible_string(std::string const& value) : value_(value) {} convertible_string(char const* val_array) : value_(val_array) {} convertible_string(std::wstring const& wvalue) : value_(ws2s(wvalue)) {} convertible_string(wchar_t const* wval_array) : value_(ws2s(std::wstring(wval_array))) {} /* assignment operators */ convertible_string& operator=(std::string const& value) { value_ = value; return *this; } convertible_string& operator=(std::wstring const& wvalue) { value_ = ws2s(wvalue); return *this; } /* implicit conversion operators */ operator std::string() const { return value_; } operator std::wstring() const { return s2ws(value_); } private: std::string value_; }; 
     #include  namespace lcv = boost::locale::conv; inline std::wstring fromUTF8(const std::string& s) { return lcv::utf_to_utf(s); } inline std::string toUTF8(const std::wstring& ws) { return lcv::utf_to_utf(ws); } 

    Eu estou usando abaixo para converter wstring para string.

     std::string strTo; char *szTo = new char[someParam.length() + 1]; szTo[someParam.size()] = '\0'; WideCharToMultiByte(CP_ACP, 0, someParam.c_str(), -1, szTo, (int)someParam.length(), NULL, NULL); strTo = szTo; delete szTo; 
     // Embarcadero C++ Builder // convertion string to wstring string str1 = "hello"; String str2 = str1; // typedef UnicodeString String; -> str2 contains now u"hello"; // convertion wstring to string String str2 = u"hello"; string str1 = UTF8string(str2).c_str(); // -> str1 contains now "hello"