Há algumas respostas muito boas aqui, mas acho que há algumas coisas que posso adicionar em relação ao Windows / Visual Studio. Isso é baseado na minha experiência com o VS2015. No Linux, basicamente a resposta é usar UTF-8 codificado em std::string
qualquer lugar. No Windows / VS, fica mais complexo. Aqui está o porquê. O Windows espera que as seqüências armazenadas usando char
s sejam codificadas usando a página de código do código de idioma. Esse é quase sempre o conjunto de caracteres ASCII seguido por 128 outros caracteres especiais, dependendo da sua localização. Deixe-me apenas declarar que isso não apenas ao usar a API do Windows, há outros três locais importantes em que essas seqüências de caracteres interagem com o C ++ padrão. Estes são literais de string, com saída e std::cout
uso de <<
um nome de arquivo para std::fstream
.
Serei sincero aqui, pois sou um programador, não um especialista em idiomas. Aprecio que USC2 e UTF-16 não são os mesmos, mas para meus propósitos eles são próximos o suficiente para serem intercambiáveis e eu os uso como tal aqui. Na verdade, não tenho certeza de qual Windows usa, mas geralmente também não preciso saber. Eu afirmei o UCS2 nesta resposta; portanto, desculpe-me antecipadamente se incomodar alguém com minha ignorância sobre esse assunto e fico feliz em alterá-lo se houver alguma coisa errada.
Literais de string
Se você digitar literais de seqüência de caracteres que contêm apenas caracteres que podem ser representados pela sua página de código, o VS os armazenará em seu arquivo com 1 byte por codificação de caracteres com base na sua página de código. Observe que, se você alterar sua página de código ou fornecer sua fonte para outro desenvolvedor usando uma página de código diferente, acho que (mas não testei) que o personagem terminará diferente. Se você executar seu código em um computador usando uma página de código diferente, não tenho certeza se o caractere também será alterado.
Se você digitar qualquer literal de string que não possa ser representado pela sua página de código, o VS solicitará que você salve o arquivo como Unicode. O arquivo será codificado como UTF-8. Isso significa que todos os caracteres não ASCII (incluindo os que estão na sua página de códigos) serão representados por 2 ou mais bytes. Isso significa que, se você fornecer sua fonte para outra pessoa, a fonte terá a mesma aparência. No entanto, antes de passar a fonte para o compilador, o VS converte o texto codificado em UTF-8 em texto codificado em página de código e todos os caracteres ausentes na página de código são substituídos ?
.
A única maneira de garantir a representação correta de um literal de cadeia de caracteres Unicode no VS é preceder o literal de cadeia de caracteres, L
tornando-o uma literal de cadeia de caracteres ampla. Nesse caso, o VS converterá o texto codificado em UTF-8 do arquivo em UCS2. Você precisa passar essa literal de string para um std::wstring
construtor ou convertê-la em utf-8 e colocá-la em a std::string
. Ou, se desejar, você pode usar as funções da API do Windows para codificá-lo usando sua página de código para colocá-lo em umstd::string
, mas também pode não ter usado uma literal de cadeia ampla.
std :: cout
Ao enviar para o console usando, <<
você só pode usar std::string
, não, std::wstring
e o texto deve ser codificado usando sua página de código do código de idioma. Se você tiver um std::wstring
, deverá convertê-lo usando uma das funções da API do Windows e qualquer caractere que não esteja na sua página de código será substituído por ?
(talvez você possa alterar o caractere, não lembro).
std :: nomes de arquivos fstream
O sistema operacional Windows usa UCS2 / UTF-16 para seus nomes de arquivos, portanto, qualquer que seja sua página de código, você pode ter arquivos com qualquer caractere Unicode. Mas isso significa que, para acessar ou criar arquivos com caracteres que não estão na sua página de código, você deve usar std::wstring
. Não há outro caminho. Esta é uma extensão específica da Microsoft std::fstream
que provavelmente não será compilada em outros sistemas. Se você usar std :: string, poderá utilizar apenas nomes de arquivos que incluem apenas caracteres na sua página de código.
Suas opções
Se você está apenas trabalhando no Linux, provavelmente não chegou tão longe. Basta usar UTF-8 em std::string
qualquer lugar.
Se você está apenas trabalhando no Windows, use o UCS2 em std::wstring
qualquer lugar. Alguns puristas podem dizer que usam UTF8 e depois convertem quando necessário, mas por que se preocupar com o aborrecimento.
Se você é multiplataforma, é uma bagunça ser franco. Se você tentar usar o UTF-8 em qualquer lugar do Windows, precisará ter muito cuidado com os literais de seqüência de caracteres e com a saída no console. Você pode facilmente corromper suas cordas lá. Se você usa std::wstring
qualquer lugar do Linux, pode não ter acesso à versão ampla std::fstream
, portanto é necessário fazer a conversão, mas não há risco de corrupção. Então, pessoalmente, acho que essa é uma opção melhor. Muitos discordariam, mas eu não estou sozinho - é o caminho percorrido pelo wxWidgets, por exemplo.
Outra opção poderia ser typedef unicodestring
como std::string
no Linux e std::wstring
no Windows, e ter uma macro chamada UNI () que prefixa L no Windows e nada no Linux, depois o código
#include <fstream>
#include <string>
#include <iostream>
#include <Windows.h>
#ifdef _WIN32
typedef std::wstring unicodestring;
#define UNI(text) L ## text
std::string formatForConsole(const unicodestring &str)
{
std::string result;
//Call WideCharToMultiByte to do the conversion
return result;
}
#else
typedef std::string unicodestring;
#define UNI(text) text
std::string formatForConsole(const unicodestring &str)
{
return str;
}
#endif
int main()
{
unicodestring fileName(UNI("fileName"));
std::ofstream fout;
fout.open(fileName);
std::cout << formatForConsole(fileName) << std::endl;
return 0;
}
ficaria bem em qualquer plataforma, eu acho.
Respostas
Então, para responder às suas perguntas
1) Se você está programando para o Windows, o tempo todo, se for multiplataforma, talvez o tempo todo, a menos que você queira lidar com possíveis problemas de corrupção no Windows ou escreva algum código com a plataforma específica #ifdefs
para solucionar as diferenças, apenas usando Linux então nunca.
2) sim Além do Linux, você também pode usá-lo para todos os Unicode. No Windows, você pode usá-lo apenas para todos os unicode se optar por codificar manualmente usando UTF-8. Mas a API do Windows e as classes C ++ padrão esperam que elas std::string
sejam codificadas usando a página de código do código de idioma. Isso inclui todos os ASCII, além de outros 128 caracteres, que variam dependendo da página de código que o computador está configurado para usar.
3) Eu acredito que sim, mas se não, então é apenas um simples typedef de um 'std :: basic_string' usando em wchar_t
vez dechar
4) Um caractere amplo é um tipo de caractere maior que o char
tipo padrão de 1 byte . No Windows, são 2 bytes, no Linux, são 4 bytes.