wcin.imbue 和 UTF-8
wcin.imbue and UTF-8
在使用 g++ 的 linux 上,如果我设置了 utf8 全局语言环境,则 wcin
会正确地将 UTF-8 转码为内部 wchar_t 编码。
但是,如果我使用经典语言环境并将 UTF8 语言环境注入 wcin,则不会发生这种情况。输入要么完全失败,要么每个单独的字节都独立地转换为 wchar_t。
使用 clang++ 和 libc++,无论是设置全局语言环境还是在 wcin
中注入语言环境都行不通。
#include <iostream>
#include <locale>
#include <string>
using namespace std;
int main() {
if(true)
// this works with g++, but not with clang++/libc++
locale::global(locale("C.UTF-8"));
else
// this doesn't work with either implementation
wcin.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
cout << s.length() << " " << (s == L"áéú");
return 0;
}
输入流仅包含 áéú 字符。 (它们是 UTF-8,而不是任何单字节编码)。
现场演示:one two(我无法使用在线编译器重现其他行为)。
这符合标准吗?我不应该单独使用全局语言环境并使用 imbue
吗?
是否应将所描述的行为归类为实施错误?
首先你应该使用 wcout 和 wcin。
现在您有两种可能的解决方案:
1) 使用
停用 iostream 和 cstdio 流的同步
ios_base::sync_with_stdio(false);
注意,这应该是第一次调用,否则行为取决于实现。
int main() {
ios_base::sync_with_stdio(false);
wcin.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
wcout << s.length() << " " << (s == L"áéú");
return 0;
}
2) 本地化语言环境和 wcout:
int main() {
std::setlocale(LC_ALL, "C.UTF-8");
wcout.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
wcout << s.length() << " " << (s == L"áéú");
return 0;
}
使用ideone测试了他们两个,工作正常。我没有随身携带 clang++/libc++,所以无法测试此行为,抱歉。
在使用 g++ 的 linux 上,如果我设置了 utf8 全局语言环境,则 wcin
会正确地将 UTF-8 转码为内部 wchar_t 编码。
但是,如果我使用经典语言环境并将 UTF8 语言环境注入 wcin,则不会发生这种情况。输入要么完全失败,要么每个单独的字节都独立地转换为 wchar_t。
使用 clang++ 和 libc++,无论是设置全局语言环境还是在 wcin
中注入语言环境都行不通。
#include <iostream>
#include <locale>
#include <string>
using namespace std;
int main() {
if(true)
// this works with g++, but not with clang++/libc++
locale::global(locale("C.UTF-8"));
else
// this doesn't work with either implementation
wcin.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
cout << s.length() << " " << (s == L"áéú");
return 0;
}
输入流仅包含 áéú 字符。 (它们是 UTF-8,而不是任何单字节编码)。
现场演示:one two(我无法使用在线编译器重现其他行为)。
这符合标准吗?我不应该单独使用全局语言环境并使用 imbue
吗?
是否应将所描述的行为归类为实施错误?
首先你应该使用 wcout 和 wcin。
现在您有两种可能的解决方案:
1) 使用
停用 iostream 和 cstdio 流的同步 ios_base::sync_with_stdio(false);
注意,这应该是第一次调用,否则行为取决于实现。
int main() {
ios_base::sync_with_stdio(false);
wcin.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
wcout << s.length() << " " << (s == L"áéú");
return 0;
}
2) 本地化语言环境和 wcout:
int main() {
std::setlocale(LC_ALL, "C.UTF-8");
wcout.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
wcout << s.length() << " " << (s == L"áéú");
return 0;
}
使用ideone测试了他们两个,工作正常。我没有随身携带 clang++/libc++,所以无法测试此行为,抱歉。