C11 Unicode支持
我正在写一些类似于atoi()
或strtoll()
字符串转换函数。 我想要包含一个我的函数版本,它接受char16_t *或char32_t *而不仅仅是char *或wchar_t *。
我的function很好,但正如我写的那样,我意识到我不明白char16_t或char32_t是什么。 我知道标准只要求它们分别是至少16位或32位的整数类型,但暗示它们是UTF-16或UTF-32。
我也知道标准定义了几个函数,但它们没有包含任何* get或* put函数(就像它们在C99中的wchar.h
中添加时那样)。
所以我想知道:他们期望我用char16_t和char32_t做什么?
这是一个很好的问题,没有明显的答案。
在C11中添加的uchar.h
类型和函数基本上没用。 它们仅支持新类型( char16_t
或char32_t
)与特定于语言环境的实现定义的多字节编码之间的转换,除非语言环境基于UTF-8,否则这些映射不会完整。 不支持有用的转换(来自/来自wchar_t
,来自/来自UTF-8)。 当然,您可以自行转换为UTF-8的转换,因为这些转换是由相关的RFC / UCS / Unicode标准100%指定的,但要小心:大多数人错误地实现它们并且有危险的错误。
请注意,UTF-8,UTF-16和UTF-32文字(分别为u8
, u
和U
)的新编译器级function可能很有用; 您可以使用您自己的函数以有意义的方式处理结果字符串,这些方法完全不依赖于语言环境。 但在我看来,C11中对Unicode的库级支持基本上没用。
测试ASCII范围内的UTF-16或UTF-32章程是“通常的”10位数之一,+, – 或“正常”白色空间很容易做到以及转换'0'-'9'
到一个数字。 鉴于此, atoi_utf16/32()
继续像atoi()
。 只需一次检查一个角色。
测试一些其他 UTF-16 / UTF-32是数字还是空白 – 这更难。 代码需要一个扩展的isspace(), isdigit()
,如果需要的语言环境可用,可以切换语言环境( setlocale()
)。 (注意:可能需要在函数完成时恢复语言环境。
转换通过isdigit()
但不是通常的10个值的字符是有问题的。 无论如何,这似乎甚至不被允许。
转换步骤:
-
将语言环境设置为UTF-16 / UTF-32的相应语言环境。
-
使用
isspace()
进行空白区域检测。 -
转换与
your_atof()
类似。 -
恢复本地。
这个问题可能char16_t
,但我想通过char16_t
和char32_t
支持来实现你的函数。
最简单的方法是使用char32_t
类型编写strtoull
函数(称之为strtoull_c32
)。 这使得解析unicode更容易,因为UTF-32
每个字符占用四个字节。 然后通过内部将UTF-8
和UTF-16
编码转换为UTF-32
并将它们传递给strtoull_c32
来实现strtoull_c32
和strtoull_c32
。
老实说,我没有查看C11标准库中的Unicode工具,但如果它们没有提供将这些类型转换为UTF-32
的合适方法,那么您可以使用第三方库为您进行转换。
有ICU ,由IBM启动,然后由Unicode Consortium采用。 它是一个function丰富且稳定的库,已经存在了很长时间。
我最近为C89创建了一个UTF库( UTFX ),您也可以使用它。 它非常简单,重量轻,经过unit testing和记录。 您可以放弃,或者使用它来了解有关UTF转换如何工作的更多信息。