C/C++ 字符串编码的相关问题

这是我在研究 C/C++ 中处理表达文本的字符串时的最终成果笔记。

  1. 有没有和 std::string 一样好用的 Unicode 字符串类?

    icu::UnicodeString

    ICU是C/C++中处理有关Unicode等国际化问题的权威、标准方案:https://icu.unicode.org

  2. 如何在C/C++代码中方便地定义一个 Unicode 字符串字面量?

    1. 源文件用 UTF-8 编码
    2. 对于 MSVC,指定编译选项/utf-8(否则它也会报警提示你)
    3. 代码中,"" 字面量在运行时默认就会是 utf-8 编码,这一点在 Windows(MSVC) 和 Linux(GCC/Clang) 上都是一致的
    4. L"" 在Windows上是 utf-16 编码,在 Linux 上是 utf-32 编码,总之实测不好用
    5. C++ 标准还指定了 u8""u""U"" 三个前缀,可以明确指定字面量在运行时是什么编码
  3. 如何从 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 的程序反而会导致乱码……

  4. 为什么 Unicode 的码位 U+D800 ~ U+DFFF 没有分配字符?

    为了确保 UTF-16 编码始终被兼容,这又是一个具体实现反而影响标准建立的例子。Unicode标准不是一蹴而就的,而是经过了一次扩充设计,最早就是16位编码(类似UTF-16),而后发现不够了又再进行扩充,所以UTF-16的高位和地位代理项其实是一个历史遗留问题。

    同样的,为什么 Unicode 只有 0x10FFFF 个字符,而不是完整的 2^32?——因为 UTF-16 只能表达这么多。

  5. Unicode 相关名词的解释

    名词解释
    UCSUniversal Character Set,统一字符集,可以理解为是 ISO 的专家为 Unicode 起的别名。
    UTFUnicode Transformation Format,统一码传输格式,包含 Unicode 标准规定的 3 个编码方法。
    SCSUStandard Compression Scheme for Unicode,统一码标准压缩方案,虽然在源代码里最不常见,但它是 Unicode 标准规定的 4 个编码方案之一,主要用于传输,例如电子邮件。
    BOMByte Order Mark,字节序标记,用于在某些情形下在 UTF 传输前指明字节序。

    官方FAQ:http://unicode.org/faq/utf_bom.html#bom1

  6. 推荐做法

    除非你要做一些字处理程序,否则对于简单的存储、传输、搜索匹配等需求,直接使用 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 串。

  7. 如何让Windows自带的命令行(CMD、Powershell)默认使用UTF-8编码?

    阅读此博客:https://blog.youkuaiyun.com/u014132143/article/details/126213522

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值