两种string的转换

为了节省存储空间,一般我们的文件或者数据使用UTF-8保存或传输。但是当我们需要对单个字符逐个处理的时候,UTF-8的变长存储又略显不便,此时可能需要转换到UTF-16,这样每个字都是wchar_t固定双字节长度,比较好操作。幸运的是,我们无需借助其他工具,C++标准库中就提供了这样的转换函数

注意 使用这些转换函数之前必须要调用 setlocale() 设置环境locale,例如:

setlocale(LC_CTYPE, "en_US.utf-8");

比如,把保存在std::string中的UTF-8字节流转换成UTF-16并保存在std::wstring中:

std::wstring s2ws(const std::string& s)
{
    const char* str = s.c_str();
    size_t len = s.size() + 1;
    wchar_t *wstr = new wchar_t[len];
    std::mbsrtowcs(wstr, str, len);
    std::wstring ret(wstr);
    delete [] wstr;
    return ret;
}

相反,从std::wstring转换到std::string

std::string ws2s(const std::wstring& ws)
{
    const wchar_t* wstr = ws.c_str();
    size_t len = 2 * ws.size() + 1;
    char *str = new char[len];
    std::wcsrtombs(str, wstr, len);
    std::string ret(str);
    delete [] str;
    return ret;
}

用下面这个函数可以计算一个UTF-8字符串里的字符个数:

int mbstrlen(const char* mbstr)
{
    std::mbstate_t state = std::mbstate_t();
    return std::mbsrtowcs(NULL, &mbstr, 0, &state);
}

常用unicode字符范围

根据Unicode内码分区表,下面是一些常用字符的内码:

字符说明 内码范围
0-9 0x30-0x39
A-Z 0x41-0x5A
a-z 0x61-0x7A
Latin标点 0x21-0x2F 0x3A-0x40 0x5B-0x60 0x7B-0x7E
一般标点 0x2000-0x206F
CJK标点 0x3000-0x303F
CJK字符 0x4E00-0x9FA5
全角字符 0xFF00-0xFFEF

如果你知道字符的unicode编码但不清楚字符长什么样子,或者想输出某已知字符的unicode编码,最简单的办法借助python。当然首先要确定你终端的locale是en_US.UTF-8等unicode兼容环境,比如

>>> print u"\u4e00"
一
>>> "一".decode("utf8")
u'\u4e00'
>>> hex(ord(u'\u4e00'))
'0x4e00'
2007-05-22 02:30
c++
status: part
comments powered by Disqus