将char32_t打印到控制台

时间:2013-04-07 00:58:00

标签: c++ unicode c++11 utf-32

如何在C ++ 11中将(cout / wcout / ...)char32_t打印到控制台?

以下代码打印十六进制值:

u32string s2 = U"Добрый день";
for(auto x:s2){
    wcout<<(char32_t)x<<endl;
}

2 个答案:

答案 0 :(得分:3)

首先,我不认为wcout应该打印为charwchar_t之外的任何字符。 char32_t既不是。

以下是打印单个wchar_t's的示例程序:

#include <iostream>

using namespace std;

int main()
{
  wcout << (wchar_t)0x41 << endl;
  return 0;
}

输出(ideone):

A

目前,即使在主要操作系统中,也无法在控制台中获得一致的Unicode输出。通过coutwcoutprintf()wprintf()等简单的Unicode文本输出将无法在没有重大黑客攻击的情况下在Windows上运行。在Windows控制台中获取可读Unicode文本的问题在于能够选择正确的Unicode字体。在这方面,Windows的控制台非常破碎。请参阅this answer of mine并按照其中的链接进行操作。

答案 1 :(得分:0)

我知道这已经很老了,但是我必须自己解决它,然后您就可以解决了。 这个想法是在Unicode的UTF-8和UTF-32编码之间切换:您可以删除u8字符串,所以只需将UTF-32编码的char32_t转换为它,就可以了。这些是我想出的底层函数(没有Modern C ++)。也许这些可以被优化,也可以:任何建议都可以。

char* char_utf32_to_utf8(char32_t utf32, const char* buffer)
// Encodes the UTF-32 encoded char into a UTF-8 string. 
// Stores the result in the buffer and returns the position 
// of the end of the buffer
// (unchecked access, be sure to provide a buffer that is big enough)
{
    char* end = const_cast<char*>(buffer);
    if(utf32 < 0x7F) *(end++) = static_cast<unsigned>(utf32);
    else if(utf32 < 0x7FF) {
        *(end++) = 0b1100'0000 + static_cast<unsigned>(utf32 >> 6);
        *(end++) = 0b1000'0000 + static_cast<unsigned>(utf32 & 0b0011'1111);
    }
    else if(utf32 < 0x10000){
        *(end++) = 0b1110'0000 + static_cast<unsigned>(utf32 >> 12);
        *(end++) = 0b1000'0000 + static_cast<unsigned>((utf32 >> 6) & 0b0011'1111);
        *(end++) = 0b1000'0000 + static_cast<unsigned>(utf32 & 0b0011'1111);
    } else if(utf32 < 0x110000) {
        *(end++) = 0b1111'0000 + static_cast<unsigned>(utf32 >> 18);
        *(end++) = 0b1000'0000 + static_cast<unsigned>((utf32 >> 12) & 0b0011'1111);
        *(end++) = 0b1000'0000 + static_cast<unsigned>((utf32 >> 6) & 0b0011'1111);
        *(end++) = 0b1000'0000 + static_cast<unsigned>(utf32 & 0b0011'1111);
    }
    else throw encoding_error(end);
    *end = '\0';
    return end;
}

如果需要,可以在类中,构造函数,模板中或任何您喜欢的对象中实现此功能。

在重载运算符后面加上char数组

std::ostream& operator<<(std::ostream& os, const char32_t* s)
{
    const char buffer[5] {0}; // That's the famous "big-enough buffer"
    while(s && *s)
    {
        char_utf32_to_utf8(*(s++), buffer);
        os << buffer;
    }
    return os;
}

和u32string

std::ostream& operator<<(std::ostream& os, const std::u32string& s)
{
    return (os << s.c_str());
}

使用Wikipedia上的Unicode字符运行最简单的愚蠢测试

int main()
{
    std::cout << std::u32string(U"\x10437\x20AC") << std::endl;
}

导致?€打印在(Linux)控制台上。不过,应该使用不同的Unicode字符对此进行测试...

此外,字节顺序也不同,但是我敢肯定,您可以在this处找到解决方案。