字符操作

来源:互联网 发布:highcharts 3d.js 编辑:程序博客网 时间:2024/05/17 11:03

字符是我们常常会用到的东西了,当然我们不会陌生char 、char[]、char*、wchar_t 、C++的string wstring MFC的 CStringA CStringW,还有一些宏TCHAR PSTR WSTR PWSTR PCWSTR PTSTR LPTSTR 很多这些字符类型或类以及他们相应的操作函数等 同时它们又分为但字符ANSI,或双字符UNICODE,本篇就是讲一下自己编程时候遇到的字符的一下特别的地方。

ANSI大家都知道,了因为用得比较多嘛,而且大家用window编程比较多的话要记住:

M i c r o s o f t 公司对U n i c o d e 支持的情况:

• Windows 2000 既支持U n i c o d e ,也支持A N S I ,因此可以为任意一种开发应用程序。

• Windows 98 只支持A N S I ,只能为A N S I 开发应用程序。

• Windows CE 只支持U n i c o d e ,只能为U n i c o d e 开发应用程序。

 

同时C O M 要求使用U n i c o d e 字符串这一点也要记住呀。

标准的C 头文件S t r i n g . h 已经作了修改,以便定义一个名字为w c h a r _ t 的数据类型,它是一个U n i c o d e 字符的数据类型:

typedef unsigned short wchar_t;
对了程序员都比较喜欢惯性的记忆方式我们可以这样记Unicode的标准C函数 是wcs开头的,而也ansi的str开头对应然后再把char 改成wchar_t:
char * strcat(char *,const char *);wchar_t * wcscat(wchar_t *,const wchar_t *);

          C标准中还提供了一个T C h a r. h 文件,包含这个头文件而不是包含string.h 它是提供了一些宏来方便你支持anis/unicode的操作,所以我们应该尽量使用它提供的宏而不是直接使用str 或则wcs函数。

         例如,在T C h a r. h 中有一个宏称为_ t c s c p y 。如果在包含该头文件时没有定义_ U N I C O D E ,那么_ t c s c p y 就会扩展为A N S I 的s t r c p y 函数。但是如果定义了_UNICODE, _tcscpy 将扩展为U n i c o d e的w c s c p y 函数。呵呵这个是window核心编程里面说的.

在里面TCHAR

#ifdef _UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif

还有

#ifdef _UNICODE
#defind _TEXT(X) L##x;
#else
#defind_TEXT(X) x;
#endif

 

这样我们编程的时候就可以通过是#defind _UNICODE来决定

TCHAR SS[] = _TEXT("fsdfs");

 

 

下面是window头文件里的了,哎window定义了更多的东西来让你的大脑去记呀.

首先我先讲window区别是#defind UNICODE 不像C 运行期头文件,同时window核心编程说要同时定义这两个宏。

先把一些类型说一下

CHAR对应 char

PSTR 对应 char *

PCSTR 对应 constr char *

 

WSTR 对应 wchar_t

PWSTR 对应 wchar_t*

PCWSTR 对应 constr wchar_t*

 

当然就有一个宏是可以通过是否定义 UNICODE 来区分是哪个咯

TSTR

PTSTR

PCTSTR

还有LPTSTR LPCTSTR 有时候这些是干什么的我也不清楚希望高手能回答一下。

 

window 头文件中对函数的操作函数就是lstrcat 这个是个宏 对应的ansi 是lstrcatA Unicode是lstrcatW 呵呵,window喜欢在结尾用A或则是W来区分

 

至于这两个中字符的转换是靠Wi d e C h a r To M u l t i B y t e 和M u l t i B y t e To Wi d e C h a r 来完成的了

 

 

那些都讲的差不多了,现在讲几种编程时候用得比较多的 TCHAR 类型 string 标准C++提供的类 CString MFC中的

我想讲它们的大小在 和字符占用的字节大小 同时在ansi 和 Unicode

我们都知道了TCHAR 对应 char 和wchar_t 而string 还有一个wstring CString 则有CStringA   、 CStringW

char a[7] = "123456"; 这样是正确的

char a[7] = "1234567"; 提示数组溢出 别忘了字符后面有个'/0' 如果是Unicode wchar_t的话是"/0/0"

 

char a[] = "123456";  sizeof 是 7 ;strlen 是 6

 

char a[] = "12345我";  sizeof 是 8;strlen 是 7

 

wchar_t w[] = "123456";  sizeof 是 14 ;wcslen 是 6

 

wchar_t w[] = "12345我";  sizeof 是 14;wcslen 是 6

 

大家可以看看这两组数据,sizeof 是计算占用的字节,strlen计算的是不包含 结尾的结尾符的char 是'\0' wchar_t是"\0\0"

strlen就是 sizeof a / sizeof (char ) 这里强调一下 sizeof 是操作符 后面是变量就可以不用() 是类型就要用(), 这样就存在了上面的现象 所以用Unicode 编程是有好处的,不怕字符中出现中文哈哈。

 

