mmu*_*phy 3 c++ string implementation utf-8 utf-16
我前段时间无意中听到有关如何创建模板化字符串类的讨论,不应该使用strcmp,strcpy和strlen作为可以使用UTF8和UTF16的模板化字符串类.我记得,你应该使用来自algorithm.h的函数,但是,我不记得实现是怎么回事,或者为什么会这样.有人可以解释一下使用哪些功能,如何使用它们以及为什么?
模板化字符串类的示例将是诸如此类的
String<UTF8> utf8String;
String<UTF16> utf16String;
Run Code Online (Sandbox Code Playgroud)
这是UTF8将是unsigned char的地方,而UTF16是unsigned short.
首先,C++不需要额外的字符串类.可能已经有数百或数千个字符串类已经开发出来,而你的字符串类不会改善这种情况.除非你纯粹为了你的启发而做这件事,否则你应该长时间地思考,然后决定不写一个新的.
您可以使用std::basic_string<char>保存UTF-8编码单元序列,std::basic_string<char16_t>持有UTF-16编码单元序列,std::basic_string<char32_t>持有UTF-32代码单元序列等C++甚至还提供这些类型的短,方便的名字:string,u16string,和u32string.basic_string已经通过提供成员函数来解决您在这里提出的问题,这些函数用于复制,比较和获取适用于您使用的任何代码单元的字符串的长度.
我想不出有任何好的理由让新代码不与遗留代码连接,而是使用其他任何东西作为字符串的规范存储类型.即使您与使用其他内容的遗留代码进行交互,如果该接口的表面区域不大,您应该仍然使用其中一种标准类型,而不是其他任何东西,当然,如果您与遗留代码接口无论如何,你将使用那种传统类型,而不是编写自己的新类型.
随着中说,之所以不能使用strcmp,strcpy和strlen你的模板字符串类型是,它们都对空终止字节序列进行操作.如果您的代码单元大于一个字节,则在实际终止空代码单元之前可能存在零的字节(假设您根本不使用空终止,这可能不应该).考虑字符串"Hello"的UTF-16表示的字节(在小端机器上).
48 00 65 00 6c 00 6c 00 6f 00
Run Code Online (Sandbox Code Playgroud)
由于UTF-16使用16位代码单元,因此字符"H"最终存储为两个字节48 00.通过假设第一个空字节为结尾对上述字节序列进行操作的函数将假设第一个字符的后半部分标记整个字符串的结尾.这显然不起作用.
所以strcmp,strcpy和strlen是可以更普遍实现的算法都专门版本.由于它们只使用字节序列,并且您需要使用代码单元序列可能大于一个字节的代码单元序列,因此您需要使用可以与任何代码单元一起使用的通用算法.标准库提供了许多通用算法.以下是我对更换这些str*功能的建议.
strcmp比较两个代码单元序列,如果两个序列相等,则返回0;如果第一个按字典顺序小于第二个,则返回正数,否则返回负数.标准库包含通用算法lexicographical_compare,它几乎完成相同的操作,但如果第一个序列按字典顺序小于第二个序列则返回true,否则返回false.
strcpy复制一系列代码单元.您可以使用标准库的copy算法.
strlen获取指向代码单元的指针,并在找到空值之前计算代码单元的数量.如果您需要此函数而不是只告诉您字符串中代码单元数的函数,则可以find通过将null值作为要查找的值传递来实现算法.如果你想找到序列的实际长度,你的类应该只提供一个size方法,直接访问你的类在内部使用的任何方法来存储大小.
与str*函数不同,我建议的算法采用两个迭代器来划分代码单元序列; 一个指向序列中的第一个元素,一个指向序列的最后一个元素之后的位置.这些str*函数只接受指向第一个元素的指针,然后假设序列一直持续到它找到的第一个零值代码单元.当您实现自己的模板化字符串类时,最好也不要使用显式的null终止约定,只需提供一个end()为字符串提供正确结束点的方法.
| 归档时间: |
|
| 查看次数: |
1437 次 |
| 最近记录: |