我有一个简单的程序,它使用在命令行上传递给它的一系列语言环境来测试wchar_t和char之间的转换。它通过打印出语言环境名称和无法转换的字符串输出失败的转换列表。
我正在使用clang和libc ++构建它。我的理解是,libc ++的命名语言环境支持由OS X上的xlocale库提供。
我看到了一些意外的失败,以及转换失败的一些情况,但没有。
这是该计划。
#warning call this program like: "locale -a | ./a.out" or pass \
locale names valid for your platform, one per line via standard input
#include <iostream>
#include <codecvt>
#include <locale>
#include <array>
template <class Facet>
class usable_facet : public Facet {
public:
// FIXME: use inheriting constructors when available
// using Facet::Facet;
template <class ...Args>
usable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
~usable_facet() {}
};
int main() {
std::array<std::wstring,11> args = {L"a",L"é",L"¤",L"€",L"Да",L"Ψ",L"א",L"আ",L"✈",L"가",L""};
std::wstring_convert<usable_facet<std::codecvt_utf8<wchar_t>>> u8cvt; // wchar_t uses UCS-4/UTF-32 on this platform
int convert_failures = 0;
std::string line;
while(std::getline(std::cin,line)) {
if(line.empty())
continue;
using codecvt = usable_facet<std::codecvt_byname<wchar_t,char,std::mbstate_t>>;
std::wstring_convert<codecvt> convert(new codecvt(line));
for(auto const &s : args) {
try {
convert.to_bytes(s);
} catch (std::range_error &e) {
convert_failures++;
std::cout << line << " : " << u8cvt.to_bytes(s) << '\n';
}
}
}
std::cout << std::string(80,'=') << '\n';
std::cout << convert_failures << " wstring_convert to_bytes failures.\n";
}
以下是正确输出的一些示例
en_US.ISO8859-1 : €
en_US.US-ASCII : ✈
这是一个不期望的输出示例
en_US.ISO8859-15 : €
欧元字符确实存在于ISO 8859-15字符集中,所以这不应该失败。
以下是我期望但未收到的输出示例
en_US.ISO8859-15 : ¤
en_US.US-ASCII : ¤
这是ISO 8859-1中存在的货币符号,但在ISO 8859-15中被删除并替换为欧元符号。此转换不应该成功,但不会发出错误信号。在进一步检查这个案例时,我发现在两种情况下,'¤'都被转换为0xA4,这是'¤'的ISO 8859-1表示。
我没有直接使用xlocale,只是间接通过libc ++。 Mac OS X上的xlocale是否因为错误的语言环境定义而破坏?有办法解决吗?或者我看到的是其他问题导致的问题?
答案 0 :(得分:3)
我怀疑你看到了xlocale系统的问题。最值得赞赏的是bug report!
答案 1 :(得分:-1)
我不知道为什么你期望wchar_t是UTF-32或者你听说过“OS X的惯例,即wchar_t是UTF-32”。这肯定是不正确的。 wchar_t只有16位宽。
有关wchar_t的详细信息,请参阅http://en.wikipedia.org/wiki/Wide_character。