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