C ++子串的多字节字符(C++ substring multi byte characters)

2019-09-17 16:29发布

我有这样的std :: string其中包含一些字符跨越多个字节。

当我做一个子上这个字符串,输出是无效的,因为ofcourse,这些字符计为2个字符。 在我看来,我应该使用一个wstring的替代,因为它会作为一个元素,而不是更多的这些字符存储。

所以我决定将字符串复制到一个wstring的,但ofcourse这没有任何意义,因为字符仍将超过200个字符分割。 这只能使情况变得更糟。

是否有一个字符串转换为wstring的,合并的特殊字符到1元,而不是2很好的解决方案。

谢谢

Answer 1:

其实只有两种可能的解决方案。 如果你这样做了很多,在大的距离,你会好起来的转换你的角色的单个元素编码,使用wchar_t (或int32_t ,或什么是最合适的。这不是简单的复制,这将转换每个单独的char到目标类型,但真正的转换功能,这将识别该多字节字符,并把它们转换成一个单一的元件。

对于偶尔使用或较短的序列,它可以编写自己的函数推进n个字节。 对于UTF-8,我用的是以下几点:

inline size_t
size(
    Byte                ch )
{
    return byteCountTable[ ch ] ;
}

template< typename InputIterator >
InputIterator
succ(
    InputIterator       begin,
    size_t              size,
    std::random_access_iterator_tag )
{
    return begin + size ;
}

template< typename InputIterator >
InputIterator
succ(
    InputIterator       begin,
    size_t              size,
    std::input_iterator_tag )
{
    while ( size != 0 ) {
        ++ begin ;
        -- size ;
    }
    return begin ;
}

template< typename InputIterator >
InputIterator
succ(
    InputIterator       begin,
    InputIterator       end )
{
    if ( begin != end ) {
        begin = succ( begin, end, size( *begin ),
                      std::::iterator_traits< InputIterator >::iterator_category() ) ;
    }
    return begin ;
}

template< typename InputIterator >
size_t
characterCount(
    InputIterator       begin,
    InputIterator       end )
{
    size_t              result = 0 ;
    while ( begin != end ) {
        ++ result ;
        begin = succ( begin, end ) ;
    }
    return result ;
}


Answer 2:

简单的版本。 基于溶液提供获取一个UTF-8编码的std :: string的实际长度? 马塞洛诗章

std::string substr(std::string originalString, int maxLength)
{
    std::string resultString = originalString;

    int len = 0;
    int byteCount = 0;

    const char* aStr = originalString.c_str();

    while(*aStr)
    {
        if( (*aStr & 0xc0) != 0x80 )
            len += 1;

        if(len>maxLength)
        {
            resultString = resultString.substr(0, byteCount);
            break;
        }
        byteCount++;
        aStr++;
    }

    return resultString;
}


Answer 3:

一个std::string对象不是字符的字符串,它是字节的字符串。 它不知道什么是所谓的“概念编码 ”的说法。 这同样适用于std::wstring ,不同之处在于它的16位值的字符串。

为了在您的文本需要解决不同的字符(好像是这样,当你想取子,例如),你需要知道是做什么用的编码为您的std :: string对象进行操作。

更新:现在你澄清,你输入的字符串是UTF-8编码,你仍然需要在编码决定使用您的输出std::wstring 。 UTF-16想到,但它真的取决于你将通过该API std::wstring对象的期望。 假设UTF-16是可以接受的,你有多种选择:

  1. 在Windows中,你可以使用MultiByteToWideChar功能; 无需额外的依赖。
  2. 该UTF8-CPP库自称为处理UTF-*编码字符串提供了一个轻量级的解决方案。 从来没有尝试过自己,但我不断听到关于它的好东西。
  3. 在Linux系统上使用libiconv的图书馆是相当普遍的。
  4. 如果你需要应付各种疯狂的编码,并希望全面爆发字母和欧米茄字尽可能编码去,看看ICU 。


Answer 4:

Unicode是困难的。

  1. std::wstring不是编码点的列表,它是一个列表wchar_t ,并且它们的宽度是实现定义的(通常16位用VC和与gcc和铛32位)。 是的,这意味着它是无用的移植代码...
  2. 单个字符可以在几个码点被编码(由于附加符号 )
  3. 在某些语言中,两个不同的人物共同组成一个“单位”是不是真的分开的(例如, LL被认为是西班牙本身就是一个字母)。

所以...这是一个有点硬。

解决3)可能是昂贵的(它需要特定的语言/使用注释); 解决1)和2)是绝对必要的...和需要支持Unicode库或编码你自己的(也可能犯错)。

  • 1)平凡解决:从UTF-8写入例程变换到码点是微不足道的(一个码点可与表示uint32_t
  • 2)是比较困难的,它需要变音符号列表和子例程必须知道从来没有削减音调符号之前(他们遵循他们晋级的字符)

否则,有可能是你在寻找什么ICU 。 祝你好运找到它。



Answer 5:

让我来承担简单,你的编码是UTF-8。 在这种情况下,我们有一些字符占据多个字节,如你的情况。 然后你的std :: string,其中的UTF-8编码的字符存储。 现在你想在字符,而不是字节为单位来SUBSTR()。 我会写,将字符长度转换为字节长度的函数。 对于UTF-8的情况下它会看起来像:

#define UTF8_CHAR_LEN( byte ) (( 0xE5000000 >> (( byte >> 3 ) & 0x1e )) & 3 ) + 1

int32 GetByteCountForCharCount(const char* utf8Str, int charCnt)
{
    int ByteCount = 0;
    for (int i = 0; i < charCnt; i++)
    {
        int charlen = UTF8_CHAR_LEN(*utf8Str);
        ByteCount += charlen;
        utf8Str += charlen;
    }
    return ByteCount;
}

所以,说你要SUBSTR()从7个字符的字符串。 没问题:

int32 pos = GetByteCountForCharCount(str.c_str(), 7);
str.substr(pos); 


Answer 6:

基于此 ,我写我的UTF8字符串函数:

void utf8substr(std::string originalString, int SubStrLength, std::string& csSubstring)
{
    int len = 0, byteIndex = 0;
    const char* aStr = originalString.c_str();
    size_t origSize = originalString.size();

    for (byteIndex=0; byteIndex < origSize; byteIndex++)
    {
        if((aStr[byteIndex] & 0xc0) != 0x80)
            len += 1;

        if(len >= SubStrLength)
            break;
    }

    csSubstring = originalString.substr(0, byteIndex);
}


文章来源: C++ substring multi byte characters