我有一个多-byte string含有混合物的日本和拉丁字。我试图复制件的这串单独的存储位置。因为它是一个多-byte string,一些人物使用的一个字节和其他人物使用的两个。在复制件的string,我不能复制"半"日本的人物。能够正确地做到这一点,我需要能够确定在多-byte string字的开始和结束。

作为一个例子,如果串包含3个字,需要[2字节][2字节][1字节]时,我必须复制或2、4或5个字节到其他位置,而不是3个,因为如果我是复制的3个我复制,只有一半的第二字。

找出在多-byte string字的开始和结束,我试图使用Windows API function CharNext和CharNextExA但没有运气。当我使用这些功能,它们导航串通过我一个字节的时间,而不是一个角色的时间。根据MSDN,CharNext是应该 该CharNext功能检索指向下一个字一串。.

这里的一些代码为了说明这一问题:

#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include <string.h>

/* string consisting of six "asian" characters */
wchar_t wcsString[] = L"\u9580\u961c\u9640\u963f\u963b\u9644";

int main() 
{
   // Convert the asian string from wide char to multi-byte.
   LPSTR mbString = new char[1000];
   WideCharToMultiByte( CP_UTF8, 0, wcsString, -1, mbString, 100,  NULL, NULL);

   // Count the number of characters in the string.
   int characterCount = 0;
   LPSTR currentCharacter = mbString;
   while (*currentCharacter)
   {
      characterCount++;

     currentCharacter = CharNextExA(CP_UTF8, currentCharacter, 0);
   }
}

(请忽略存泄漏和失败做的错误检查。)

现在,在上面的例子,我希望characterCount成为6个,因为这是数字在亚洲串。但是,characterCount变为18因为mbString包含18个字:

門阜陀阿阻附

我不明白,它应该的工作。怎么CharNext应该知道是否"é欧元é"的字符串是一个编码版本的日本的一个角色,或者实际上符é欧元和é?

一些注意事项:

  • 我读Joels博客中约为什么每一个开发者需要知道关于统一编码。我可能误解了某事在它。
  • 如果所有我想做的只是数字,我可以数字在亚洲串直接。记住,我真正的目标是复制件的多-byte string为一个单独的位置。单独的位置仅仅支持多字节,不widechar.
  • 如果我把内容的mbString回到广泛的炭使用MultiByteToWideChar,我得到正确的string(門阜陀阿阻附),这表明没有错mbString.

编辑:显然的CharNext功能不支持UTF-8,但是Microsoft忘了文件。我扔/copiedpasted在一起我自己的惯例,我不会使用,哪些需要改进。我猜是很容易crashable.

  LPSTR CharMoveNext(LPSTR szString)
  {
     if (szString == 0 || *szString == 0)
        return 0;

     if ( (szString[0] & 0x80) == 0x00)
        return szString + 1;
     else if ( (szString[0] & 0xE0) == 0xC0)
        return szString + 2;
     else if ( (szString[0] & 0xF0) == 0xE0)
        return szString + 3;
     else if ( (szString[0] & 0xF8) == 0xF0)
        return szString + 4;
     else
        return szString +1;
  }
有帮助吗?

解决方案

这是一个很好的解释什么是在这里的 排序这一切了博客: 是CharNextExA坏了吗?.总之,CharNext不是设计工作与UTF8串。

其他提示

尽我所能确定(谷歌和实验), CharNextExA 实际上并没有与工作UTF-8,仅支持多编码,使用较短的铅/尾字节对或单一的字符。

UTF-8是一个相当定期编码,有很多图书馆,将做你想做的,但它也是相当容易滚你自己的。

看看在这里 unicode.org, 特别是表3-7的有效顺序的形式。

const char* NextUtf8( const char* in )
{
    if( in == NULL || *in == '\0' )
        return in;

    unsigned char uc = static_cast<unsigned char>(*in);

    if( uc < 0x80 )
    {
        return in + 1;
    }
    else if( uc < 0xc2 )
    {
         // throw error? invalid lead byte
    }
    else if( uc < 0xe0 )
    {
        // check in[1] for validity( 0x80 .. 0xBF )
        return in + 2;
    }
    else if( uc < 0xe1 )
    {
        // check in[1] for validity( 0xA0 .. 0xBF )
        // check in[2] for validity( 0x80 .. 0xBF )
        return in + 3;
    }
    else // ... etc.
    // ...
}

CharNextExA不起作用UTF-8, 你可以分析它自己。只是跳过字符,有10个在前两位。你可以看到的图案中的定义UTF-8: http://en.wikipedia.org/wiki/Utf-8

LPSTR CharMoveNext(LPSTR szString)
{
    ++szString;
    while ((*szString & 0xc0) == 0x80)
        ++szString;
    return szString;
}

这不是一个直接回答你的问题,但是你可能找到下面的教程很有帮助,当然,我没有。事实上,这里提供的信息是足够的,你应该能够穿越多-byte string自己轻松:

完成串教程

尝试使用932的代码页。我不认为CP_UTF8是一个真正代码页,并只能作为WideCharToMultibyte()并回。你也可以尝试isleadByte(),但是这需要设置区域设置正确,或设置默认代码页正确。我已经成功地使用IsDBCSLeadByteEx(),但从来没有CP_UTF8.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top