C++ C++;迭代或将UTF-8字符串拆分为符号数组?
搜索与平台和第三方库无关的迭代UTF-8字符串或将其拆分为UTF-8符号数组的方法 请发布一段代码片段 已解决:C++ C++;迭代或将UTF-8字符串拆分为符号数组?,c++,arrays,utf-8,split,C++,Arrays,Utf 8,Split,搜索与平台和第三方库无关的迭代UTF-8字符串或将其拆分为UTF-8符号数组的方法 请发布一段代码片段 已解决: 试试。如果我理解正确,听起来您想找到每个UTF-8字符的开头。如果是这样,那么解析它们就相当简单了(解释它们是另一回事)。但涉及多少个八位组的定义由以下机构明确定义: 例如,如果lb具有UTF-8字符的第一个八位字节,我认为下面将确定所涉及的八位字节数 unsigned char lb; if (( lb & 0x80 ) == 0 ) // lead b
试试。如果我理解正确,听起来您想找到每个UTF-8字符的开头。如果是这样,那么解析它们就相当简单了(解释它们是另一回事)。但涉及多少个八位组的定义由以下机构明确定义: 例如,如果
lb
具有UTF-8字符的第一个八位字节,我认为下面将确定所涉及的八位字节数
unsigned char lb;
if (( lb & 0x80 ) == 0 ) // lead bit is zero, must be a single ascii
printf( "1 octet\n" );
else if (( lb & 0xE0 ) == 0xC0 ) // 110x xxxx
printf( "2 octets\n" );
else if (( lb & 0xF0 ) == 0xE0 ) // 1110 xxxx
printf( "3 octets\n" );
else if (( lb & 0xF8 ) == 0xF0 ) // 1111 0xxx
printf( "4 octets\n" );
else
printf( "Unrecognized lead byte (%02x)\n", lb );
不过,最终,正如另一篇文章所建议的那样,使用现有库会让您受益匪浅。上面的代码可能会根据八位字节对字符进行分类,但一旦完成,它不会帮助“处理”字符。即兴:
// Return length of s converted. On success return should equal s.length().
// On error return points to the character where decoding failed.
// Remember to check the success flag since decoding errors could occur at
// the end of the string
int convert(std::vector<int>& u, const std::string& s, bool& success) {
success = false;
int cp = 0;
int runlen = 0;
for (std::string::const_iterator it = s.begin(), end = s.end(); it != end; ++it) {
int ch = static_cast<unsigned char>(*it);
if (runlen > 0) {
if ((ch & 0xc0 != 0x80) || cp == 0) return it-s.begin();
cp = (cp << 6) + (ch & 0x3f);
if (--runlen == 0) {
u.push_back(cp);
cp = 0;
}
}
else if (cp == 0) {
if (ch < 0x80) { u.push_back(ch); }
else if (ch > 0xf8) return it-s.begin();
else if (ch > 0xf0) { cp = ch & 7; runlen = 3; }
else if (ch > 0xe0) { cp = ch & 0xf; runlen = 2; }
else if (ch > 0xc0) { cp = ch & 0x1f; runlen = 1; }
else return it-s.begin(); // stop on error
}
else return it-s.begin();
}
success = runlen == 0; // verify we are between codepoints
return s.length();
}
//返回已转换的s的长度。成功返回时应等于s.length()。
//On error返回指向解码失败的字符。
//请记住检查成功标志,因为解码错误可能发生在
//弦外之音
int转换(std::vector&u、const std::string&s、bool&success){
成功=错误;
int cp=0;
int-runlen=0;
对于(std::string::const_迭代器it=s.begin(),end=s.end();it!=end;++it){
int ch=静态施法(*it);
如果(runlen>0){
if((ch&0xc0!=0x80)| | cp==0)返回它-s.begin();
cp=(cp 0xf8)返回它-s.begin();
如果(ch>0xf0){cp=ch&7;runlen=3;}
如果(ch>0xe0){cp=ch&0xf;runlen=2;}
如果(ch>0xc0){cp=ch&0x1f;runlen=1;}
否则返回-s.begin();//出错时停止
}
否则返回-s.begin();
}
success=runlen==0;//验证我们在代码点之间
返回s.length();
}
正是您想要的使用小型平台独立库解决的问题:
char*str=(char*)text.c_str();//utf-8字符串
char*str_i=str;//字符串迭代器
char*end=str+strlen(str)+1;//结束迭代器
做
{
uint32_t code=utf8::next(str_i,end);//获取utf-8符号的32位代码
如果(代码==0)
继续;
无符号字符[5]符号={0};
utf8::append(code,symbol);//将代码复制到symbol
//…用符号做点什么
}
而(str_i
C++没有任何处理UTF-8编码的标准工具。所以,要么使用单独的库,要么编写自己的库。写自己的是可能的,但有无数的细节。是的,这就是我问这个问题的原因。“第三方库独立方式”+1 ICU是一个跨平台库,根据许可的开源许可证发布。如果OP希望避免依赖第三方库,ICU的源代码是免费的,但包含超过1e+06行代码。它是开源的。您可以尝试从中使用字符串迭代器源代码,而不是所有1e+06行代码。谢谢。endianess对这个函数重要吗?“如果(*it<0x80){u.push_back(*it);}”=>“由于数据类型范围有限,比较总是正确的”从const char*const'到
char*'的转换无效Ok,我修复了错误。UTF8是严格的字节级,所以endianness不重要。我再说一遍。UTF8是字节级编码。这意味着您按顺序读取每个字节。在IP端口之间或从主存储器到微处理器寄存器的传输顺序并不重要。当这些位重新组合在一起时,它们在所有处理器上的解释方式相同(19==19)。Endianness不是问题。我已经自己找到了这个图书馆。我需要一个密码,不过还是谢谢你。回答得很好!这正是我要找的!谢谢在某些语言中,一个单词包含两个或两个以上的符号,如'哈哈' 在中文里,应该用vector
来存储单词吗?如果是这样,比较单词似乎需要迭代向量/数组,而且速度相当慢。。。
// Return length of s converted. On success return should equal s.length().
// On error return points to the character where decoding failed.
// Remember to check the success flag since decoding errors could occur at
// the end of the string
int convert(std::vector<int>& u, const std::string& s, bool& success) {
success = false;
int cp = 0;
int runlen = 0;
for (std::string::const_iterator it = s.begin(), end = s.end(); it != end; ++it) {
int ch = static_cast<unsigned char>(*it);
if (runlen > 0) {
if ((ch & 0xc0 != 0x80) || cp == 0) return it-s.begin();
cp = (cp << 6) + (ch & 0x3f);
if (--runlen == 0) {
u.push_back(cp);
cp = 0;
}
}
else if (cp == 0) {
if (ch < 0x80) { u.push_back(ch); }
else if (ch > 0xf8) return it-s.begin();
else if (ch > 0xf0) { cp = ch & 7; runlen = 3; }
else if (ch > 0xe0) { cp = ch & 0xf; runlen = 2; }
else if (ch > 0xc0) { cp = ch & 0x1f; runlen = 1; }
else return it-s.begin(); // stop on error
}
else return it-s.begin();
}
success = runlen == 0; // verify we are between codepoints
return s.length();
}
char* str = (char*)text.c_str(); // utf-8 string
char* str_i = str; // string iterator
char* end = str+strlen(str)+1; // end iterator
do
{
uint32_t code = utf8::next(str_i, end); // get 32 bit code of a utf-8 symbol
if (code == 0)
continue;
unsigned char[5] symbol = {0};
utf8::append(code, symbol); // copy code to symbol
// ... do something with symbol
}
while ( str_i < end );