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_tchar32_t )与特定于语言环境的实现定义的多字节编码之间的转换,除非语言环境基于UTF-8,否则这些映射不会完整。 不支持有用的转换(来自/来自wchar_t ,来自/来自UTF-8)。 当然,您可以自行转换为UTF-8的转换,因为这些转换是由相关的RFC / UCS / Unicode标准100%指定的,但要小心:大多数人错误地实现它们并且有危险的错误。

请注意,UTF-8,UTF-16和UTF-32文字(分别为u8uU )的新编译器级function可能很有用; 您可以使用您自己的函数以有意义的方式处理结果字符串,这些方法完全不依赖于语言环境。 但在我看来,C11中对Unicode的库级支持基本上没用。

测试ASCII范围内的UTF-16或UTF-32章程是“通常的”10位数之一,+, – 或“正常”白色空间很容易做到以及转换'0'-'9'到一个数字。 鉴于此, atoi_utf16/32()继续像atoi() 。 只需一次检查一个角色。

测试一些其他 UTF-16 / UTF-32是数字还是空白 – 这更难。 代码需要一个扩展的isspace(), isdigit() ,如果需要的语言环境可用,可以切换语言环境( setlocale() )。 (注意:可能需要在函数完成时恢复语言环境。

转换通过isdigit()但不是通常的10个值的字符是有问题的。 无论如何,这似乎甚至不被允许。

转换步骤:

  1. 将语言环境设置为UTF-16 / UTF-32的相应语言环境。

  2. 使用isspace()进行空白区域检测。

  3. 转换与your_atof()类似。

  4. 恢复本地。

这个问题可能char16_t ,但我想通过char16_tchar32_t支持来实现你的函数。

最简单的方法是使用char32_t类型编写strtoull函数(称之为strtoull_c32 )。 这使得解析unicode更容易,因为UTF-32每个字符占用四个字节。 然后通过内部将UTF-8UTF-16编码转换为UTF-32并将它们传递给strtoull_c32来实现strtoull_c32strtoull_c32

老实说,我没有查看C11标准库中的Unicode工具,但如果它们没有提供将这些类型转换为UTF-32的合适方法,那么您可以使用第三方库为您进行转换。

有ICU ,由IBM启动,然后由Unicode Consortium采用。 它是一个function丰富且稳定的库,已经存在了很长时间。

我最近为C89创建了一个UTF库( UTFX ),您也可以使用它。 它非常简单,重量轻,经过unit testing和记录。 您可以放弃,或者使用它来了解有关UTF转换如何工作的更多信息。