在使用g++的Linux上,如果我设置了utf8全局语言环境,则wcin会将UTF-8正确地转码为内部wchar_t编码。

但是,如果我使用经典语言环境并将UTF8语言环境注入(inject)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++,所以无法测试此行为,对不起。

关于c++ - wcin.imbue和UTF-8,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32438942/

10-11 00:54