宽字符集操作函数_wchar_t 宽字符集 研究 和COM的 BSTR VARIANT

http://smycll.blog.hexun.com/80156767_d.html

 

宽字符集操作函数_wchar_t 宽字符集 研究 和COM的 BSTR VARIANT

 

wchar_t 是和 char 平等的地位,即 wchar_t 并非 typedef出来的,是原生的变量。

简单的说,它拥有两个字节,和short 占用空间一样。

比如:

字符串 "我们\n"

ANSI 的十六进制为:ce d2 c3 c7 0A 00

6个字节,其中包括字符串最后的\0

Unicode十六进制为:11 62 EC 4E 0A 00 00 00

8个字节,所有的字符 全部是2个字节,即使字母  数字 都是,当然换行\n  也是0A 00 了。

一般 程序中字符串 前面加个  L"" 就表示 是Unicode 字符串了。

windows下有一个 宏 _T("") 和上面的一样。

1.第一个简单的问题,如何打印出来 Unicode?

2个字节,可以按照 数字打印,但是如果要按照字符 打印,用普通的printf 是不行了。

可以使用wprintf打印,也就是 普通的 printf前面加一个 Wide的 W。类似的函数都是,比如 wsprintf。

复制代码
    char* lpszText = "我们\r\n";//ANSI:ce d2 c3 c7
                            //Unicode:11 62 EC 4E
                            //回车 \r 0D  \n 0A
    printf("char * text: %s 0x%08x 0x%08x \nANSI编码是   :", lpszText, lpszText, *lpszText );
    print_hex_to_file(stdout,(const uint8_t *)lpszText,strlen(lpszText)+1,16);//此函数自己编写的

    BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);
    wprintf(L"BSTR text: %s 0x%08x 0x%08x \nUniCode编码是:", bstrText, bstrText, *bstrText);
    print_hex_to_file(stdout,(const uint8_t *)bstrText,wcslen(bstrText)*2+2,16);
复制代码

的结果为:

复制代码
char * text: 我们 
0x013fbd80 0xffffffce ANSI编码是 :0x ce d2 c3 c7 0d 0a 00 BSTR text: 我们
0x007be5b4 0x00006211 UniCode编码是:0x 11 62 ec 4e 0d 00 0a 00 00 00
复制代码

对了,开始我用wprintf始终无法打印中文,后来 添加了下面的两句 才可以了。

    #include <locale.h>

    setlocale( LC_CTYPE, "chs" );

源码的编码 是 ANSI 或  UniCode 对结果 都没有什么影响。

对了 如果要打印单个 wchar_t 怎么打印呢?上面都是指针,都是字符串,那好好办。单个。。。

    setlocale( LC_CTYPE, "chs" );
    WCHAR wstr1;
    wchar_t wstr2;
    wstr1=L'';
    wstr2=L'';
    wprintf(L"我们 在宽字符集(%c,%c) 的每个大小为:%d 字节\n",wstr1,wstr2,sizeof(wstr1));

赋值的时候 始终记住 L  ,结果正常。

我们 在宽字符集(我,们) 的每个大小为:2 字节

如果你将 '我' 赋值给 一个 char 类型,那么 你只能得到 '我' ce d2  的 前一个 字节。打印出来 肯定 就是乱码  ? 了。

复制代码
char ss;
ss='';
printf("ss=%c\n",ss);



结果是:
ss=? 
复制代码

并且 ?  后面是没有换行的,因为 \n 已经和 %c 融合 为 ?  了。。反正 ce 打印出来 或许 很诡异的。

2.第二个简单的问题,如何 与 char 类型 互相转换

复制代码
int ConvertStringToBSTRDemo()
{
    char* lpszText = "Test";
    printf("char * text: %s\n", lpszText);
    BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);
    wprintf(L"BSTR text: %s\n", bstrText);
    ::SysFreeString(bstrText);

    return 0;
};
int ConvertBSTRToStringDemo()
{
    BSTR bstrText = ::SysAllocString(L"Test");
    wprintf(L"BSTR text: %s\n", bstrText);
    char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
    printf("char * text: %s\n", lpszText2);
    ::SysFreeString(bstrText);
    delete[] lpszText2;

    return 0;
};
复制代码

这个全局函数 SysFreeString() 发现 不加 貌似 也没有内存泄漏?(VLD检测)

我靠,我知道了,可能是VLD没有重载COM里的内存分配释放,所以 还是 去掉 SysFreeString前的注释。

经过实验 循环10 000 000次,会发生 300MB左右的内存泄漏。但是VLD确实无法检测。所以 千万得小心了!

COM编程里的 BSTR其实就是wchar_t* 类型,有BSTR的地方就是分配了指针的,一定要自己释放内存的!

BSTR和String(char *) 的转换,其实就是 wchar_t* 和 char * 的转换了。这是COM的方法

还可以使用stdlib里的方法:

