2014-09-29 139 views
6

我在写一些类似于atoi()strtoll()的字符串转换函数。我想包括我的函数的一个版本,它可以接受char16_t *或char32_t *,而不仅仅是char *或wchar_t *。C11 Unicode支持

我的函数可以正常工作,但是当我写它时,我意识到我不明白char16_t或char32_t是什么。我知道标准只要求它们是一个至少16或32位的整数类型,但其含义是它们是UTF-16或UTF-32。我也知道该标准定义了几个函数,但它们不包括任何* get或* put函数(就像他们在C99中添加wchar.h时所做的那样)。

所以我想知道:他们期望我用char16_t和char32_t做什么?

+1

转换为UTF-8,还有什么? – Deduplicator 2014-09-29 18:58:04

+0

@Deduplicator:如果这就是他们希望你对他们做的事情,你会认为他们会给你这样做的功能...... – 2014-09-29 19:16:31

+0

你打算不仅支持'0..9'(U + 0030 .. U + 0039)(也可能是'A..Z/a..z',最高级别为最高级别,基数为36),但在完整的Unicode表格中也标记为“Numeric”的所有其他字符? 'Coz这包括印刷形式(超级和下标,圆圈数字高达20(!))和脚本特定形式(阿拉伯数字,希伯来数字),以及罗马数字,古希腊和“计数杆”等等。 – usr2564301 2014-09-29 20:56:55

回答

9

这是一个很好的问题,没有明显的答案。

在C11中添加的uchar.h类型和功能在很大程度上是无用的。它们仅支持新类型(char16_tchar32_t)与特定于语言环境的实现定义的多字节编码之间的转换,这些映射除非区域设置基于UTF-8,否则不会完整。不支持有用的转换(来自wchar_t以及来自/来自UTF-8的有用转换)。当然,由于这些转换是由相关的RFC/UCS/Unicode标准100%指定的,因此您可以推出自己的转换到UTF-8 /从UTF-8转换,但要小心:大多数人执行错误并且存在危险的错误。

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

+0

你知道多少它限制了可移植性,以承担多字节编码是UTF-8? (我的意思是,这是类似于“标准允许非2的补码”,这在实践中可能经常被忽略,或者这真的是我应该担心的事情吗?) – mafso 2014-09-29 20:43:47

+0

@mafso:我不认为* internal *表示作为UTF8的字符串是潜在的可移植性问题。但是如果没有可移植的(几乎可以肯定“每个定义”)方式来显示结果,你将如何显示文本? – usr2564301 2014-09-29 20:49:04

+1

@Jongware:我知道它不可移植(理论上)。但是这种“特定于语言环境的多字节编码”和“特定于语言环境的宽字符编码”的东西是用C89进行标准化的,而Unicode编码并不像今天这样被广泛使用(IIRC他们甚至没有当时标准化)。我的问题是,如果它现在可以安全地假设在编程中使用Unicode编码。 – mafso 2014-09-29 20:57:38

3

测试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() F。或空白检测。

  3. 对于your_atof()转换是一个类似的方式。

  4. 恢复本地。

+0

不要忘记,UTF-16和UTF-32都有大端和小端的变体,你可能会关心。 – JohnH 2014-09-29 20:29:30

+0

@JohnH:这如何与UTF-32相关? – mafso 2014-09-29 20:33:46

+1

@mafso大/小端变体确实适用于UTF-16和UTF-32。在_byte_级别,2或4字节的顺序非常不符合软件的字节顺序。这可以使用各种字节重新排序功能来纠正。使用Unicode代码点> = 0x10000,编码为UTF-16时,2个UTF-16代理的顺序有时会以大或小的顺序排列。其中只有一个是正确的(忘记哪个)。当使用错误的时候,它应该标记为编码错误,虽然有些系统是宽松的(非投诉)。 – chux 2014-09-29 21:01:22

0

这个问题可能有点老了,但我想谈谈与char16_tchar32_t支持实现你的功能。

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

我真的没有看过C11标准库中的Unicode设施,但如果他们没有提供将这些类型转换为UTF-32的合适方法,那么您可以使用第三方库为您进行转换。

ICU,这是由IBM启动,然后由Unicode联盟采用。这是一个功能丰富且稳定的库,已经存在了很长时间。

我最近为C89创建了一个UTF库(UTFX),您也可以使用它。这是非常简单和轻量级的,单元测试和记录。您可以放弃,或者使用它来了解更多关于UTF转换如何工作的信息。