如何在utf8中获取代码点文字

时间:2017-07-31 15:16:56

标签: c++ utf-8 c++17

我刚刚意识到,C ++ 17的u8字符前缀不适用于所有 utf8代码点,仅适用于ASCII部分。

来自cppreference

  

UTF-8字符文字,例如u8'a'。这样的文字具有类型char,并且该值等于c-char的ISO 10646代码点值,前提是代码点值可用单个UTF-8代码单元表示。如果c-char不在Basic Latin或C0 Controls Unicode块中,则程序格式不正确。

auto hello = u8'嗨';     // ill-formed
auto world = u8"世";     // not a character
auto what = 0xE7958C;    // almost human-readable
auto wrong = u8"錯"[0];  // not even correct

如何在utf8中简洁地获得代码点文字?

编辑:对于想知道如何存储utf8代码点的人们,我认为合理的方式就像the way Golang does it。基本思想是当只需要一个代码点时,以32位类型存储单个代码点。

EDIT2:根据有用评论提出的论点,没有理由将编码的utf8一直保留在32位类型中。要么解码,要么是utf32并且前缀为U,要么将其编码为字符串,前缀为u8

2 个答案:

答案 0 :(得分:7)

如果您需要代码点,则应使用char32_tU作为前缀:

auto hello = U'嗨';

UTF-8将代码点存储为8位代码单元序列。 C ++中的char是代码单元,因此它不能存储整个Unicode代码点。如果您提供需要存储多个代码单元的代码点,则字符文字的u8前缀不会编译,因为字符文字只产生一个char

如果你想要一个以UTF8编码的单一Unicode码点,那么你想要的是字符串文字,而不是字符文字:

auto hello = u8"嗨";
  

我认为合理的方式就像Golang一样。

嗯,你没有使用Go,是吗?

在C ++中,如果你要求一个字符文字,那么你指的是那个大小类型的单个对象。 u8字面值总是char。它的类型不会根据文字中的内容而变化。你问了一个字符文字,你得到一个字符文字。

从您链接的网站,很明显Go实际上并没有UTF-8字符文字的概念。它只有字符文字,所有都是32位值。实际上,Go中的所有字符文字都表现得像U''

答案 1 :(得分:1)

在C ++中,字符文字正好是一个字符对象。 C ++术语中的字符对象对应于Unicode中的代码单元。 UTF-8的某些代码点需要多个代码单元。因此,并非所有UTF-8代码点都可以由单个字符对象表示。可表示的代码点是Basic Latin和C0 Control块。

要表示任何UTF-8代码点,您需要一个代码单元数组,即字符串。字符串文字有一个类似的前缀:u8"☺"