当前位置: 首页 > 知识库问答 >
问题:

将Unicode字符串作为字符循环

端木淇
2023-03-14

对于以下字符串,大小输出不正确。为什么会这样?我该如何解决?

string str = " ██████";
cout << str.size();
// outputs 19 rather than 7

我试着逐字符遍历str,这样我就可以把它读入向量

共有2个答案

戎元忠
2023-03-14

std::string仅包含1字节长的字符(通常为8位,包含UTF-8字符),您需要wchar\u t和std::wstring来实现您想要的:

std::wstring str = L" ██████";
std::cout << str.size();

尽管这打印了7个(一个空格和6个unicode字符)。请注意字符串文字之前的L,因此它将被解释为宽字符串。

鄢英哲
2023-03-14

basic_字符串的size()和length()成员返回以基础字符串为单位的大小,而不是可见字符数。要获得预期数量:

  • 对于不包含非BMP、组合字符和连接字符的非常简单的字符串,请使用带前缀的UTF-16
  • 对于不包含任何组合或连接字符的非常简单的字符串,请使用带前缀的UTF-32
  • 规范化字符串并对任意Unicode字符串进行计数

<代码>”██████“是一个空格,后跟一系列6u2588个字符。您的编译器似乎将UTF-8用于std::string。UTF-8是一种可变长度编码,许多字母使用多个字节编码(因为很明显,单用一个字节编码不能超过256个字符). 在UTF-8中,U 0800和U FFFF之间的代码点由3个字节编码。所以UTF-8中字符串的长度是16*3=19字节。

您可以使用像这样的任何Unicode转换器进行检查,并看到字符串在UTF-8中被编码为20 E2 96 88 E2 96 88 E2 96 88 E2 96 88,您还可以循环遍历字符串的每个字节以检查

如果你想知道字符串中可见字符的总数,那么就要复杂得多,churill的解决方案也不起作用。阅读推特上的示例

如果你使用最基本的字母、数字和标点符号之外的任何东西,情况会变得更加混乱。虽然许多人使用多字节汉字来举例说明这些问题,但推特发现,重音元音最容易引起混淆,因为说英语的人只是希望它们能起作用。举个例子:“café”这个词。事实证明,有两个字节序列看起来完全相同,但使用的字节数不同:

café  0x63 0x61 0x66 0xC3 0xA9        Using the “é” character, called the “composed character”.
café  0x63 0x61 0x66 0x65 0xCC 0x81   Using the combining diacritical, which overlaps the “e”

您需要一个像ICU这样的Unicode库来规范化字符串和计数。例如,Twitter使用规范化表单C

由于您只对似乎不在BMP之外且不包含任何组合字符的框绘制字符感兴趣,因此UTF-16和UTF-32将起作用。与std::string一样,std::wstring也是basic_string,并且没有强制编码。在大多数实现中,它通常是UTF-16(Windows)或UTF-32(*nix),因此您可以使用它,但它不可靠,并且取决于源代码编码。更好的方法是使用std::u16stringstd::basic_string

std::wstring wstr     = L" ██████";
std::u16string u16str = u" ██████";
std::u32string u32str = U" ██████";
std::cout << str.size();    // may work, returns the number of wchar_t characters
std::cout << u16str.size(); // always returns the number of UTF-16 code units
std::cout << u32str.size(); // always returns the number of UTF-32 code units

如果您对如何解决所有Unicode字符的问题感兴趣,请继续阅读下面的内容

上面提到的“café”问题提出了一个问题,即如何计算推特字符串“café”中的字符。在人眼看来,长度显然是四个字符。根据数据的表示方式,可以是5个或6个UTF-8字节。推特不想因为我们使用UTF-8或者API客户端使用更长的表示形式而惩罚用户。因此,无论发送哪种表示,推特都会将“café”计算为四个字符。

[...]

推特使用文本的标准化形式C(NFC)计算推特的长度。与长格式版本(0x65 0xCC 0x81)相比,这种规范化更倾向于使用完全组合的字符(café示例中的0xC3 0xA9)。Twitter还统计文本中的代码点数量,而不是UTF-8字节。café示例中的0xC3 0xA9是一个代码点(U 00E9),在UTF-8中编码为两个字节,而0x65 0xCC 0x81是两个编码为三个字节的代码点

推特-计数字符

另请参见

  • 当“Zoë”!==“Zoë”。或者为什么需要规范化Unicode字符串

 类似资料:
  • 问题内容: 我需要将unicode字符串转换为具有以unicode编码的非ascii字符的字符串。例如,字符串“汉字Max”应显示为“ \ u6F22 \ u5B57 Max”。 我尝试过的 的不同组合 新的String(sourceString.getBytes(encoding1),encoding2) Apache StringEscapeUtils也会转义ascii字符,例如双引号 Str

  • 我需要读入带有unicode转义的标准ascii样式字符串,并将其转换为包含utf8编码等价物的std::字符串。因此,例如“\u03a0”(包含6个字符的std::字符串)应转换为包含两个字符的std::字符串,分别为0xCE和0xA0,以原始二进制格式。 如果有一个简单的答案使用icu或boost我会很高兴,但我还没有找到一个。 (这类似于将Unicode字符串转换为转义ASCII字符串,但注

  • 想改进这个问题吗?通过编辑这篇文章添加细节并澄清问题。 我有一个特殊字符的输入字符串,如 如果我打印这个字符串,它将返回:正确的。 我想将此字符串转换为特殊字符的Unicode字符串,例如“1a 2\uxx00\uxx01\uxx02......”这样当我打印这个新字符串时,kt也应该给出 我想将其转换为Unicode的原因是我将把它传递给JAVA代码,该代码将把这些Unicode字符写入PDF文

  • 问题内容: 这个问题看起来很尴尬,但我一直找不到答案。 与下面的C#代码行等效的PHP是什么? 此示例创建一个带有单个Unicode字符的字符串,该字符串的“ Unicode数值”为十六进制的1000(十进制的4096)。 也就是说,在PHP中,如何创建一个具有“ Unicode数值”已知的Unicode字符的字符串? 问题答案: 因为JSON直接支持语法,所以我想到的第一件事是: 另一种选择是使

  • 问题内容: 您能否详细说明Python中字节字符串和Unicode字符串之间的区别。我读过这个: 字节码只是将源代码转换为字节数组 这是否意味着Python具有自己的编码/编码格式?还是使用操作系统设置?我不明白 你能解释一下吗?谢谢! 问题答案: 没有python不使用自己的编码。它将使用它有权访问并指定的任何编码。中的字符代表一个unicode字符。但是,要表示256个以上的字符,单个unic

  • 问题内容: 我有一个包含unicode字符等的字符串,以某种方式不被我接收,但被作为接收。如何将其转换回unicode? 显然不是答案。那是什么 问题答案: Unicode转义仅适用于unicode字符串,因此 实际上是由6个字符组成的字符串:“ \”,“ u”,“ 2”,“ 0”,“ 2”,“ 6”。 要从中制作出unicode,请使用: