宽字符集操作函数_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

相关文章

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Python使用DrissionPage中ChromiumPage进行自动化网页操作

《Python使用DrissionPage中ChromiumPage进行自动化网页操作》DrissionPage作为一款轻量级且功能强大的浏览器自动化库,为开发者提供了丰富的功能支持,本文将使用Dri... 目录前言一、ChromiumPage基础操作1.初始化Drission 和 ChromiumPage

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

Redis中管道操作pipeline的实现

《Redis中管道操作pipeline的实现》RedisPipeline是一种优化客户端与服务器通信的技术,通过批量发送和接收命令减少网络往返次数,提高命令执行效率,本文就来介绍一下Redis中管道操... 目录什么是pipeline场景一:我要向Redis新增大批量的数据分批处理事务( MULTI/EXE

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注