5

据我所知,linux 使用 UTF-8 编码。这意味着我可以std::string用来处理字符串吗?只是编码将是 UTF-8。

现在在 UTF-8 上,我们知道有些字符是 1 个字节,有些是 2,3.. 字节。我的问题是:如何使用 C++ 在 Linux 上处理 UTF-8 编码的字符串?

特别是:您将如何获得以字节(或字符数)为单位的字符串长度?你将如何遍历字符串?等等

我问的原因是,正如我所说的 UTF-8 字符可能不止一个字节,对吗?很明显myString[7]and myString[8]- 可能不是指两个不同的字符。同样事实是 UTF-8 字符串是十个字节,它的字符数并没有说太多,对吧?

4

5 回答 5

5

您不能使用std::string. string,尽管它的名字,只是(多)字节的容器。它不是文本存储的类型(除了字节缓冲区显然可以存储任何对象,包括文本)。它甚至不存储字符(char是一个字节,而不是一个字符)。

如果您想实际处理(而不仅仅是存储)Unicode 字符,则需要在标准库之外冒险。传统上,这是由ICU等库完成的。

然而,虽然这是一个成熟的库,但它的 C++ 接口很糟糕。Ogonek采用了现代方法。它还没有建立得很好并且仍在进行中,但提供了一个更好的界面。

于 2013-10-04T13:27:30.700 回答
3

可能希望在操作之前将 UTF-8 编码的字符串转换为某种固定宽度的编码。但这取决于你想要做什么。

要获取 UTF-8 字符串的字节长度,只需str.size(). 要获得 chars 的长度稍微困难一些,但您可以通过忽略字符串中值 >= 0x80 且 < 0xC0 的任何字节来获得它。在 UTF-8 中,这些值总是尾随字节。所以计算这样的字节数并从字符串的大小中减去它。

以上确实忽略了组合字符的问题。它确实取决于您对角色的定义。

于 2013-10-04T13:36:39.847 回答
2

这里有多个概念:

  1. UTF-8 编码的长度(以字节为单位)
  2. 使用的 Unicode 代码点数(= 0x80..0xbf 范围之外的 UTF-8 字节数)
  3. 字形的数量(西方语言中的“字符”)
  4. 显示时占用的屏幕空间

通常,您只对 1.(用于内存要求)和 4.(用于显示)感兴趣,其他没有实际应用。

可以从渲染上下文中查询屏幕空间的大小。请注意,这可能会根据上下文而改变(例如,阿拉伯字母会在单词的开头和结尾改变形状),因此如果您在进行文本输入,您可能需要执行额外的技巧来为用户提供一致的体验。

于 2013-10-04T14:59:51.523 回答
1

我正在使用libunistring库,它可以帮助您处理所有问题。

例如,这里是简单的字符串长度(以 utf-8 字符表示)函数:

size_t my_utf8_strlen(uint8_t *str) {
    if (str == NULL) return 0;
    if ((*str) == 0) return 0;

    size_t length = 0;
    uint8_t *current = str;
    // UTF-8 character.
    ucs4_t ucs_c = UNINAME_INVALID;

    while (current && *current) {
        current = u8_next(&ucs_c, current);
        length++; 

        // Broken character.
        if (ucs_c == UNINAME_INVALID || ucs_c == 0xfffd) 
        return length - 1;
    }

    return length;
}

// Use case
std::string test;

// Loading some text in `test` variable.
// ...

std::cout << my_utf8_strlen(&test[0]) << std::endl;
于 2013-10-04T14:29:13.817 回答
0

您可以根据第一个字节的主要x位确定它: UTF-8,描述

于 2013-10-04T13:27:06.803 回答