我注意到std :: string的length方法返回字节长度,std :: u16string中的相同方法返回2字节序列的数量.
我还注意到,当字符或代码点在BMP之外时,长度返回4而不是2.
此外,Unicode转义序列仅限于\ unnnn,因此转义序列不能插入U + FFFF上方的任何代码点.
换句话说,似乎不支持BMP之外的代理对或代码点.
鉴于此,使用理解UTF-8,UTF-16,代理对等的非标准字符串操作库是否被接受或推荐?
我的编译器是否有错误或我是否错误地使用标准字符串操作方法?
例:
/*
* Example with the Unicode code points U+0041, U+4061, U+10196 and U+10197
*/
#include <iostream>
#include <string>
int main(int argc, char* argv[])
{
std::string example1 = u8"A?";
std::u16string example2 = u"A?";
std::cout << "Escape Example: " << "\u0041\u4061\u10196\u10197" << "\n";
std::cout << "Example: " << example1 << "\n";
std::cout << "std::string Example length: " << example1.length() << "\n";
std::cout << "std::u16string Example length: " << example2.length() << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我用GCC 4.7编译时得到的结果:
Escape Example: A??6?7
Example: A?
std::string Example length: 12
std::u16string Example length: 6
Run Code Online (Sandbox Code Playgroud)
std::basic_string
是面向代码单元,而不是面向字符.如果您需要处理代码点,您可以转换为char32_t,但标准中没有任何内容可用于更高级的Unicode功能.
\UNNNNNNNN
除了直接输入非BMP代码点之外,您还可以使用转义序列(假设您正在使用支持它们的源代码编码).
根据您的需要,这可能是您需要的所有Unicode支持.许多软件不需要比字符串的基本操作更多,例如那些可以直接在代码单元上轻松完成的操作.对于稍高级别的需求,您可以将代码单元转换为代码点并对其进行处理.对于更高级别的需求,例如处理字形集群,将需要额外的支持.
我想说这意味着标准中有足够的支持来表示Unicode数据和执行基本操作.无论第三方库用于更高级别的功能,都应该建立在标准库上.随着时间的推移,标准也可能包含更多更高级别的功能.
由于过早判断的风险,在我看来标准中使用的语言略有模糊(虽然最终结论很清楚,最后见):
在char16_t文字的描述中(即u"..."
您的示例中的文字),文字的大小定义为:
char16_t字符串文字的大小是转义序列,通用字符名称和其他字符的总数,加上需要代理项对的每个字符一个,加上一个用于终止u'\ 0'.
脚注进一步澄清:
[注意:char16_t字符串文字的大小是代码单元的数量,而不是字符数. - 尾注]
这意味着字符和代码单元的定义.代理对是一个字符,但是两个代码单元.
但是,(由其衍生的)length()
方法的描述声称:std::basic_string
std::u16string
返回字符串中的字符数,即std :: distance(begin(),end()).它与size()相同.
如图所示,length()
使用单词character的描述意味着char16_t
调用代码单元的定义.
但是,所有这些的结论是:长度被定义为代码单元,因此您的编译器符合标准,并且将继续需要特殊库来提供正确的字符计数.
我使用下面的参考:
归档时间: |
|
查看次数: |
4226 次 |
最近记录: |