这是我在研究 C/C++ 中处理表达文本的字符串时的最终成果笔记。
-
有没有和 std::string 一样好用的 Unicode 字符串类?
icu::UnicodeString
ICU是C/C++中处理有关Unicode等国际化问题的权威、标准方案:https://icu.unicode.org
-
如何在C/C++代码中方便地定义一个 Unicode 字符串字面量?
- 源文件用 UTF-8 编码
- 对于 MSVC,指定编译选项/utf-8(否则它也会报警提示你)
- 代码中,
""
字面量在运行时默认就会是 utf-8 编码,这一点在 Windows(MSVC) 和 Linux(GCC/Clang) 上都是一致的 - L"" 在Windows上是 utf-16 编码,在 Linux 上是 utf-32 编码,总之实测不好用
- C++ 标准还指定了
u8""
、u""
、U""
三个前缀,可以明确指定字面量在运行时是什么编码
-
如何从 std::cin、std::cout 读入输出一个 Unicode 字符串?
cin、cout 都只不过是简单直接地按字节从缓冲区读写数据,进去的是什么编码,出来的就是什么编码。如果字面量在运行时内存里是 u8 编码,那么输出是就是 u8 编码。
在 windows 上,cmd 和 powershell 的终端默认是 GBK 代码页,所以显示出来就会乱码。同样的,因为是 GBK 代码页,所以 cin 读进去的也是 GBK 编码,cin、cout 不过是原模原样地传递了字节串。
所以,怎么从 std::cin、std::cout 读入 Unicode 取决于你程序的具体运行环境——说白了就是没有一个好方法帮你,除非你用一些开发框架,它们帮你解决了不同平台的适配问题,比如 Qt 就会自动把 QString 自动为平台原生的字符编码类型。Qt 很有意思,由于它会转换输出为平台原生编码,所以如果你 chcp 65001 使用了 UTF-8 代码页,这时再运行使用 QString 的程序反而会导致乱码……
-
为什么 Unicode 的码位 U+D800 ~ U+DFFF 没有分配字符?
为了确保 UTF-16 编码始终被兼容,这又是一个具体实现反而影响标准建立的例子。Unicode标准不是一蹴而就的,而是经过了一次扩充设计,最早就是16位编码(类似UTF-16),而后发现不够了又再进行扩充,所以UTF-16的高位和地位代理项其实是一个历史遗留问题。
同样的,为什么 Unicode 只有 0x10FFFF 个字符,而不是完整的 2^32?——因为 UTF-16 只能表达这么多。
-
Unicode 相关名词的解释
名词 解释 UCS Universal Character Set,统一字符集,可以理解为是 ISO 的专家为 Unicode 起的别名。 UTF Unicode Transformation Format,统一码传输格式,包含 Unicode 标准规定的 3 个编码方法。 SCSU Standard Compression Scheme for Unicode,统一码标准压缩方案,虽然在源代码里最不常见,但它是 Unicode 标准规定的 4 个编码方案之一,主要用于传输,例如电子邮件。 BOM Byte Order Mark,字节序标记,用于在某些情形下在 UTF 传输前指明字节序。 官方FAQ:http://unicode.org/faq/utf_bom.html#bom1
-
推荐做法
除非你要做一些字处理程序,否则对于简单的存储、传输、搜索匹配等需求,直接使用 std::string 默认的 utf-8 编码就好。在处理时相比于 ASCII,只需要简单地将 >127 的字节归为一类字符即可,因为:
UTF-8 maintains transparency for all the ASCII code values (0…127). These values do not appear in any byte of a transformed result except as the direct representation of the ASCII values. Thus, ASCII text is also UTF-8 text.
除了切片和索引!除了UTF-32,其它的编码都不能按码位(也就是通常理解的单个字的概念)随机访问,需要用专用的算法,ICU 帮你写好了这些函数。如果直接切,可能切出来一个头尾字符非法的 Unicode 串。
-
如何让Windows自带的命令行(CMD、Powershell)默认使用UTF-8编码?
阅读此博客:https://blog.youkuaiyun.com/u014132143/article/details/126213522