如何获得std :: string的准确长度?

时间:2015-07-27 11:53:53

标签: c++ string std

我正在使用此代码修剪长std::string以使其适合文本容器。

std::string AppDelegate::getTrimmedStringWithRange(std::string text, int range)
{
    if (text.length() > range)
    {
        std::string str(text,0,range-3);
        return str.append("...");
    }
    return text;
}

但是对于HINDI "हिन्दी"之类的其他语言,std::string的长度是错误的。

我的问题是如何在所有测试用例中检索std :: string的准确长度。

由于

3 个答案:

答案 0 :(得分:7)

std::string的长度并非“错误”;你只是误解了它的含义。 std::string存储字节,而不是您选择的编码中的“字符”。它兴高采烈地不了解那一层。因此,std::string的长度是它包含的字节数。

要计算这样的“字符”,您需要一个支持分析所选编码的库,无论是什么。

只有当您选择的编码与ASCII兼容时,您才能计算字节并完成它。

答案 1 :(得分:6)

假设您使用的是UTF-8,您可以将字符串转换为简单的(hah!)Unicode并计算字符数。我从rosettacode抓住了这个例子。

#include <iostream>
#include <codecvt>
int main()
{
    std::string utf8 = "\x7a\xc3\x9f\xe6\xb0\xb4\xf0\x9d\x84\x8b"; // U+007a, U+00df, U+6c34, U+1d10b
    std::cout << "Byte length: " << utf8.size() << '\n';
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
    std::cout << "Character length: " << conv.from_bytes(utf8).size() << '\n';
}

答案 2 :(得分:2)

如注释中所述,长度将返回以utf8编码的字符串的字节数。在这种多字节编码中,非ascii字符编码为2到6个字节,因此你的utf8字符串长度看起来比实际的unicode字母长。

解决方案1 ​​

如果你有很多长字符串,你可以将它们保存在utf8中。 utf8编码使得查找额外的多字节字符变得相对容易:它们都以二进制的10xxxxxx开头。因此,计算这些额外字节的数量,并从字符串长度

中减去它
cout << "Bytes: " << s.length() << endl;
cout << "Unicode length " << (s.length() - count_if(s.begin(), s.end(), [](char c)->bool { return (c & 0xC0) == 0x80; })) << endl;

解决方案2

如果需要更多处理而不仅仅计算长度,您可以考虑在标准库中使用wstring_convert::from_bytes()将字符串转换为wstring。 wstring的长度应该是你期望的。

wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
wstring w = cv.from_bytes(s);
cout << "Unicode length " << w.length() << endl;

注意:linux上的 wstring基于32位wchar_t,其中一个宽字符可以包含所有unicode characeter集。所以这很完美。然而,在Windows上,wchar_t仅为16位,因此某些字符可能仍需要多字编码。幸运的是,所有hindi characters都在U + 0000到U + D7FF的范围内,可以在一个16位字上进行编码。所以也应该没问题。