Eu não acho que stringsaceite caracteres de 8 bits. Já está codificado em UTF-8?
Kennytm
3
Qual é a codificação do seu sistema para criar "おはよう"uma string codificada pelo sistema?
SBI
Acredito que o MSVC aceite isso e faça uma codificação multibyte, talvez UTF-8.
Potatoswatter
1
@ Potatoswatter: MSVC não usa UTF-8 por padrão para QUALQUER COISA. Se você inserir esses personagens, ele pede que a codificação para converter o arquivo para, e o padrão é página de código 1252.
Mooing Duck
2
@ Samir: mais importante é o que é a codificação do arquivo ? Você pode mover essa sequência para o início do arquivo e mostrar um hexdump dessa parte? Provavelmente, podemos identificar isso a partir disso.
Mooing Duck
Respostas:
239
Supondo que a string de entrada no seu exemplo (お は よ う) seja codificada em UTF-8 (o que não é, pelo que parece, mas vamos assumir que seja por causa desta explicação :-)) de uma string Unicode de seu interesse, seu problema poderá ser totalmente resolvido apenas com a biblioteca padrão (C ++ 11 e mais recente).
Como o codecvtcabeçalho foi descontinuado no C ++ 17, foram levantadas algumas preocupações com a solução apresentada nesta resposta. No entanto, o comitê de padrões do C ++ adicionou uma declaração importante em http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html dizendo
esse componente da biblioteca deve ser retirado do anexo D, ao lado, até que uma substituição adequada seja padronizada.
Portanto, no futuro próximo, a codecvtsolução nesta resposta é segura e portátil.
Isso funciona apenas se todos os caracteres tiverem um byte único, ou seja, ASCII ou ISO-8859-1 . Qualquer coisa com vários bytes falhará miseravelmente, incluindo o UTF-8. A pergunta contém claramente caracteres de vários bytes.
Mark Ransom
28
Essa resposta é claramente insuficiente e não faz nada além de copiar caracteres estreitos como em caracteres largos. Veja as outras respostas, particularmente a de Johann Gerell, para saber como passar corretamente de uma sequência de caracteres de bytes múltiplos ou utf8 para uma sequência utf16.
DLRdave
10
essa resposta é perigosa e provavelmente será interrompida no sistema não-ascii. ou seja, um nome de arquivo árabe será mutilado por esse hack.
Stephen Stephen
9
Essa resposta é útil se você ignorar as nuances do corpo da pergunta e se concentrar no título da pergunta, que foi o que me trouxe aqui do Google. Como é, o título da pergunta é extremamente enganador e deve ser alterado para refletir a verdadeira pergunta que está sendo feita
Anne Quinn
3
Isso funciona apenas para caracteres ASCII de 7 bits. Para latin1, ele funciona apenas se char estiver configurado como não assinado. Se o tipo char for assinado (o que geralmente ocorre), caracteres> 127 fornecerão resultados incorretos.
huyc 16/05
32
Sua pergunta está subespecificada. Estritamente, esse exemplo é um erro de sintaxe. No entanto, std::mbstowcsé provavelmente o que você está procurando.
É uma função da biblioteca C e opera em buffers, mas aqui está um idioma fácil de usar, cortesia de TBohne (anteriormente Mooing Duck):
std::wstring ws(s.size(), L' ');// Overestimate number of code points.
ws.resize(std::mbstowcs(&ws[0], s.c_str(), s.size()));// Shrink to fit.
@ Samir: Você precisa garantir que a codificação em tempo de execução seja a mesma que a codificação em tempo de compilação. Pode ser necessário setlocaleou ajustar os sinalizadores do compilador. Não sei porque não uso o Windows, mas é por isso que não é um recurso comum. Considere a outra resposta, se possível.
@WaffleSouffle Isso está desatualizado. Implementações contíguas são necessárias desde 2011 e as implementações encerram esses truques muito antes disso.
Potatoswatter
1
e alguns ambientes como mingw ainda não têm o cabeçalho codecvt assim algumas das soluções 'melhores' mais cedo se não funcionam ou seja, este problema ainda não tem boas soluções em mingw mesmo em Dez 2014
Brian Jack
18
Somente API do Windows, antes da implementação do C ++ 11, caso alguém precise:
Você pode otimizar isso. Não é necessário fazer cópia dupla da string usando a vector. Basta reservar os caracteres na string fazendo wstring strW(charsNeeded + 1);e, em seguida, usá-lo como tampão para a conversão: &strW[0]. Por último garantir última nula está presente após a conversão, fazendostrW[charsNeeded] = 0;
C00000FD
1
@ c00000fd, tanto quanto eu sei, o buffer interno std :: basic_string precisa ser contínuo apenas desde o padrão C ++ 11. Meu código é anterior ao C ++ 11, conforme observado na parte superior da postagem. Portanto, o código & strW [0] não seria compatível com o padrão e poderá travar legitimamente no tempo de execução.
18780 Alex
13
Se você estiver usando o Windows / Visual Studio e precisar converter uma string em wstring, poderá usar:
#include<AtlBase.h>#include<atlconv.h>...
string s ="some string";
CA2W ca2w(s.c_str());
wstring w = ca2w;
printf("%s = %ls", s.c_str(), w.c_str());
O mesmo procedimento para converter uma string para string (às vezes você precisará especificar uma página de código ):
#include<AtlBase.h>#include<atlconv.h>...
wstring w = L"some wstring";
CW2A cw2a(w.c_str());
string s = cw2a;
printf("%s = %ls", s.c_str(), w.c_str());
// // using ATL
CA2W ca2w(str, CP_UTF8);// // or the standard way taken from the answer above#include<codecvt>#include<string>// convert UTF-8 string to wstring
std::wstring utf8_to_wstring (const std::string& str){
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;return myconv.from_bytes(str);}// convert wstring to UTF-8 string
std::string wstring_to_utf8 (const std::wstring& str){
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;return myconv.to_bytes(str);}
Às vezes, você precisará desativar o aviso de segurança # 4995 ', não conheço outra solução alternativa (isso acontece quando eu compilei o WindowsXp no VS2012).
Desculpe, eu não sou um falante nativo de inglês. Edite como achar melhor.
lmiguelmh
O que há com o downvoter? O que há de errado com a resposta?
Lmiguelmh
Provavelmente, o fato de promover código não portátil.
Pavel Minaev 24/08/2015
Sim, foi por isso que afirmei que isso funciona apenas no Windows / Visual Studio. Mas, pelo menos, esta solução é correta, e não um presente:char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
lmiguelmh
Nota adicional: CA2W está no espaço de nome do ATL. (ATL :: CA2W)
Val
12
Aqui está uma maneira de combinar string, wstringe constantes de cadeia mista para wstring. Use a wstringstreamclasse.
Isso NÃO funciona para codificações de caracteres de vários bytes. Esta é apenas uma maneira idiota de jogar fora a segurança de tipo e expandir os caracteres de 7 bits do std :: string para os 7 bits inferiores de cada caractere do std: wstring. Isso só é útil se você tiver uma sequência ASCII de 7 bits e precisar chamar uma API que exija uma sequência ampla.
A resposta parece interessante. Você poderia explicar um pouco: isso funcionará para codificações de vários bytes e por que / como?
wh1t3cat1k
esquemas de codificação são ortogonais à classe de armazenamento. stringarmazena caracteres de 1 byte e wstringarmazena caracteres de 2 bytes. algo como utf8 armazena caracteres de vários bytes como uma série de valores de 1 byte, ou seja, em a string. as classes de string não ajudam na codificação. Eu não sou um especialista em codificar classes em c ++.
Mark Lakata
2
Alguma razão para que essa não seja a melhor resposta, dada a curta e simples? Algum caso que não cobre?
Ryuu
@ MarkLakata, li sua resposta ao primeiro comentário, mas ainda não tenho certeza. Funcionará para caracteres de vários bytes? Em outras palavras, não é propenso à mesma armadilha que esta resposta ?
precisa saber é o seguinte
@ Marc.2377 Isso NÃO funciona para codificações de caracteres de vários bytes. Esta é apenas uma maneira idiota de jogar fora a segurança de tipo e expandir os caracteres de std::string7 bits dos 7 bits inferiores de cada caractere std:wstring. Isso é útil apenas se você tiver uma sequência ASCII de 7 bits e precisar chamar uma API que exija uma sequência ampla. Veja stackoverflow.com/a/8969776/3258851 se precisar de algo mais sofisticado.
Porque isso só funciona se a codificação for Windows-1252, que nem pode conter as letras da pergunta.
Mooing Duck
3
essa é a maneira menos propensa a erros quando você sabe que está lidando com ASCII. Esse é um caso de uso proeminente ao portar aplicativos para APIs mais recentes.
Sid Sarasvati
Este não é o caminho. Se você estiver usando o Visual Studio, use atlconv.h. Verifique as outras respostas.
Essa variante é a minha favorita na vida real. Ele converte a entrada, se for UTF-8 válido , na respectiva wstring. Se a entrada estiver corrompida, ela wstringserá construída a partir dos bytes únicos. Isso é extremamente útil se você realmente não tiver certeza da qualidade dos seus dados de entrada.
O que há com todas essas respostas alocando memória dinâmica de maneira insegura e copiando os dados do buffer para a string? Por que ninguém se livra do intermediário inseguro?
Mooing Duck
hahakubile, você pode ajudar por favor com algo semelhante para o ws2s?
cristian
1
Com base nos meus próprios testes (no Windows 8, vs2010), o mbstowcs pode danificar a string original, funciona apenas com a página de código ANSI. Se MultiByteToWideChar / WideCharToMultiByte também puder causar corrupção de string - mas eles tendem a substituir caracteres que não conhecem por '?' pontos de interrogação, mas o mbstowcs tende a parar quando encontra caracteres desconhecidos e corta a corda nesse exato momento. (Eu testei caracteres vietnamitas em janelas finlandesas).
Portanto, prefira a função api da Multi-windows em vez das funções analógicas ansi C.
Além disso, o que eu notei que a maneira mais curta de codificar string de uma página de código para outra não é usar as funções de API api da MultiByteToWideChar / WideCharToMultiByte, mas suas macros analógicas ATL: W2A / A2W.
Portanto, a função analógica, como mencionado acima, soa como:
Mas observe que essas macro usam muito a pilha - não use para loops ou loops recursivos para a mesma função - depois de usar a macro W2A ou A2W - é melhor retornar o mais rápido possível, para que a pilha seja liberada da conversão temporária.
Este Str2Wstr tem um problema com a terminação 0. Não é possível concatenar mais as seqüências de caracteres geradas via "+" (como na sequência de caracteres s3 = s1 + s2). Vou postar uma resposta em breve resolvendo esse problema. Primeiro, é necessário testar alguns vazamentos de memória.
Isso também não vai funcionar. Você precisará converter esses caracteres não-BMP em seqüências de escape em C.
Dave Van den Eynde 04/04
3
@ Dave: ela não funciona se suas sustentações do compilador Unicode em arquivos de origem, e todos os da última década fazer (visual studio, gcc, ...)
Thomas Bonini
Olá, independentemente da codificação padrão do sistema (posso ter o árabe como codificação padrão do sistema, por exemplo), qual deve ser a codificação do arquivo de código-fonte para L "お は よ う" funcionar? deveria estar em UTF-16 ou posso ter UTF-8 sem BOM para a codificação de arquivo .cpp?
Afriza N. Arief 12/08
2
@afriza: isso realmente não importa, contanto que seus apoios compilá-lo
Thomas Bonini
2
Não é um erro; caracteres estendidos em uma cadeia "estreita" são definidos para mapear para seqüências multibyte. O compilador deve suportá-lo desde que o sistema operacional o faça, o mínimo que você pode pedir.
Potatoswatter
-2
use esse código para converter sua string em wstring
Observe que a pergunta não menciona o Windows e esta resposta é somente para Windows.
Johann Gerell 27/08/2015
CP_ACPé certamente o argumento errado. De repente, o estado do ambiente do encadeamento em execução afeta o comportamento do código. Não aconselhável. Especifique uma codificação de caracteres fixa na sua conversão. (E considere o tratamento de erros.)
strings
aceite caracteres de 8 bits. Já está codificado em UTF-8?"おはよう"
uma string codificada pelo sistema?Respostas:
Supondo que a string de entrada no seu exemplo (お は よ う) seja codificada em UTF-8 (o que não é, pelo que parece, mas vamos assumir que seja por causa desta explicação :-)) de uma string Unicode de seu interesse, seu problema poderá ser totalmente resolvido apenas com a biblioteca padrão (C ++ 11 e mais recente).
A versão TL; DR:
Exemplo compilável e executável online mais longo:
(Todos mostram o mesmo exemplo. Existem muitos para redundância ...)
Nota (antiga) :
Conforme apontado nos comentários e explicado em https://stackoverflow.com/a/17106065/6345, há casos em que o uso da biblioteca padrão para converter entre UTF-8 e UTF-16 pode gerar diferenças inesperadas nos resultados em diferentes plataformas . Para uma melhor conversão, considere
std::codecvt_utf8
o descrito em http://en.cppreference.com/w/cpp/locale/codecvt_utf8Nota (nova) :
Como o
codecvt
cabeçalho foi descontinuado no C ++ 17, foram levantadas algumas preocupações com a solução apresentada nesta resposta. No entanto, o comitê de padrões do C ++ adicionou uma declaração importante em http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html dizendoPortanto, no futuro próximo, a
codecvt
solução nesta resposta é segura e portátil.fonte
std::codecvt_utf8
para iniciantes<codecvt>
está obsoleto desde o C ++ 17.fonte
Sua pergunta está subespecificada. Estritamente, esse exemplo é um erro de sintaxe. No entanto,
std::mbstowcs
é provavelmente o que você está procurando.É uma função da biblioteca C e opera em buffers, mas aqui está um idioma fácil de usar, cortesia de TBohne (anteriormente Mooing Duck):
fonte
setlocale
ou ajustar os sinalizadores do compilador. Não sei porque não uso o Windows, mas é por isso que não é um recurso comum. Considere a outra resposta, se possível.std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
RAII FTWSomente API do Windows, antes da implementação do C ++ 11, caso alguém precise:
fonte
vector
. Basta reservar os caracteres na string fazendowstring strW(charsNeeded + 1);
e, em seguida, usá-lo como tampão para a conversão:&strW[0]
. Por último garantir última nula está presente após a conversão, fazendostrW[charsNeeded] = 0;
Se você estiver usando o Windows / Visual Studio e precisar converter uma string em wstring, poderá usar:
O mesmo procedimento para converter uma string para string (às vezes você precisará especificar uma página de código ):
Você pode especificar uma página de código e até UTF8 (isso é muito bom ao trabalhar com JNI / Java ). Uma maneira padrão de converter um std :: wstring em utf8 std :: string é mostrada nesta resposta .
Se você quiser saber mais sobre páginas de código, há um artigo interessante sobre Joel no Software: O Mínimo Absoluto Todo desenvolvedor de software deve saber absolutamente, positivamente, positivamente sobre Unicode e conjuntos de caracteres .
Essas macros CA2W (Converter ANSI para Wide = unicode) fazem parte das macros de conversão de string ATL e MFC , incluindo exemplos.
Às vezes, você precisará desativar o aviso de segurança # 4995 ', não conheço outra solução alternativa (isso acontece quando eu compilei o WindowsXp no VS2012).
Edit: Bem, de acordo com este artigo, o artigo de Joel parece ser: "embora divertido, é bastante claro sobre detalhes técnicos reais". Artigo: O que todo programador precisa absolutamente e positivamente de saber sobre codificação e conjuntos de caracteres para trabalhar com texto .
fonte
char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
Aqui está uma maneira de combinar
string
,wstring
e constantes de cadeia mista parawstring
. Use awstringstream
classe.Isso NÃO funciona para codificações de caracteres de vários bytes. Esta é apenas uma maneira idiota de jogar fora a segurança de tipo e expandir os caracteres de 7 bits do std :: string para os 7 bits inferiores de cada caractere do std: wstring. Isso só é útil se você tiver uma sequência ASCII de 7 bits e precisar chamar uma API que exija uma sequência ampla.
fonte
string
armazena caracteres de 1 byte ewstring
armazena caracteres de 2 bytes. algo como utf8 armazena caracteres de vários bytes como uma série de valores de 1 byte, ou seja, em astring
. as classes de string não ajudam na codificação. Eu não sou um especialista em codificar classes em c ++.std::string
7 bits dos 7 bits inferiores de cada caracterestd:wstring
. Isso é útil apenas se você tiver uma sequência ASCII de 7 bits e precisar chamar uma API que exija uma sequência ampla. Veja stackoverflow.com/a/8969776/3258851 se precisar de algo mais sofisticado.De
char*
parawstring
:De
string
parawstring
:Observe que isso só funciona bem se a sequência que está sendo convertida contiver apenas caracteres ASCII.
fonte
atlconv.h
. Verifique as outras respostas.usando Boost.Locale:
fonte
Essa variante é a minha favorita na vida real. Ele converte a entrada, se for UTF-8 válido , na respectiva
wstring
. Se a entrada estiver corrompida, elawstring
será construída a partir dos bytes únicos. Isso é extremamente útil se você realmente não tiver certeza da qualidade dos seus dados de entrada.fonte
Se você tem QT e tem preguiça de implementar uma função e outras coisas, pode usar
std :: string str; QString (str) .toStdWString ()
fonte
QString
, porque oQString
construtor não pode aceitar uma string por algum motivo.O método s2ws funciona bem. A esperança ajuda.
fonte
Com base nos meus próprios testes (no Windows 8, vs2010), o mbstowcs pode danificar a string original, funciona apenas com a página de código ANSI. Se MultiByteToWideChar / WideCharToMultiByte também puder causar corrupção de string - mas eles tendem a substituir caracteres que não conhecem por '?' pontos de interrogação, mas o mbstowcs tende a parar quando encontra caracteres desconhecidos e corta a corda nesse exato momento. (Eu testei caracteres vietnamitas em janelas finlandesas).
Portanto, prefira a função api da Multi-windows em vez das funções analógicas ansi C.
Além disso, o que eu notei que a maneira mais curta de codificar string de uma página de código para outra não é usar as funções de API api da MultiByteToWideChar / WideCharToMultiByte, mas suas macros analógicas ATL: W2A / A2W.
Portanto, a função analógica, como mencionado acima, soa como:
_acp é declarado na macro USES_CONVERSION.
Ou também a função que frequentemente sinto falta ao realizar a conversão de dados antigos para um novo:
Mas observe que essas macro usam muito a pilha - não use para loops ou loops recursivos para a mesma função - depois de usar a macro W2A ou A2W - é melhor retornar o mais rápido possível, para que a pilha seja liberada da conversão temporária.
fonte
String para wstring
wstring para String
fonte
string s = "おはよう";
é um erro.Você deve usar o wstring diretamente:
fonte
use esse código para converter sua string em wstring
fonte
CP_ACP
é certamente o argumento errado. De repente, o estado do ambiente do encadeamento em execução afeta o comportamento do código. Não aconselhável. Especifique uma codificação de caracteres fixa na sua conversão. (E considere o tratamento de erros.)