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

2024-02-17 04:32

本文主要是介绍宽字符集操作函数_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 0Aprintf("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 0xffffffceANSI编码是 :0x ce d2 c3 c7 0d 0a 00BSTR text: 我们
0x007be5b4 0x00006211UniCode编码是: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()      把宽字符转换为多字节字符


 

 

 

这篇关于宽字符集操作函数_wchar_t 宽字符集 研究 和COM的 BSTR VARIANT的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/716679

相关文章

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

MySQL追踪数据库表更新操作来源的全面指南

《MySQL追踪数据库表更新操作来源的全面指南》本文将以一个具体问题为例,如何监测哪个IP来源对数据库表statistics_test进行了UPDATE操作,文内探讨了多种方法,并提供了详细的代码... 目录引言1. 为什么需要监控数据库更新操作2. 方法1:启用数据库审计日志(1)mysql/mariad

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

python 常见数学公式函数使用详解(最新推荐)

《python常见数学公式函数使用详解(最新推荐)》文章介绍了Python的数学计算工具,涵盖内置函数、math/cmath标准库及numpy/scipy/sympy第三方库,支持从基础算术到复杂数... 目录python 数学公式与函数大全1. 基本数学运算1.1 算术运算1.2 分数与小数2. 数学函数

Oracle 数据库数据操作如何精通 INSERT, UPDATE, DELETE

《Oracle数据库数据操作如何精通INSERT,UPDATE,DELETE》在Oracle数据库中,对表内数据进行增加、修改和删除操作是通过数据操作语言来完成的,下面给大家介绍Oracle数... 目录思维导图一、插入数据 (INSERT)1.1 插入单行数据,指定所有列的值语法:1.2 插入单行数据,指