用C/ c++转义unicode字符

Escaping unicode characters with C/C++

本文关键字:unicode 字符 转义 c++      更新时间:2023-10-16

我需要将输入字符串中的unicode字符转义为UTF-16或UTF-32转义序列。例如,输入字符串字面值"Eat, drink, 愛"应转义为"Eat, drink, u611b"。下面是排序表中的规则:

逃脱 | Unicode代码点


'u' HEX HEX HEX | u +0到u +FFFF范围内的Unicode码位

包含对应的十六进制编码值。

'U' HEX HEX HEX HEX HEX HEX HEX HEX | 范围内的Unicode码位U+0到U+10FFFF(含)对应于编码的十六进制价值。


通常检测Unicode字符很简单,因为如果ASCII:

第二个字节为0:
L"a" = 97, 0

,它不会被转义。对于Unicode字符,第二个字节永远不会是0:

L"愛" = 27, 97

,转义为u611b。但是我如何检测UTF-32字符串,因为它要以不同于UTF-16的8十六进制数字进行转义?

它不像检查字符串大小那么简单,因为UTF-16字符是多字节的,例如:

L"प्रे" = 42, 9, 77, 9, 48, 9, 71, 9

我的任务是转义未转义的输入字符串字面量,如Eat, drink, 愛,并将它们存储到磁盘中,以转义的字面量形式Eat, drink, u611b (UTF-16示例)如果我的程序找到一个UTF-32字符,它也应该以U8902611b (UTF-32示例)的形式转义,但我找不到某种方式知道我是否在输入字节数组中处理UTF-16或UTF-32。那么,如何在wchar_t字符串或字节数组中可靠地区分UTF-32和UTF-16字符呢?

你的问题有很多问题,我尽量回答最重要的。

Q。我有一个像"Eat, drink, 愛"这样的c++字符串,它是UT8-8, UTF-16还是UTF-32字符串?
A.这是实现定义的。在许多实现中,这将是一个UTF-8字符串,但这不是标准所要求的。参考你的文档

Q。我有一个像L"Eat, drink, 愛"一样宽的c++字符串,它是UT8-8, UTF-16还是UTF-32字符串?
A.这是实现定义的。在许多实现中,这将是一个UTF-32字符串。在其他一些实现中,它将是一个UTF-16字符串。这两项都不是标准强制要求的。参考你的文档

Q。我怎么能有便携式UT8-8, UTF-16或UTF-32 c++字符串字面值?
在c++ 11中有一种方法:

u8"I'm a UTF-8 string."
u"I'm a UTF-16 string."
U"I'm a UTF-32 string."
在c++ 03中,没有这样的运气。

Q。字符串"Eat, drink, 愛"是否至少包含一个UTF-32字符?
答:没有UTF-32(以及UTF-16和UTF-8)这样的字符。有UTF-32等字符串。它们都包含Unicode字符。

Q。Unicode字符到底是什么?
a .它是Unicode标准定义的编码字符集的一个元素。在c++程序中,它可以用各种方式表示,最简单和直接的方式是用单个32位整数值对应字符的代码点。(为了简单起见,我在这里忽略了复合字符,并将"字符"answers"代码点"等同起来,除非另有说明)。

Q。给定一个Unicode字符,如何转义它?
A.审视它的价值。如果在256和65535之间,打印一个2字节(4个十六进制数字)转义序列。如果大于65535,打印一个3字节(6个十六进制数字)的转义序列。否则,按正常方式打印。

Q。给定一个UTF-32编码的字符串,我如何将其分解为字符?
a .字符串的每个元素(称为代码单元)对应一个字符(码点)。一个接一个地拿。没有什么特别需要做的。

Q。给定一个UTF-16编码的字符串,如何将其分解为字符?
A.在 0xD800到0xDFFF范围之外的值(代码单位)对应于具有相同值的Unicode字符。对于每个这样的值,打印一个普通字符或一个2字节(4个十六进制数字)转义序列。 0xD800到0xDFFF范围内的值以成对的方式分组,每对表示U+10000到U+10FFFF范围内的单个字符(代码点)。对于这样的一对,打印一个3字节(6个十六进制数字)转义序列。要将一对(v1, v2)转换为它的字符值,使用以下公式:

c = (v1 - 0xd800) >> 10 + (v2-0xdc00)

注意pair的第一个元素必须在0xd800的范围内。0xdbff和第二个在0xdc00..0xdfff,否则是病态的。

Q。给定一个UTF-8编码的字符串,如何将其分解为字符?
答:UTF-8编码比UTF-16编码稍微复杂一点,我不会在这里详细说明。网上有很多描述和示例实现,请查阅。

Q。我的 L"प्रे" 字符串是怎么回事?
a .它是一个复合字符,由四个Unicode码点U+092A, U+094D, U+0930, U+0947组成。请注意,它与用代理对表示的高代码点不同,这在答案的UTF-16部分中有详细说明。这是一个"字符"与"代码点"不一样的情况。分别转义每个代码点。在这个抽象层次上,您处理的是代码点,而不是实际的字符。当你为用户显示字符时,或者在打印文本中计算它们的位置时,字符就会发挥作用,但在处理字符串编码时则不会。