C ++如何获取下一个多字节字符

时间:2014-07-08 18:27:45

标签: c++ unicode ansi multibyte wchar-t

他们是否可以在多字节字符串中获取下一个完整字符,例如“z \ u00df \ u6c34 \ U0001d10b”或“zß水”将表示为4个字符,不包括宽字符串中的空终止但可能包含9个字符多字节字符串。我使用下面的代码来转换为字符串,因为我在内部使用了widestirng,但是如果__wideToString没有给出适当的长度,即使长度大于它需要的长度,它们似乎也是微妙的问题。我也意识到我可以通过仅使用字符串来跳过与wstring的整个转换,如果我可以简单地获取多字节字符串中的多少个字符组成下一个完整字符。所以在字符串u8“u6c34 \ U0001d10b”中可以存储6个字符,我只想要接下来的2个“水”。任何人都可以指导我解决这个问题吗?

我一直有这个unicode类型的问题,他们似乎没有很多关于它如何在C ++中处理的信息,除了第三方解决方案,我试图避免。

static 
std::string __wideToString(const std::wstring & ws){
    if(ws.empty()){throw std::invalid_argument("Wide string must have length >= 1");}
    std::setlocale(LC_ALL, "");
    size_t length = sizeof(wchar_t)*ws.length();
    std::string str(length,' ');
    if((length=wcstombs(&str[0], ws.c_str(), length))==size_t(-1)){//return -1 on invalid conversion
        throw std::length_error("Conversion Error Invalid Wide Character"); 
    }
    str.resize(length); // Shrink to fit.
    return str;
}

static 
std::wstring __stringToWide(const std::string & str){
    if(str.empty()){throw std::invalid_argument("String must have length >= 1");}
    std::setlocale(LC_ALL, "");
    size_t length = str.length();
    std::wstring ws(length, L' '); // Overestimate number of code points.
    if((length=mbstowcs(&ws[0], str.c_str(), length))==size_t(-1)){//return -1 on invalid conversion
        throw std::length_error("Conversion Error Invalid Multibyte Character");    
    } 
    ws.resize(length); // Shrink to fit.
    return ws;
}

2 个答案:

答案 0 :(得分:1)

wcstombs()不适用于unicodes 0 - 0xff之外的字符。

它将失败,返回值为-1(对于中文字母等)或者无声地产生错误的输出(例如从'ā'中删除变音符号,因此它变成'a')。

问题在于,如果您的字符无法用普通的std :: string表示,那么您所做的事情就没有意义。没有支持您尝试执行的操作系统API或C ++ 03/11功能。

像wideToString()之类的命名方法没有意义,除非你只有一个有限的类似ANSI的字符集。 stringToWide()虽然有意义。

回到你的问题 - Windows将wstring有效负载存储为UTF-16,并且其中的每个wchar_t都是一个16位UTF-16代码单元(因此对于unicodes 0xffff之外的字符需要两个wchar_ts)。 Linux将wstring有效负载存储为UTF-8,但wchar_t是32位UTF-32代码单元。

因此,在Windows上,您可以在网上搜索一些UTF-16解码功能,以找出下一个字符的开始位置。但同样,它不会帮助你。

答案 1 :(得分:1)

此函数将获得字节长度和代码点:

<style>
相关问题