A questão é como converter wstring em string?
Eu tenho o próximo exemplo:
#include <string>
#include <iostream>
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 linha comentada é:
std::string = Hello
std::wstring = Hello
std::string = Hello
mas sem é apenas:
std::wstring = Hello
Há algo errado no exemplo? Posso fazer a conversão como acima?
EDITAR
Um novo exemplo (levando em consideração algumas respostas) é
#include <string>
#include <iostream>
#include <sstream>
#include <locale>
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.
std::wstring
? stackoverflow.com/questions/1049947/…Respostas:
Aqui está uma solução elaborada com base nas outras sugestões:
Isso normalmente funciona para Linux, mas cria problemas no Windows.
fonte
std::setlocale(LC_ALL, "");
realmente necessário?std::wcout.imbue(locale)
deve fazer o trabalho e tem o benefício de não alterar nenhum estado global.std::wstring_convert
do C ++ 11 envolve muito desse ruído.*** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***
no Linux de 64 bits (gcc 4.7.3). Mais alguém está passando por isso?Como Cubbi apontou em um dos comentários,
std::wstring_convert
(C ++ 11) fornece uma solução simples e elegante (você precisa#include
<locale>
e<codecvt>
):Eu estava usando uma combinação de
wcstombs
alocação / desalocação tediosa de memória antes de me deparar com isso.http://en.cppreference.com/w/cpp/locale/wstring_convert
update (28.11.2013)
Um liners pode ser declarado assim (obrigado Guss pelo seu comentário):
As funções do wrapper podem ser definidas da seguinte forma: (Obrigado ArmanSchwarz pelo seu comentário)
Nota: existe alguma controvérsia sobre se
string
/wstring
deve ser transmitida para funções como referências ou como literais (devido ao C ++ 11 e atualizações do compilador). Vou deixar a decisão para a pessoa que está implementando, mas vale a pena saber.Nota: Estou usando
std::codecvt_utf8
o código acima, mas se você não estiver usando UTF-8, precisará alterá-lo para a codificação apropriada que estiver usando:http://en.cppreference.com/w/cpp/header/codecvt
fonte
std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
Solução de: http://forums.devshed.com/c-programming-42/wstring-to-string-444006.html
Cuidado que não há nenhuma conversão de conjunto de caracteres em andamento aqui. O que isso faz é simplesmente atribuir cada iterado
wchar_t
a umachar
- uma conversão truncante. Ele usa o std :: string c'tor :Conforme declarado nos comentários:
-
E nota que os pontos de código na faixa
0x80 - 0x9F
em Win1252 vai não funcionam. Isto inclui€
,œ
,ž
,Ÿ
, ...fonte
Em vez de incluir o código do idioma e todas essas coisas sofisticadas, se você conhece o FACT, sua string é conversível, faça o seguinte:
Exemplo ao vivo aqui
fonte
Eu acredito que a maneira oficial ainda é seguir todas as
codecvt
facetas (você precisa de algum tipo de tradução com reconhecimento de local), como emou algo assim, não tenho código de trabalho por aí. Mas não sei ao certo quantas pessoas hoje em dia usam esse mecanismo e quantas simplesmente pedem ponteiros para a memória e permitem que a UTI ou alguma outra biblioteca lide com os detalhes sangrentos.
fonte
Há dois problemas com o código:
A conversão em
const std::string s( ws.begin(), ws.end() );
não é necessária para mapear corretamente os caracteres largos para sua contraparte estreita. Provavelmente, cada caractere amplo será tipificado apenas parachar
.A resolução para esse problema já é dada na resposta pelo kem e envolve a
narrow
função dactype
faceta da localidade .Você está gravando saída para ambos
std::cout
estd::wcout
no mesmo programa. Amboscout
ewcout
estão associados ao mesmo fluxo (stdout
) e os resultados do uso do mesmo fluxo como um fluxo orientado a bytes (comocout
faz) e um fluxo orientado a largura (comowcout
) não são definidos.A melhor opção é evitar misturar saída estreita e ampla no mesmo fluxo (subjacente). Para
stdout
/cout
/wcout
, você pode tentar alternar a orientaçãostdout
ao alternar entre saída ampla e estreita (ou vice-versa):fonte
Esse código possui dois formulários para converter std :: string em std :: wstring e std :: wstring em std :: string. Se você negar #if definido WIN32, você obtém o mesmo resultado.
1. std :: string para std :: wstring
• WinAPI MultiByteToWideChar
• _mbstowcs_s_l
2. std :: wstring para std :: string
• WideCharToMultiByte WinAPI
• _wcstombs_s_l
3. No Windows, você precisa imprimir unicode, usando o WinAPI.
• WriteConsole
4. No programa principal.
5. Finalmente, você precisa de um suporte completo e poderoso para caracteres unicode no console. Eu recomendo o ConEmu e defina como terminal padrão no Windows . Você precisa conectar o Visual Studio ao ConEmu. Lembre-se que o arquivo exe do Visual Studio é devenv.exe
Resultado
fonte
Você também pode usar o método estreito da faceta ctype diretamente:
fonte
No momento em que escrevemos essa resposta, a pesquisa número um no Google por "converter string wstring" o colocaria nessa página. Minha resposta mostra como converter string em wstring, embora essa NÃO seja a pergunta real, e eu provavelmente deva excluir essa resposta, mas isso é considerado uma forma incorreta. Você pode pular para esta resposta do StackOverflow , que agora é mais alta do que esta página.
Aqui está uma maneira de combinar string, wstring e constantes de string mistas com o wstring. Use a classe wstringstream.
fonte
Além de apenas converter os tipos, você também deve estar ciente do formato real da string.
Ao compilar para o conjunto de caracteres de vários bytes, o Visual Studio e a API do Win assumem UTF8 (na verdade, a codificação de janelas é Windows-28591 ).
Ao compilar para o conjunto de caracteres Unicode, o Visual studio e a API Win assumem UTF16.
Portanto, você deve converter a sequência do formato UTF16 para UTF8 também, e não apenas converter para std :: string.
Isso será necessário ao trabalhar com formatos com vários caracteres, como alguns idiomas não latinos.
A idéia é decidir que
std::wstring
sempre representa UTF16 .E
std::string
sempre representa UTF8 .Isso não é imposto pelo compilador, é mais uma boa política. Observe os prefixos de string que eu uso para definir UTF16 ( L ) e UTF8 ( u8 ).
Para converter entre os dois tipos, você deve usar: std :: codecvt_utf8_utf16 <wchar_t>
fonte
No meu caso, eu tenho que usar o caractere multibyte (MBCS) e quero usar std :: string e std :: wstring. E não pode usar c ++ 11. Então eu uso mbstowcs e wcstombs.
Faço a mesma função com o uso de 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 há alfabeto nem string de vários bytes, não está funcionando. Então eu mudo wcstombs para WideCharToMultiByte.
EDIT para usar 'MultiByteToWideChar' em vez de 'wcstombs'
fonte
wcstombs()
.Esta solução é inspirada na solução do dk123 , mas usa uma faceta codecvt dependente da localidade. O resultado está na cadeia codificada por código de idioma em vez de UTF-8 (se não estiver definido como código de idioma):
Eu estava procurando, mas não consigo encontrá-lo. Finalmente, descobri que posso obter a faceta certa ao
std::locale
usar astd::use_facet()
função com o nome correto. Espero que isto ajude.fonte
Caso alguém mais esteja interessado: eu precisava de uma classe que pudesse ser usada de forma intercambiável, onde quer que fosse
string
ouwstring
fosse esperado. A classe a seguirconvertible_string
, com base na solução de dk123 , pode ser inicializado com qualquer umstring
,char const*
,wstring
ouwchar_t const*
e pode ser atribuído a pelo ou implicitamente convertidos em qualquer umstring
ouwstring
(assim pode ser passado para uma série de funções que tomam qualquer um).fonte
std::wstring
na classe, do que armazenarstd::string
e fazer uma conversão parastd::wstring
quando necessáriostd::wstring
. Porquestd::wstring
é um pouco mais rápidostd::string
e é melhor compatível. Mesmo ele consome mais memória do questd::string
.fonte
Estou usando abaixo para converter wstring em string.
fonte
<string>
) e uma definição paraWideCharToMultiByte()
- isso é algum invólucrostd::wctomb()
?fonte