我有这样的std :: string其中包含一些字符跨越多个字节。
当我做一个子上这个字符串,输出是无效的,因为ofcourse,这些字符计为2个字符。 在我看来,我应该使用一个wstring的替代,因为它会作为一个元素,而不是更多的这些字符存储。
所以我决定将字符串复制到一个wstring的,但ofcourse这没有任何意义,因为字符仍将超过200个字符分割。 这只能使情况变得更糟。
是否有一个字符串转换为wstring的,合并的特殊字符到1元,而不是2很好的解决方案。
谢谢
我有这样的std :: string其中包含一些字符跨越多个字节。
当我做一个子上这个字符串,输出是无效的,因为ofcourse,这些字符计为2个字符。 在我看来,我应该使用一个wstring的替代,因为它会作为一个元素,而不是更多的这些字符存储。
所以我决定将字符串复制到一个wstring的,但ofcourse这没有任何意义,因为字符仍将超过200个字符分割。 这只能使情况变得更糟。
是否有一个字符串转换为wstring的,合并的特殊字符到1元,而不是2很好的解决方案。
谢谢
其实只有两种可能的解决方案。 如果你这样做了很多,在大的距离,你会好起来的转换你的角色的单个元素编码,使用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 ;
}
简单的版本。 基于溶液提供获取一个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;
}
一个std::string
对象不是字符的字符串,它是字节的字符串。 它不知道什么是所谓的“概念编码 ”的说法。 这同样适用于std::wstring
,不同之处在于它的16位值的字符串。
为了在您的文本需要解决不同的字符(好像是这样,当你想取子,例如),你需要知道是做什么用的编码为您的std :: string对象进行操作。
更新:现在你澄清,你输入的字符串是UTF-8编码,你仍然需要在编码决定使用您的输出std::wstring
。 UTF-16想到,但它真的取决于你将通过该API std::wstring
对象的期望。 假设UTF-16是可以接受的,你有多种选择:
MultiByteToWideChar
功能; 无需额外的依赖。 Unicode是困难的。
std::wstring
不是编码点的列表,它是一个列表wchar_t
,并且它们的宽度是实现定义的(通常16位用VC和与gcc和铛32位)。 是的,这意味着它是无用的移植代码... LL
被认为是西班牙本身就是一个字母)。 所以...这是一个有点硬。
解决3)可能是昂贵的(它需要特定的语言/使用注释); 解决1)和2)是绝对必要的...和需要支持Unicode库或编码你自己的(也可能犯错)。
uint32_t
) 否则,有可能是你在寻找什么ICU 。 祝你好运找到它。
让我来承担简单,你的编码是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);
基于此 ,我写我的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);
}