提问人:James Raitsev 提问时间:8/18/2012 最后编辑:Peter MortensenJames Raitsev 更新时间:5/16/2023 访问量:239343
如何在 C++ 中打印 Unicode 字符
How to print Unicode character in C++
问:
我正在尝试打印一个俄语“ф”(U+0444 西里尔文小写字母 EF)字符,该字符的代码为十进制 1092。使用 C++,如何打印出此字符?我本来以为以下内容会起作用,但是......
int main (){
wchar_t f = '1060';
cout << f << endl;
}
答:
归根结底,这完全取决于平台。不幸的是,Unicode支持在标准C++中非常差。对于 GCC,您必须将其设置为窄字符串,因为它们使用 UTF-8,而 Windows 需要宽字符串,并且您必须输出到 .wcout
// GCC
std::cout << "ф";
// Windoze
wcout << L"ф";
评论
\uXXXX
XXXX
\u
\UXXXXXXXX
std::wcout
'\u0400'
\u0400
'1060'
是四个字符,不会在标准下编译。如果您的宽字符与 Unicode 的 1:1 匹配,则应将字符视为数字(检查您的区域设置)。
int main (){
wchar_t f = 1060;
wcout << f << endl;
}
评论
operator <<
'1060'
是类型的多字符字符文本,在标准 C++ 下是完全合法的。不过,它的价值是实现定义的。大多数实现将获取字符的值并将它们连接起来以生成单个整数值。这些有时用于所谓的“FourCC”。int
若要表示字符,可以使用通用字符名称 (UCN)。字符“ф”的 Unicode 值为 U+0444,因此在C++中可以将其写成“\u0444”或“\U00000444”。此外,如果源代码编码支持此字符,那么您可以在源代码中逐字逐句地编写它。
// both of these assume that the character can be represented with
// a single char in the execution encoding
char b = '\u0444';
char a = 'ф'; // this line additionally assumes that the source character encoding supports this character
打印出此类字符取决于要打印的内容。如果要打印到 Unix 终端仿真器,终端仿真器使用支持此字符的编码,并且该编码与编译器的执行编码匹配,则可以执行以下操作:
#include <iostream>
int main() {
std::cout << "Hello, ф or \u0444!\n";
}
此程序不要求“ф”可以用单个字符表示。在 OS X 和大多数现代 Linux 安装中,这都可以正常工作,因为源编码、执行编码和控制台编码都是 UTF-8(支持所有 Unicode 字符)。
Windows 的情况更难,并且有不同的可能性和不同的权衡。
如果你不需要可移植代码(你将使用wchar_t,这在其他平台上应该避免),最好的办法是将输出文件句柄的模式设置为仅接受 UTF-16 数据。
#include <iostream>
#include <io.h>
#include <fcntl.h>
int main() {
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << L"Hello, \u0444!\n";
}
可移植代码更难。
评论
char
\u
\x
使用 编译时,可以简单地-std=c++11
const char *s = u8"\u0444";
cout << s << endl;
评论
\uXXXX
\UXXXXXXXX
u8"..."
如果您使用 Windows(注意,我们使用的是 printf()),而不是 cout):
// Save as UTF-8 without a signature
#include <stdio.h>
#include<windows.h>
int main (){
SetConsoleOutputCP(65001);
printf("ф\n");
}
它不是 Unicode,但它正在工作 - Windows-1251 而不是 UTF-8:
// Save as Windows 1251
#include <iostream>
#include<windows.h>
using namespace std;
int main (){
SetConsoleOutputCP(1251);
cout << "ф" << endl;
}
评论
在 Linux 中,我只能做:
std::cout << "ф";
我只是从这里复制粘贴了字符,至少在我尝试的随机样本中没有失败。
Linux 中的另一种解决方案:
string a = "Ф";
cout << "Ф = \xd0\xa4 = " << hex
<< int(static_cast<unsigned char>(a[0]))
<< int(static_cast<unsigned char>(a[1])) << " (" << a.length() << "B)" << endl;
string b = "√";
cout << "√ = \xe2\x88\x9a = " << hex
<< int(static_cast<unsigned char>(b[0]))
<< int(static_cast<unsigned char>(b[1]))
<< int(static_cast<unsigned char>(b[2])) << " (" << b.length() << "B)" << endl;
我需要在UI中显示字符串,并将其保存到XML配置文件中。上面指定的格式适用于 c++ 中的字符串,我想补充一点,我们可以通过将“\u”替换为“&#x”并在末尾添加“;”来为特殊字符提供 xml 兼容字符串。
例如:
C++: “\u0444” → XML :"ф"
此代码适用于 Linux(C++11、Geany 和 GCC 7.4 (. 2018-12-06)):g++
#include <iostream>
using namespace std;
int utf8_to_unicode(string utf8_code);
string unicode_to_utf8(int unicode);
int main()
{
cout << unicode_to_utf8(36) << '\t';
cout << unicode_to_utf8(162) << '\t';
cout << unicode_to_utf8(8364) << '\t';
cout << unicode_to_utf8(128578) << endl;
cout << unicode_to_utf8(0x24) << '\t';
cout << unicode_to_utf8(0xa2) << '\t';
cout << unicode_to_utf8(0x20ac) << '\t';
cout << unicode_to_utf8(0x1f642) << endl;
cout << utf8_to_unicode("$") << '\t';
cout << utf8_to_unicode("¢") << '\t';
cout << utf8_to_unicode("€") << '\t';
cout << utf8_to_unicode("🙂") << endl;
cout << utf8_to_unicode("\x24") << '\t';
cout << utf8_to_unicode("\xc2\xa2") << '\t';
cout << utf8_to_unicode("\xe2\x82\xac") << '\t';
cout << utf8_to_unicode("\xf0\x9f\x99\x82") << endl;
return 0;
}
int utf8_to_unicode(string utf8_code)
{
unsigned utf8_size = utf8_code.length();
int unicode = 0;
for (unsigned p=0; p<utf8_size; ++p)
{
int bit_count = (p? 6: 8 - utf8_size - (utf8_size == 1? 0: 1)),
shift = (p < utf8_size - 1? (6*(utf8_size - p - 1)): 0);
for (int k=0; k<bit_count; ++k)
unicode += ((utf8_code[p] & (1 << k)) << shift);
}
return unicode;
}
string unicode_to_utf8(int unicode)
{
string s;
if (unicode>=0 and unicode <= 0x7f) // 7F(16) = 127(10)
{
s = static_cast<char>(unicode);
return s;
}
else if (unicode <= 0x7ff) // 7FF(16) = 2047(10)
{
unsigned char c1 = 192, c2 = 128;
for (int k=0; k<11; ++k)
{
if (k < 6)
c2 |= (unicode % 64) & (1 << k);
else
c1 |= (unicode >> 6) & (1 << (k - 6));
}
s = c1;
s += c2;
return s;
}
else if (unicode <= 0xffff) // FFFF(16) = 65535(10)
{
unsigned char c1 = 224, c2 = 128, c3 = 128;
for (int k=0; k<16; ++k)
{
if (k < 6)
c3 |= (unicode % 64) & (1 << k);
else if
(k < 12) c2 |= (unicode >> 6) & (1 << (k - 6));
else
c1 |= (unicode >> 12) & (1 << (k - 12));
}
s = c1;
s += c2;
s += c3;
return s;
}
else if (unicode <= 0x1fffff) // 1FFFFF(16) = 2097151(10)
{
unsigned char c1 = 240, c2 = 128, c3 = 128, c4 = 128;
for (int k=0; k<21; ++k)
{
if (k < 6)
c4 |= (unicode % 64) & (1 << k);
else if (k < 12)
c3 |= (unicode >> 6) & (1 << (k - 6));
else if (k < 18)
c2 |= (unicode >> 12) & (1 << (k - 12));
else
c1 |= (unicode >> 18) & (1 << (k - 18));
}
s = c1;
s += c2;
s += c3;
s += c4;
return s;
}
else if (unicode <= 0x3ffffff) // 3FFFFFF(16) = 67108863(10)
{
; // Actually, there are no 5-bytes unicodes
}
else if (unicode <= 0x7fffffff) // 7FFFFFFF(16) = 2147483647(10)
{
; // Actually, there are no 6-bytes unicodes
}
else
; // Incorrect unicode (< 0 or > 2147483647)
return "";
}
更多:
- https://sites.google.com/view/technik-informatyk-nysa/porady/porady-c-cpp#h.p_lz0skneGFILy
- UTF-8 (维基百科)
特别感谢这里的答案或多或少是相同的问题。
对我来说,我所需要的只是 setlocale(LC_ALL, “en_US.UTF-8“);
然后,我甚至可以使用原始字符。wchar_t
评论
std::cout
std::cout