多字节字符与宽字符重新认识

来源:互联网 发布:淘宝收藏图片在线制作 编辑:程序博客网 时间:2024/06/08 05:27

一直都说,多字节字符,何为多字节,并不只是一个char就是了。英文的字符都是char能表示,但是中文字符,是2个字节表示的。

所以,

char s[] = "ha哈哈";    int l = strlen(s);// 6    char c = s[2];// -71 '?' cannot represent
s 是占7个字节。

s[2]只是'哈'的前半部分,所以决不能写这样的比较代码!!!

if (s[2]=='哈')

所以,字符串中有中文时,一定要格外小心。


甚至,所有的C、C++的字符串库函数都是可能得出错误结果的。如下:

#include <stdio.h>//#include <stddef.h>#include <locale.h>#include <string.h>#include <string>using namespace std; int main(){    setlocale(LC_CTYPE, "chs");// useless        char ss22[] = "/\\hh猪哈猪头";// '/':2F, '\\':5C  GBK: 81~FE(H),40~FF(L)//ss22[5] = 47;ss22[7] = 92;char *p1 = strrchr(ss22, '/');//char *p2 = strrchr(ss22, '\\');// got unwished posstring sstr22 = ss22;size_t pos2 = sstr22.rfind('\\');// also got unwished pos        printf("%p %p %p %d\n", ss22, p1, p2, (int)pos2);    //----------char ss33[] = "hh哈猪头/\\";ss33[3] = 92;char *p11 = strchr(ss33, '\\');// got unwished poschar *p12 = strstr(ss33, "\\");// also got unwished posstring sstr33 = ss33;size_t pos31 = sstr33.find('\\');// also got unwished possize_t pos32 = sstr33.find("\\");// also got unwished pos    printf("%p %p %p %d %d\n", ss33, p11, p12, (int)pos31, (int)pos32);}

当多字节字符串中中文字符的 低字节部分 与 已有的英文字符编码相同时,查找字符或字符串时都会一视同仁,无法察觉出是中文字符的部分还是英文字符。

所以在程序中,有中文字符的情况下,还是多用UNICODE(UCS)或UTF8吧,windows API 也多用 W版的吧。

最近工作中,有用GetModuleFileNameA得到模块目录,然后用strrchr(buf, '\\');判断有木有斜杠符,最后忽然想到这个多字节的问题。坑爹啊!!!


对于多字节,可用mblen 函数来查询一个多字节字符所占用的 字节数。

和多字节相关的还经常要用到区域信息,可用setlocale()来设置。

下面是用mbtowc(多字节字符转成宽字符)  来实现mbstowcs:

size_t mbstowcs(wchar_t *pwcs, char *pmbs, size_t n){size_t i = 0;mbtowc(NULL, NULL, 0);// init shift statewhile (*pmbs && i < n){int len = mbtowc(&pwcs[i++], pmbs, MB_CUR_MAX);if (len == -1)return (size_t)-1;pmbs += len;// to next mb char}return i;}

// MB_CUR_MAX: the value of which is the maximum number of bytes in a multibyte character
   with the current locale (category LC_CTYPE).

0 0
原创粉丝点击