【问题标题】:How do I output unicode character captured as a substring of command line argument?如何输出捕获为命令行参数子字符串的 unicode 字符?
【发布时间】:2016-07-08 16:59:14
【问题描述】:

我对 C++ 字符串中的 unicode 字符感到困惑。

我有一个这样的程序:

#include <iostream>

int main(int argc, char* argv[]) 
{
std::cout << "3rd char of " << argv[1] << "is: " << argv[1][2] <<  std::endl;
}

当我用这个命令运行它时:

 mapper abͲ

它返回这个:

 3rd character of abͲis: �

现在,显然我的系统支持 unicode (Ubuntu 16.04),编译器不介意程序 (g++ 5.3.1)。我知道 argv 是 char* 对象的向量,但是如果字符是 unicode,我如何访问单个参数向量中的单个字符?一定是我遗漏了一些类型冲突。

【问题讨论】:

  • 您必须了解 UTF-8 的工作原理。
  • @LarryTurtis - 建议:尝试 cout strlen(argv[1])int(argv[1][2])int(argv[1][3])
  • 你不能只输出char* 字符串的单个字节而不了解字节是如何编码的。在此示例中,输入字符 Ͳ 实际上是 Unicode 代码点 U+0372 GREEK CAPITAL LETTER ARCHAIC SAMPI,它以 UTF-8 编码为两个字节 0xCD 0xB2,它们是 UTF-8 编码的 char* 字符串中的单独 char 元素。
  • 解决这些编程问题的一种方法是将输入字符串转换为 UTF-32,即每个字符的固定长度(= 1 int = 4 字节),然后使用它们,或者其他方法是使用一些像ICU这样的UTF库,它的API函数可以选择特定的字符、字符串的长度(实际上是字符数)等等。出于教育目的,你尝试自己处理UTF-8很好,但是@ 987654334@ 本身现在已经超过 25 年了,它仍在修复和开发中...... ;)
  • 现在您可能会感到困惑,为什么 UTF-8 被多次选择作为 linux 的默认值,而它远非微不足道,并且具有每个字符的可变字节数功能。答:大多数情况下,处理 ASCII 字符串(主要是文件名)的旧命令行工具无需修改即可处理 UTF-8 文件名,而不会意识到字符串是 UTF-8 编码的。对于 UTF-16/UCS-2(Java、Win32)编码,情况并非如此,需要更改和重新编译所有工具才能准备好 UTF-16/UCS-2。

标签: c++ c++11 unicode


【解决方案1】:

在 C++ 中处理文本时要记住的最重要的一点是,一个char 不等于一个字符。对于像ASCII这样的单字节字符编码,一个char ==一个字符,但是对于像UTF-8这样的多字节编码,一个字符可以由多个chars组成。

在这种情况下,您尝试输出的字符 (U+0372 GREEK CAPITAL LETTER ARCHAIC SAMPI) 不适合单个 char。它的实际值将取决于您的系统文本编码,因为它已传递到argv。 Ubuntu 16.04 上的默认编码是 UTF-8,因此该字符将是两个字节 0xCD 0xB2

【讨论】:

  • char 起源早于 6 到 8 位编码的时代(在 7b ASCII 成为流行和事实上的标准之前)。在计算机传播到世界各地之后,为其他语言设计了定制的 7-16b 编码。从这个角度来看,Unicode 系列编码是一个相当新的事物,发生在 UNIX 和第一个文件系统之后很长时间,许多 *NIX 工具(今天仍在使用)确实诞生于固定的 8b 编码环境,锁定为整个系统的单个代码页集(所以俄罗斯人没有韩语等字符)。 Unicode 编码是多语言计算机使用的现代解决方案。
  • 而 UTF-8 是 Unicode 编码家族的特殊之处,它与 ASCII 部分兼容。在有效的 UTF-8 字符串中不能出现零字节,除非即使在 UTF-8 编码中它也是一个真正的零。因此,对于 ASCII 就绪代码,UTF-8 字符串看起来是有效的 8 位扩展 ASCII 零终止字符串。因此,只要 ASCII 工具不必处理字母计数或特定字符,它就会正确处理 UTF-8 字符串。 (对不起这么多cmets,但我认为理解为什么这些事情会按照他们的方式完成是很好的:))。
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
相关资源
最近更新 更多