字符串
WideCharToMultiByte(CP_BIG5,0,pszUni,-1,pszBig5,iLen,NULL,NULL);
TRACE("%s\n",pszBig5);
delete []pszBig5;
delete []pszUni;
3. 建Unicode的VC++项目的一般步骤
1、 在项目设置的“菜单—Project—Settings—C/C++--Preprocessor definitions”中,将_MBCS预处理定义修改为_UNICODE;
2、 在“菜单—Tools—Debug”中,将“Display unicode strings”选项打勾;
3、 除非指定要使用char类型的字符串,否则应该将字符串常量用_T括起来,例如
//修改前 char szBuf[]="Hello!";
//修改后 TCHAR szBuf[]=_T("Hello!");
4、 有些数据类型要进行相应的转换,如
原数据类型
新数据类型
char
TCHAR
char *
LPTSTR
const char *
LPCTSTR
5、 原有字符串处理函数进行相应转换,一般规律为str***转换为_tcs***,例如
原函数
替换后的函数
strlen
_tcslen
strcpy
_tcscpy
strcat
_tcscat
sprintf
_stprintf 注意此处有不同
示例:
/* 转换前
char szBuf[]="Hello!";
char szBuf2[16];
char *pszBuf=szBuf;
const char *pszBuf2=szBuf;
strcpy(szBuf2,szBuf);
int iLen=strlen(szBuf2);
int iLen2=sizeof(szBuf)-1;
sprintf(szBuf2,"str is:%s",szBuf);
*/
//转换后
TCHAR szBuf[]=_T("Hello!");
TCHAR szBuf2[16];
LPTSTR pszBuf=szBuf;
LPCTSTR pszBuf2=szBuf;
_tcscpy(szBuf2,szBuf);
int iLen=_tcslen(szBuf2);
int iLen2=sizeof(szBuf)/sizeof(TCHAR)-1;
_stprintf(szBuf2,_T("str is:%s"),szBuf);
1. MFC的CString类
1.1. CString实现的机制.
CString是通过“引用”来管理串的,象Window内核对象、COM对象等都是通过引用来实现的。而CString也是通过这样的机制来管理分配的内存块。实际上CString对象只有一个指针成员变量,所以任何CString实例的长度只有4字节.即:
int len = sizeof(CString);//len等于4
这个指针指向一个CStringData结构体类型对象的数据区,即从nAllocLength以后开始的区域:
struct CStringData
{
long nRefs; // 引用计数 www.2cto.com
int nDataLength; // 字符串长度
int nAllocLength; // 已分配的缓冲区大小,应该大于或等于字符串长度
// TCHAR data[nAllocLength]
TCHAR* data() // 实际的数据区
{ return (TCHAR*)(this+1); }
};
正因为如此,一个这样的内存块可被多个CString所引用,例如下列代码:
CString str("abcd");
CString a = str;
CString b(str);
CString c;
c = b;
由于有了这些信息,CString就能正确地分配、管理、释放引用内存块。
如果你想在调试程序的时候获得这些信息。可以在Watch窗口键入下列表达式:
(CStringData*)((CStringData*)(this->m_pchData)-1)或
(CStringData*)((CStringData*)(str.m_pchData)-1)//str为指CString实例
正因为采用了这样的好机制,使得CString在大量拷贝时,不仅效率高,而且分配内存少。
1.2. LPCTSTR 与 GetBuffer(int nMinBufLength)
这两个函数提供了与标准C的兼容转换。在实际中使用频率很高,但却是最容易出错的地方。这两个函数实际上返回的都是指针,但它们有区别:
1、LPCTSTR 它的执行过程其实很简单,只是返回引用内存块的串地址。它是作为操作符重载提供的,所以在代码中有时可以隐式转换,而有时却需强制转制。如:
CString str;
const char* p = (LPCTSTR)str;
//假设有这样的一个函数,Test(const char* p); 你就可以这样调用
Test(str);//这里会隐式转换为LPCTSTR
2、GetBuffer(int nMinBufLength) 它与LPCTSTR类似,也会返回一个指针,不过返回的是LPTSTR
3、一般说LPCTSTR转换后只应该当常量使用,或者做函数的入参;而GetBuffer(...)取出指针后,可以通过这个指针来修改里面的内容,或者做函数的入参。为什么呢?也许经常有这样的代码:
CString sBuf2=sBuf;//指向同一个内存块
//{{错误使用方法
char *pszTemp=(char *)(LPCTSTR)sBuf;
pszTemp[1]='Z'; //它会导致sBuf2的值也变化了
//}}错误使用方法
所以LPCTSTR做转换后,你只能去读这块数据,千万别去改变它的内容。
假如我想直接通过指针去修改数据的话,那怎样办呢?就是用GetBuffer(...):
sBuf="TestCString";
sBuf2=sBuf;//指向同一个内存块
//{{正确的使用方法
//它导致sBuf和sBuf2指向不同的内存块
pszTemp=sBuf.GetBuffer(0);//如果不希望缓冲区变大,直接传0就行了
pszTemp[1]='Z';
sBuf.ReleaseBuffer();
//}}正确的使用方法 CString str("abcd");
为什么会这样?其实GetBuffer(20)调用时,它实际上另外建立了一块新内块存,而原来的内存块引用计数也相应减1. 所以执行代码后sBuf与sBuf2是指向了两块不同的地方