二、

    前些日子写个程序,别人用驱动修改了底层的Iwebrower控件NavigateComplete2( IDispatch *pDisp,VARIANT *URL )等接口传递出来的URL地址字符串,用的是UNICODE所以他直接在地址字符串只插入'\0'结束符号,像上面说的结尾符的char 是'\0' wchar_t是"\0\0" 所以用UNICODE字符操作的话是没问题

如假设:http://www.baidu.com/s?tn=sogouie_dg&bs=CSDN&f=8&rsv_bp=1&wd=%D7%D6%B7%FB+%5C0&inputT=7438 这个是地址 

被他改成http://www.baidu.com/s?\0tn=sogouie_dg&bs=CSDN&f=8&rsv_bp=\01&wd=%D7%D6%B7%FB+%5C0&\0inputT=7438 

 这样的话 我本来是用

VARIANT *URL 

_bstr_t bst = URL->bstrVal;


char * csUrl = bst;

这样的话就错了,我直接用strlen csUrl 得到的就是http://www.baidu.com/s?的长度, 呵呵可惜当初没有得到 

 BSTR的长度 其实我看网上说是前4个字节 ,的确是前 4个字节,可惜我以为是 URL->bstrVa 开头的前4个字节,最后用

nURLCount = *(DWORD *)(URL->bstrVal - 2); 就可以获得它的长度,或者用nURLCount = SysStringLen(URL->bstrVal);

如果用后面的得到的是字符个数,前面的是字节。

 然后这样就可以变成我要的字符串了。


nURLCount = SysStringLen(URL->bstrVal);

int iRet = ::WideCharToMultiByte(CP_ACP, 0, URL->bstrVal, nURLCount * 2, NULL, 0, NULL, NULL);
if (iRet == 0)
return ;
CHAR *szBuff = new CHAR[iRet];

iRet = ::WideCharToMultiByte(CP_ACP, 0, URL->bstrVal, nURLCount * 2, szBuff, iRet, NULL, NULL);
if (iRet == 0)
return;

VC看到的内存就是 URL->bstrVal 地址是18b104 前面 4字节 就是72 

http://www.soso.com/wbhp.shtml?cid=union.s.wh&unc=r400105

 0x0018B100  72 00 00 00 68 00 74 00 74 00 70 00 3a 00 2f 00 2f 00 77 00 77 00 77 00 2e 00 73 00 6f 00  r...h.t.t.p.:././.w.w.w...s.o.
0x0018B11E  73 00 6f 00 2e 00 63 00 6f 00 6d 00 2f 00 77 00 62 00 68 00 70 00 2e 00 73 00 68 00 74 00  s.o...c.o.m./.w.b.h.p...s.h.t.
0x0018B13C  6d 00 6c 00 3f 00 63 00 69 00 64 00 3d 00 75 00 6e 00 69 00 6f 00 6e 00 2e 00 73 00 2e 00  m.l.?.c.i.d.=.u.n.i.o.n...s...
0x0018B15A  77 00 68 00 26 00 75 00 6e 00 63 00 3d 00 72 00 34 00 30 00 30 00 31 00 30 00 35 00 00 00  w.h.&.u.n.c.=.r.4.0.0.1.0.5...
0x0018B178  32 00 00 00 62 00 31 00 2e 00 70 00 6e 00 67 00 2e 00 2e 00 2e 00 00 00 00 00 00 00 0c 00  2...b.1...p.n.g...............

 对了一个问题如果我得到了字符的实际长度用下面的方法,是不是就成功的吧带有\0的字符从URL->bstrVal拷贝到csUrl 了呢,同时中途自动转换到ASCII了,这个我暂时没有去确认。

http://www.baidu.com/s?\0tn=sogouie_dg&bs=CSDN&f=8&rsv_bp=\01&wd=%D7%D6%B7%FB+%5C0&\0inputT=7438 VARIANT *URL 

_bstr_t bst = URL->bstrVal;


char * csUrl = bst;

不然我就不会用WideCharToMultiByte函数去转换了。

上面的太长了http://www.hao123.com/ 22个字符 0x2c就是44 那个44可是不包括 最后的 00 00 '\0''\0'

0x00187EF8  2c 00 00 00 68 00 74 00 74 00 70 00 3a 00 2f 00 2f 00 77 00 77 00 77 00 2e 00 68 00 61 00  ,...h.t.t.p.:././.w.w.w...h.a.
0x00187F16  6f 00 31 00 32 00 33 00 2e 00 63 00 6f 00 6d 00 2f 00 00 00 64 00 75 00 2f 00 00 00 ad ba  o.1.2.3...c.o.m./...d.u./...­º

 

 遗留问题1.

 

_bstr_t bst = URL->bstrVal;


char * csUrl = bst; 

是否实现了吧wchar_t转换为char 的同时中间插入了\0的时候能不能完全的吧包含\0的字符数据拷贝到char

其他的默认字符转换而不是明显的使用WideCharToMultiByte的方式是否也会拷贝的中途被\0截取了。

 

0 0
原创粉丝点击