因此,我要打印ASCII
扩展表C++
,它必须包含乌克兰语字母(西里字母)。我使用的是KDE neon 5.26
linux发行版,它基于Ubuntu
.终端显然是 KDE 的Console
。
我编写了该代码:
#include<iostream>
int main(void) {
for (unsigned char i = 32; int(i) < 255; i++) {
std::cout <<" [" << i << "] " << int(i) << " \t";
if ((i-1)%5 == 0)
std::cout << "\n";
}
char ua_str[] = "Привіт"; // hello in ukrainian
std::cout << "\n\n" << ua_str << "\n" << ua_str[4] << " is " << int(ua_str[4]) << "\n";
return std::cout.fail() ? EXIT_FAILURE : EXIT_SUCCESS;
}
用 编译它g++ lab3.cpp
。它产生这样的输出:
我感兴趣的是它是如何打印char ua_str[]
但不会打印的ua_str[4]
。
终端编码设置为,我在终端编码设置中UTF8
找不到。ASCII
如果我将输出重定向到abc.txt
文本文件./a.out > abc.txt
并打开它,它看起来如下所示:
然后我试图在循环之前添加std::setlocale(LC_ALL, "uk_UA.utf8");
到我的程序中,但它没有改变任何东西,输出是相同的......int main(void)
for
我稍后要制作音译脚本,但无法打印并使用乌克兰字母正常工作......
C++
所以,问题是:如何在on中打印和使用西里尔字母 cahrs KDE neon 5.26
?
答案1
问题在于 UTF-8 不是扩展的 ASCII 编码(对 >127 的字节有很多不同的解释),因此您尝试的方法将不起作用。您告诉终端将某些内容解释为 UTF-8,但事实并非如此。
您需要做的是弄清楚您希望使用哪种特定编码。我猜你的老师指的是 ISO/IEC 8859-5,但我不能确定。唯一知道的方法是询问 - 或者使用您告诉文本编辑器在显示正确字符时使用的编码。这是一个很容易尝试的方法。
就其本身而言,编辑器、控制台或人类无法知道您指的是 ISO/IEC 8859-5 还是其他一些 ASCII 扩展(更正确的是:代码页)。
引用维基百科关于这一点:
使用术语“扩展 ASCII”有时会受到批评,因为它可能被错误地解释为表示 ASCII 标准已更新以包含更多字符,或者该术语明确标识单个编码,但两种情况都不是。
你在这里看到了这种模糊性。
所以,老实说,对于 C++ 初学者来说,这可能不是最好的练习。幸运的是,世界已经基本转向 UTF,因此这种歧义不再影响我们。(这样做的缺点只是你正在编写的确切程序更难编写,因为你需要知道要枚举哪些 unicode 代码点。我不确定你想多久用字节值指定西里尔字母一次,我预计这在现实中接近“从不”。)
现在,要么通过将控制台配置为使用 8859-1 来破坏控制台,要么学习如何将 8859-1 转换为 utf-8 并打印它。后者将是更明智的做法!您的源代码仍然是 UTF-8,这就是为什么在字符串中打招呼是开箱即用的。
那么,如何将“传统”扩展 ASCII 编码转换为 UTF-8?我得查一下。我是德国人,我的名字里有变音符号,自从 UTF-8 成为一种选择以来,我从来没有想过使用除 UTF-8 以外的任何东西。
答案2
UTF-8 是一种多字节编码。在源中添加一个循环:
for (int i = 0; i < sizeof(ua_str); i++) {
std::cout << ua_str[i] << " is " << (0xFF & ua_str[i]) << "\n";
}
现在您可以看到,6 个字符的字符串实际上是一个 12 字节的数组。每个字母由两个字节表示。
“П”为 208-159,“р”为 209-128 等
直指ua_str[4]
第3个字母的页字节。