C++ C++;unicode字符打印

C++ C++;unicode字符打印,c++,unicode,cout,C++,Unicode,Cout,我需要使用iostream在Linux终端上打印一些unicode字符。但奇怪的事情还是发生了。当我写作时: cout << "\u2780"; 我得到:14851712 问题是,我不知道编译时要打印的确切字符。因此,我想做如下事情: int x; // some calculations... cout << (char)('\u2780' + x); intx; //一些计算。。。 coutUnicode字符\u2780超出char数据类型的范围。您应该收到这个编

我需要使用
iostream
在Linux终端上打印一些unicode字符。但奇怪的事情还是发生了。当我写作时:

cout << "\u2780";
我得到:
14851712

问题是,我不知道编译时要打印的确切字符。因此,我想做如下事情:

int x;
// some calculations...
cout << (char)('\u2780' + x);
intx;
//一些计算。。。

coutUnicode字符
\u2780
超出
char
数据类型的范围。您应该收到这个编译器警告来告诉您:(至少我的g++4.7.3给出了这个警告)

如果您想将U+2780等字符作为单个单元使用,则必须使用widechar数据类型
wchar\U t
,或者如果您足够幸运,能够使用C++11、
char32\U t
char16\U t
。请注意,一个16位单元不足以表示整个Unicode字符范围

如果这对您不起作用,可能是因为默认的“C”语言环境不支持非ASCII输出。要解决该问题,可以在程序开始时调用
setlocale
;这样,您就可以输出用户区域设置支持的全部字符范围:(可能支持也可能不支持您使用的所有字符)

#包括
#包括
使用名称空间std;
int main(){
setlocale(LC_ALL,“”);
当你写的时候

cout << "\u2780";
您也可以使用现有的任何其他生成UTF-8的方法。例如,iconv、ICU和手动使用pre-C++11 codecvt_byname方面都可以工作。(我不展示这些示例,因为该代码比
wstring_convert
允许的简单代码更复杂)


另一种适用于少量字符的方法是使用文字创建字符串数组

char const *special_character[] = { "\u2780", "\u2781", "\u2782",
  "\u2783", "\u2784", "\u2785", "\u2786", "\u2787", "\u2788", "\u2789" };

std::cout << special_character[i] << '\n';
char const*特殊字符[]={“\u2780”、“\u2781”、“\u2782”,
“\u2783”、“\u2784”、“\u2785”、“\u2786”、“\u2787”、“\u2788”、“\u2789”};

std::cout由于C++11§2.14.3/1:

多字符文字或普通字符文字包含一个在执行字符集中不可表示的c字符,受条件支持,具有int类型,并具有实现定义的值

执行字符集是
char
可以表示的,即ASCII

您得到的是14851712,或十六进制e29e80,它是U+2780的UTF-8表示形式。将多字节编码UTF-8放入
int
是疯狂和愚蠢的,但这正是您从“有条件支持、实现定义”功能中得到的

要获得UTF-32值,请使用
U'\u2780'
。第一个
U
指定
char32\U t
类型和UTF-32编码(即最多31位,但没有代理项对)。第二个
\u
指定包含代码点的通用字符名。若要获取假定与
wcout
兼容的值,请使用
L'\u2780'
,但这不一定使用Unicode运行时值,也不必获得超过两个字节的存储空间

至于可靠地操纵和打印Unicode代码点,正如其他答案所指出的,C++标准还没有完全达到。乔妮的答案是最好的方法,但它仍然假定编译器和用户的环境使用相同的区域设置,这通常不是真的。


您还可以使用
u8“\u2780”
在源代码中指定UTF-8字符串,并使用类似
std::locale::global(std::locale(“en_US.UTF-8”)的内容强制运行时环境使用UTF-8乔妮建议使用C接口<代码> STD:St/ActoS> <代码> >代码> > C++ >接口>代码> STD::LoaLe::Global < /C> >从代码> >代码>,这是一个解决方案,在GCC上在OX X上和其他平台上被破坏的C++接口。您的Linux发行版可能已经在自己的GCC包中添加了补丁。

在Linux中,我已经成功地直接打印出了任何unicode,这是最简单的方式:

std::cout << "ΐ , Α, Β, Γ, Δ, ,Θ , Λ, Ξ, ... ±, ... etc"

std::您是否正在与操作员一起使用wchar\t
L
?如果可能,请将您的完整代码发布到[sscce.org](sscce)如果您不想弄乱Unicode编码,您可以使用一个表将字符串映射到
x
的可能值,而不是添加它。如果
sizeof(wchar\t),可能重复的字符串当然也会有同样的问题,其他字符(SMP)<4
。我建议使用
char16\u t
char32\u t
顺便说一句。除了编码前缀
L
,还有
u8
用于
UTF8
编码,
u
用于
char16\u t
,以及
char32\u
用于
setlocale>
传递
时的
setlocale
对于区域名称,设置用户首选的区域设置,不一定是Unicode区域设置。谢谢@DyP,我已经添加了关于新字符数据类型的注释。@Sventimir IIRC他们在C++11中遗漏了对流的Unicode支持;
wcout不支持,因为您或我可能遗漏了一些内容,因为编译器现在需要“U未在作用域中声明”。@Sventimir显然GCC 4.7.2不支持它,但它是C++11标准的一部分。只需使用
L'xxx'
;在Linux中它应该做基本相同的事情。使用
GCC--std=C++11
调用添加C++11支持也不起作用。它现在可以编译,但可以打印字符的十进制值(10112),而不是字符本身。
cout << "\u2780";
#include <codecvt>

int main() {
  char32_t base = U'\u2780';

  std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
  std::cout << convert.to_bytes(base + 5) << '\n';
}
char const *special_character[] = { "\u2780", "\u2781", "\u2782",
  "\u2783", "\u2784", "\u2785", "\u2786", "\u2787", "\u2788", "\u2789" };

std::cout << special_character[i] << '\n';
std::cout << "ΐ , Α, Β, Γ, Δ, ,Θ , Λ, Ξ, ... ±, ... etc"