wcstombs 和 mbstowcs  wcs应该就是WideCString ,但是 mbs 怎么就表示 ansi普通的字符编码 我就不知道缩写了

复制代码
    wchar_t   ws[10]; //sizeof(ws)=20字节
    wsprintf(ws,L"我们");
    char cs[50];
    sprintf(cs,"");
    //清除数据 与初始化
    //wchar_t * 转化为 char *
    int ret=0;
    printf("wcstombs前:       cs=%4s ws=%%S=%S\n",cs,ws);
    ret=wcstombs(cs,ws,sizeof(ws));
    printf("wcstombs后: ret=%d,cs=%4s ws=%%S=%S\n",ret,cs,ws);

    wsprintf(ws,L"");
    //清除数据 与初始化
    //char * 转化为 wchar_t *
    wprintf(L"mbstowcs前:       ws=%4s cs=%%S=%S\n",ws,(cs));
    ret=mbstowcs(ws,cs,sizeof(ws)*2);
    wprintf(L"mbstowcs后: ret=%d,ws=%2s cs=%%S=%S\n",ret,ws,(cs));
复制代码

运行结果

wcstombs前:       cs=     ws=%S=我们
wcstombs后: ret=4,cs=我们 ws=%S=我们
mbstowcs前:       ws=     cs=%S=我们
mbstowcs后: ret=2,ws=我们 cs=%S=我们

windows下也有另外的相同意思的API

//MultiByteToWideChar

最后 加上 我喜欢的 print_hex_to_file函数

复制代码
void print_hex_to_file(FILE*fp,const uint8_t *array, int count/*aray的大小*/,int lineCount/*默认应该是16*/)
{
    int i;
    fprintf(fp,"0x ");
    for(i = 0; i < count; ){
        fprintf(fp,"%02x ", array[i]);
        i++;
        if ( !(i % lineCount) && i<count){
            fprintf (fp,"\n0x ");
        }
    }
    fprintf(fp,"\n");
};
复制代码

转载请注明出处:http://www.cnblogs.com/ayanmw 多谢

------------------------------------------------------------------------------------------------

一定要专业!本博客定位于ArcGIS开发,C语言,C++语言,Java语言,Android开发和少量的Web开发,之前是做Web开发的,其实就是ASP维护,发现EasyASP这个好框架,对前端后端数据库 都很感觉亲切啊。.


-------------------------


字符分类: 宽字符函数普通C函数描述

iswalnum()      isalnum() 测试字符是否为数字或字母

iswalpha()      isalpha() 测试字符是否是字母

iswcntrl()      iscntrl() 测试字符是否是控制符

iswdigit()      isdigit() 测试字符是否为数字

iswgraph()      isgraph() 测试字符是否是可见字符

iswlower()      islower() 测试字符是否是小写字符

iswprint()      isprint() 测试字符是否是可打印字符

iswpunct()      ispunct() 测试字符是否是标点符号

iswspace()      isspace() 测试字符是否是空白符号

iswupper()      isupper() 测试字符是否是大写字符

iswxdigit()     isxdigit()测试字符是否是十六进制的数字

大小写转换:

宽字符函数     普通C函数描述

towlower()      tolower() 把字符转换为小写

towupper()      toupper() 把字符转换为大写

字符比较:      宽字符函数普通C函数描述

wcscoll()      strcoll() 比较字符串

日期和时间转换:

宽字符函数描述

strftime()      根据指定的字符串格式和locale设置格式化日期和时间

wcsftime()      根据指定的字符串格式和locale设置格式化日期和时间, 并返回宽字符串

strptime()      根据指定格式把字符串转换为时间值, 是strftime的反过程

打印和扫描字符串:

宽字符函数描述

fprintf()/fwprintf()      使用vararg参量的格式化输出

fscanf()/fwscanf()          格式化读入

printf()              使用vararg参量的格式化输出到标准输出

scanf()              从标准输入的格式化读入

sprintf()/swprintf()      根据vararg参量表格式化成字符串

sscanf()              以字符串作格式化读入

vfprintf()/vfwprintf()      使用stdarg参量表格式化输出到文件

vprintf()              使用stdarg参量表格式化输出到标准输出

vsprintf()/vswprintf()      格式化stdarg参量表并写到字符串

数字转换:

宽字符函数     普通C函数描述

wcstod()        strtod()   把宽字符的初始部分转换为双精度浮点数

wcstol()        strtol()   把宽字符的初始部分转换为长整数

wcstoul()       strtoul() 把宽字符的初始部分转换为无符号长整数

多字节字符和宽字符转换及操作:

宽字符函数描述

mblen()          根据locale的设置确定字符的字节数

mbstowcs()          把多字节字符串转换为宽字符串

mbtowc()/btowc()     把多字节字符转换为宽字符

wcstombs()          把宽字符串转换为多字节字符串

wctomb()/wctob()      把宽字符转换为多字节字符


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值