wchar和char的了解以及相互转化
来源:互联网 发布:网络最牛的对联 编辑:程序博客网 时间:2024/05/19 00:37
今天遇到wchar和char字符转换的问题,花费了不少的时间。
typedef struct tagSerialData{ nuWCHAR serialdata[10]; nuUINT dataLength;}SERIAL_DATA, *pSERIAL_DATA;
这是我定义的结构体(nuWCHAR是公司自定义的,相当于WCHAR),但是另外公司的同事把结构体定义成了
struct tagSerialData{ char serialdata[10]; int dataLength;}SERIAL_DATA, *pSERIAL_DATA;
所以导致我将自己定义的结构体的dataLength赋值成10时,联调的同事接收到的Length=0;或者我将自己定义的结构体的serialdata赋值成“1234567890”时,同事接收到的Length是一个无限大的数
这是我给自己定义的结构体赋值,获取长度SERIAL_DATA s_stcSerialData = {0};wcscpy(s_stcSerialData.serialdata,L"1234567890");s_stcSerialData.dataLength=wcslen(s_stcSerialData.serialdata)
后来发现定义的结构体不一样时,我只好修改自己的结构体,变成nuCHAR,但是在后面的功能上我要用的是WCHAR类型的数据。这就需要我将他后来传给我的char类型的数据转换成WCHAR .
我在网上搜的wchar转化成char的例子如下:
int MultiByteToWideChar( UINT uCodePage, //标识了与多字节字符串关联的一个代码值 一般不用 传0??? DWORD dwFlags, //允许我们额外的控制,它会影响带变音符号(比如重音) 一般不用 传0 PCSTR pMultiByteStr, // 源多字节字符串 int cbMulitByte, //源多字节字符串的长度(字符) 如果传进-1,函数便可以自动判断源串长度 PWSTR pWideCharStr, //转换后的串的指针 即缓冲区的首地址 int cchWideChar ); //指定这个缓冲区的最大长度(字符数),如果传入0,则函数不会转换,而是返回一个宽字符数(包括终止字符'\0'),只有当缓冲区能够容纳该数量的宽字符时,转换才会成功。 1: 以下为将一个多字节串转化成Unicode形式的步骤: (1)、调用MultiByteToWideChar,为pWideCharStr传入NULL,为cchWideChar传入0,为pMultiByteStr传入-1 (2)、假设上次调用的返回值为n ,开辟一块缓冲区,大小为 n *sizeof( wchar_t) (3)、再调用一次MultiByteToWideChar,pWideCharStr为开辟的缓冲区的首地址,cchWideChar 为n (4)、使用转换后的字符串 (5)、释放缓冲区代码: char str1[100] = "1234567890"; int numChar = ::MultiByteToWideChar(0,0,str1,-1,NULL,0); wchar_t *str2 = (wchar_t*)malloc( numChar*sizeof(wchar_t) ); ::MultiByteToWideChar(0,0,str1,-1,str2,numChar); ::wprintf_s(str2);2:unicode转换为多字节字符串:int WideCharToMultiByte( UINT nCodePage, //标识了与多字节字符串关联的一个代码值 一般不用 传0??? DWORD dwFlags, //允许我们额外的控制,它会影响带变音符号(比如重音) 一般不用 传0 PCWSTR pWideCharStr,//源unicode字符串 int cchWideChar, //unicode字符数 PSTR pMultiByteStr, //缓冲区首地址 int cbMultiByte, //缓冲区最大的长度 防止溢出 PCSTR pDefaultChar,//当有一个字符不能转换时,用该指针指向那个不能转换的字符 PBOOL pfUesdDefultChar) ;//如果成功转换 该值为FALSE 如果有至少一个字符不能成功转换,该值为TURE 用该值来检测能否转化成功, 最后这两个参数只有在碰到有一个字符不能转化时才用到,一般传值NULL使用步骤和多字节转化为unicode差不多,不同的是第一次调用时返回直接就是所需缓冲区的大小(字节数)!!!代码: wchar_t str1[100] = L"1234567890"; int numChar = ::WideCharToMultiByte(0,0,str1,-1,NULL,0,NULL,NULL); char *str2 = (char*)malloc( numChar ); ::WideCharToMultiByte(0,0,str1,-1,str2,numChar,NULL,NULL); printf(str2); free(str2);这是写的一个小例子:#include <stdio.h>#include <Windows.h>int main(){ char *a = "ab"; wchar_t *b = (wchar_t *)a; wprintf(L"%s %s\n", b, L"ab"); sleep(1000);//作用是为了使在屏幕上停留 return 0;}结果:? ab没有经过转化的wchar类型和char类型不能这样强制转换#include <stdio.h>#include <Windows.h>int main(){ char *a = "ab"; int numChar = ::MultiByteToWideChar(0,0,a,-1,NULL,0); wchar_t *b = (wchar_t*)malloc(numChar*sizeof(wchar_t)); ::MultiByteToWideChar(0,0,a,-1,b,numChar); wprintf(L"%s %s\n", b, L"ab"); free(b); Sleep(1000); return 0;}结果:ab ab成功将char转化成wchar类型。
WCHAR和CHAR的区别:
首先,说下窄字符char了,大家都很清楚,就是8bit表示的byte,长度固定。char字符只能表示ASII码表中的256个字符,包括前128个可见字符和后面的128个不可见字符。 而wchar_t则是因为char所能表示的字符数太少(256个)而应运而生的,它的长度可以8bit,16bit,32bit,长度是与不同平台上的c库相关的。其实这个长度是根据指定平台上想要用的encoding编码方式来设定的。 在win32 MSVC环境下,c库中wchar_t的长度是2个byte,定义如下: typedef unsigned short wchar_t; /* 16 bits */ 它是按照utf-16编码,但是因为wchar_t定义的长度只有2个字节,所以它不能表示utf-16编码长度为4个字节的字符。即wchar_t只表示了utf-16的一个子集。换句话话说,就是MSVC下,wchar_t是utf-16编码的,但是只能表示utf-16的一个子集。按utf-16编码时,大部分字符都以固定长度的字节 (2字节) 储存. 在Linux-x86的GCC环境下,c库中wchar_t的长度为四个字节,用UCS-4(即utf-32编码方式)。 wchar_t就是存储的字符的unicode码值的编码值,如windows下就是unicode码值的utf-16编码值: TCHAR wide[] = L"态"; 在vs中watch为: [0] 24577 L'态' wchar_t,即对应的十进制为24577,而"态"unicode表中查到的码值为十六进制的6001,而0x6001对应的十进制值就是24577. TCHAR wide[] = L"a"; 因为a的unicode值与ASCII值一样,为97. 如果unicode码值U小于0x10000,则U的UTF-16编码就是U对应的16位无符号整数。 所以可知,0x6001的utf-16编码值就是0x6001。 wchar_t w1= L'中'; //Unicode 编码 wchar_t w2= '中'; //Ansi编码 printf( "%0x %0x ",w1,w2); 结果: 4e2d d6d0 虽然同样是赋值给wchar_t,但是不同的编码则值是不同的。同时也说明了wchar_t不光是可以存储Unicode宽字符,也可以存储其它的编码。但是如果是存储的Ansi编码,则按照宽字符的格式输出的是什么呢? wchar_t c= L'中'; wcout.imbue(locale("chs")); wcout<<c<<endl; 上述代码能正常输出'中'字 wchar_t c= '中'; wcout.imbue(locale("chs")); wcout<<c<<endl; 上述代码不能正常输出'中'字,结果是什么也没输出。 所以如果是需要宽字符参数的API里传入值为Ansi编码值的wchar_t可能会得到不可预测的结果。 c/c++标准只是声明wchar_t是一个可以表示字符集中的任意一个字符的足够宽的变量类型。wchar_t可以用任何encoding编码方式来存储这个字符,如ANSI, or UCS-2, or UCS- 4, 甚至是SCU-128,只不过我们通常是用unicode编码方式。wchar_t是与实现相关的。所以为了可移植性,我们不能假定wchar_t的编码方式,然后根据编码方式做一些相关性操作,我们只能理解它为一个足够宽的字符类型。
虽然从网上使用了这种转化的办法,但是在自己函数上实现的过程中,还是遇到了问题:就是转化之后还是出现了乱码。
这是我函数中接收wchar字符串,并且将wchar字符串显示在文本框中的函数:
vSetObjectText(ID_STATIC_SERIALDATA,CGnBaseDlg::SerialData);
vSetObjectText(ID_STATIC_MAINCTRL_VER,s_stcMainCtrlVer.wMainCtrl);
而后来才发现vSetObjectText()函数的第二个参数应该接收的是一个全局变量,而之前我在转化之前定义的都是静态的变量,所以才导致虽然多次写入到文件的s_stcSerialData.serialData能读取到正确的字符串,但是在文本框中却出现乱码的情况。
另外附上非常不错的文章链接:
http://club.topsage.com/thread-2227977-1-1.html
http://blog.sina.com.cn/s/blog_62714d6a0100ld9z.html
- wchar和char的了解以及相互转化
- char* 与 WCHAR* 的相互转化
- qstring wchar char 相互转化
- qstring wchar char 相互转化
- MFC中CString和string以及char * 的相互转化
- [转载]字节码问题--wchar和char的区别以及wchar和char之间的相互转换字符编码转换等方法及函数介绍
- 字节码问题--wchar和char的区别以及wchar和char之间的相互转换字符编码转换等方法及函数介绍
- 字节码问题--wchar和char的区别以及wchar和char之间的相互转换字符编码转换等方法及函数介绍
- CString、wchar和char类型的相互转换(转载)
- CString、wchar和char类型的相互转换
- C++/MFC-CHAR和WCHAR类型的相互转换
- CString、wchar和char相互转换
- CString、wchar和char相互转换
- [转]CString、wchar和char相互转换
- CString、wchar和char相互转换
- char* 转化为 WCHAR* 的方法
- CHAR与WCHAR字符串的转化
- TCHAR和char 的相互转化
- 多层级Spinner列表选项实时更新树形层级(选择城市)
- C#基础笔记
- 在iOS7中修改状态栏字体的颜色
- java设计模式--六大设计原则
- Python的种种
- wchar和char的了解以及相互转化
- LeetCode 234:Palindrome Linked List
- JAVA timer的基本知识
- 协议 Protocol 的使用
- javascript 将xml字符串转换成json对象
- PHP 使用telent测试HTTP
- Linux Is Not Matrix——Nginx安装
- easyui中ajax笔记
- vs2013+Opencv2.4.9+MFC的图像浏览窗口