我一直在努力解决 C++ 中的 unicode 支持,并且出现了奇怪的行为。如果我从文件加载一行 unicode 文本,我可以将其存储在常规字符串中并将其输出到 stdout,而不会出现问题。但是,如果我使用具有完全相同字符的 unicode 字符串文字,我必须将其存储在 wstring 中,并且无法正确输出。为什么?
为什么可以在字符串中获取unicode而不需要wstring?为什么cout正确而wstring却无法wcout?
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main(int argc,
char* argv[])
{
ifstream infile("unicode.txt");
string strFromFile;
getline(infile, strFromFile);
infile.close();
cout << "From file: " << strFromFile << endl;
wstring strLiteral = L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ";
wcout << "From literal: " << strLiteral << endl;
return 0;
}
输出:
From file: ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ
From literal: �
�"&*46A�JL��V^fj�t�N��
�!'157BqKM��W_gk�u�O�
我用以下内容编译了这个示例:
g++ main.cpp -Wall
我的编译器是:
g++ (Ubuntu 13.2.0-4ubuntu3) 13.2.0
编码。您的文件很可能采用 UTF-8 格式,它以不同长度的字节序列对 Unicode 进行编码。打印您读取的字符串长度,并与显示的字符数进行比较。
或者做一个
hexdump -C unicode.txt
,然后观察右边的字符现在......垃圾。
不过,相比之下,L""
字符串就复杂了。在我的系统上观察这些测试:
#include <iostream>
#include <string>
int main()
{
std::wcout << L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}
stieber@gatekeeper:~ $ g++ Test.cpp; ./a.out
????????????M??????????CH???????????????????????n?ch??
与您的不同,但不是我们想要的。我们来做点别的吧:
#include <iostream>
#include <string>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "");
std::wcout << L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}
stieber@gatekeeper:~ $ g++ Test.cpp; ./a.out
ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ
好多了。这是因为我们将语言环境设置为您首选的语言环境,而不是
"C"
语言环境,后者似乎讨厌 unicode。
但是,我们总是可以这样做:
#include <iostream>
#include <string>
int main()
{
std::cout << "ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}
stieber@gatekeeper:~ $ g++ Test.cpp; ./a.out
ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ
因为我们只是绕过区域设置并使用 UTF-8。
但是,请注意:
#include <iostream>
#include <string>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "");
std::cout << "ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
std::wcout << L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}
这不起作用:
stieber@gatekeeper:~ $ g++ Test.cpp; ./a.out
ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ
▒
▒"&*46A▒JL▒▒V^fj▒t▒N▒▒
▒!'157BqKM▒▒W_gk▒u▒O▒
我们先得到正确的字符串,然后得到乱码字符串。不要混合
std::cout
和 std::wcout
——我不完全确定这是为什么,或者我是否可以重置任何负责的东西,但目前看来这是一个坏主意。