VC++常用数据类型及其操作详解
-------西安邮电学院计算机系
徐兆元(FLxyzsby@https://www.doczj.com/doc/dc18544894.html, FLxyzsby@https://www.doczj.com/doc/dc18544894.html,)
2004/08/03 目录
一.VC常用数据类型列表
二.常用数据类型转化
2.1数学类型变量与字符串相互转换
2.2CString及string,char *与其他数据类型的转换和操作
●CString,string,char*的综合比较
●数学类型与CString相互转化
●CString与char*相互转换举例
●CString 与BSTR 型转换
●V ARIANT 型转化成CString 型
2.3 BSTR、_bstr_t与CComBSTR
2.4 V ARIANT 、_variant_t 与COleVariant
附录CString及字符串转及操作详解
参考书籍:CSDN,<
一.VC常用数据类型列表
说明:
(1)-------表示省略
(2)1Byte=8Bit,
字与机器有关,在8位系统中:字=1字节,16位系统中,1字=2字节,32位中:1字=4字节, 64位中1字=8字节.不要搞混这些概念.
二.常用数据类型转化及操作
2.1 数学类型变量与字符串相互转换(这些函数都在STDLIB.H里)
(1)将数学类型转换为字符串可以用以下一些函数:
举例: _CRTIMP char * __cdecl _itoa(int, char *, int);//这是一个将数字转换为一个字符串类型的函数,最后一个int表示转换的进制
如以下程序:
int iTyep=3;
char *szChar;
itoa(iType,szChar,2);
cout< 类似函数列表: _CRTIMP char * __cdecl _itoa(int, char *, int);//为了完整性,也列在其中 _CRTIMP char * __cdecl _ultoa(unsigned long, char *, int); _CRTIMP char * __cdecl _ltoa(long, char *, int); _CRTIMP char * __cdecl _i64toa(__int64, char *, int); _CRTIMP char * __cdecl _ui64toa(unsigned __int64, char *, int); _CRTIMP wchar_t * __cdecl _i64tow(__int64, wchar_t *, int); _CRTIMP wchar_t * __cdecl _ui64tow(unsigned __int64, wchar_t *, int); _CRTIMP wchar_t * __cdecl _itow (int, wchar_t *, int);//转换为长字符串类型 _CRTIMP wchar_t * __cdecl _ltow (long, wchar_t *, int); _CRTIMP wchar_t * __cdecl _ultow (unsigned long, wchar_t *, int); 还有很多,请自行研究 (2)将字符串类型转换为数学类型变量可以用以下一些函数: 举例: _CRTIMP int __cdecl atoi(const char *);//参数一看就很明了 char *szChar=”88”; int temp(0); temp=atoi(szChar); cout< 类似的函数列表: _CRTIMP int __cdecl atoi(const char *); _CRTIMP double __cdecl atof(const char *); _CRTIMP long __cdecl atol(const char *); _CRTIMP long double __cdecl _atold(const char *); _CRTIMP __int64 __cdecl _atoi64(const char *); _CRTIMP double __cdecl strtod(const char *, char **);// _CRTIMP long __cdecl strtol(const char *, char **, int);// _CRTIMP long double __cdecl _strtold(const char *, char **); _CRTIMP unsigned long __cdecl strtoul(const char *, char **, int); _CRTIMP double __cdecl wcstod(const wchar_t *, wchar_t **);//长字符串类型转换为数学类型_CRTIMP long __cdecl wcstol(const wchar_t *, wchar_t **, int); _CRTIMP unsigned long __cdecl wcstoul(const wchar_t *, wchar_t **, int); _CRTIMP int __cdecl _wtoi(const wchar_t *); _CRTIMP long __cdecl _wtol(const wchar_t *); _CRTIMP __int64 __cdecl _wtoi64(const wchar_t *); 还有很多,请自行研究 2.2.CString及string,char *与其他数据类型的转换和操作 (1)CString,string,char*的综合比较(这部分CSDN上的作者joise的文章 << CString,string,char*的综合比较>>写的很详细,请大家在仔细阅读他的文章. 地址: https://www.doczj.com/doc/dc18544894.html,/joise/ 或参考附录: (2)转换: ●数学类型与CString相互转化 数学类型转化为CString 可用Format函数,举例: CString s; int i = 64; s.Format("%d", i) CString转换为数学类型:举例 CString strValue("1.234"); double dblValue; dblValue = atof((LPCTSTR)strValue); ●CString与char*相互转换举例 CString strValue(“Hello”); char *szValue; szValue=strValue.GetBuffer(szValue); 也可用(LPSTR)(LPCTSTR)对CString// 进行强制转换. szValue=(LPSTR)(LPCTSTR)strValue; 反过来可直接赋值: char *szChar=NULL; CString strValue; szChar=new char[10]; memset(szChar,0,10); strcpy(szChar,”Hello”); strValue=szChar; ●CString 与BSTR 型转换 CString 型转化成BSTR 型 当我们使用ActiveX 控件编程时,经常需要用到将某个值表示成BSTR 类型.BSTR 是一种记数字符串,Intel平台上的宽字符串(Unicode),并且可以包含嵌入的NULL 字符。 可以调用CString 对象的AllocSysString 方法将CString 转化成BSTR: CString str; str = .....; // whatever BSTR bStr = str.AllocSysString(); BSTR型转换为CString 如果你在UNICODE 模式下编译代码,你可以简单地写成: CString convert(BSTR bStr) { if(bStr == NULL) return CString(_T("")); CString s(bStr); // in UNICODE mode return s; } 如果是ANSI 模式 CString convert(BSTR b) { CString s; if(b == NULL) return s; // empty for NULL BSTR #ifdef UNICODE s = b; #else LPSTR p = s.GetBuffer(SysStringLen(b) + 1); ::WideCharToMultiByte(CP_ACP, // ANSI Code Page 0, // no flags b, // source widechar string -1, // assume NUL-terminated p, // target buffer SysStringLen(b)+1, // target buffer length NULL, // use system default char NULL); // don''t care if default used s.ReleaseBuffer(); #endif return s; } ●V ARIANT 型转化成CString 型 V ARIANT 类型经常用来给COM 对象传递参数,或者接收从COM 对象返回的值。你也能自己编写返回V ARIANT 类型的方法,函数返回什么类型依赖可能(并且常 常)方法的输入参数(比如,在自动化操作中,依赖与你调用哪个方法。IDispatch::Invoke 可能返回(通过其一个参数)一个包含有BYTE、WORD、float、double、date、BSTR 等等V ARIANT 类型的结果,(详见MSDN 上的V ARIANT 结构的定义)。在下面的例子中,假设类型是一个BSTR的变体,也就是说在串中的值是通过bsrtVal 来引用,其优点是在ANSI 应用中,有一个构造函数会把LPCWCHAR 引用的值转换为一个CString(见BSTR-to-CString 部分)。在Unicode 模式中,将成为标准的CString 构造函数,参见对缺省::WideCharToMultiByte 转换的告诫,以及你觉得是否可以接受(大多数情况下,你会满意的)。V ARIANT vaData; vaData = m_com.YourMethodHere(); ASSERT(vaData.vt == VT_BSTR); CString strData(vaData.bstrVal); 你还可以根据vt 域的不同来建立更通用的转换例程。为此你可能会考虑:CString VariantToString(V ARIANT * va) { CString s; switch(va->vt) { /* vt */ case VT_BSTR: return CString(vaData->bstrVal); case VT_BSTR | VT_BYREF: return CString(*vaData->pbstrVal); case VT_I4: s.Format(_T("%d"), va->lVal); return s; case VT_I4 | VT_BYREF: s.Format(_T("%d"), *va->plVal); case VT_R8: s.Format(_T("%f"), va->dblVal); return s; ... 剩下的类型转换由读者自己完成 default: ASSERT(FALSE); // unknown V ARIANT type (this ASSERT is optional) return CString(""); } /* vt */ } 2.3 BSTR、_bstr_t与CComBSTR CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。 char *转换到BSTR可以这样: BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上头文件comutil.h 反之可以使用char *p=_com_util::ConvertBSTRToString(b); 2.4(引)V ARIANT 、_variant_t 与COleVariant V ARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagV ARIANT 的定义。 对于V ARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子: V ARIANT va; int a=2001; va.vt=VT_I4;///指明整型数据 va.lVal=a; ///赋值 对于不马上赋值的V ARIANT,最好先用V oid VariantInit(V ARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系: unsigned char bVal; VT_UI1 short iVal; VT_I2 long lVal; VT_I4 float fltVal; VT_R4 double dblVal; VT_R8 V ARIANT_BOOL boolVal; VT_BOOL SCODE scode; VT_ERROR CY cyVal; VT_CY DATE date; VT_DA TE BSTR bstrVal; VT_BSTR IUnknown FAR* punkVal; VT_UNKNOWN IDispatch FAR* pdispVal; VT_DISPATCH SAFEARRAY FAR* parray; VT_ARRAY|* unsigned char FAR* pbVal; VT_BYREF|VT_UI1 short FAR* piVal; VT_BYREF|VT_I2 long FAR* plVal; VT_BYREF|VT_I4 float FAR* pfltVal; VT_BYREF|VT_R4 double FAR* pdblVal; VT_BYREF|VT_R8 V ARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL SCODE FAR* pscode; VT_BYREF|VT_ERROR CY FAR* pcyVal; VT_BYREF|VT_CY DATE FAR* pdate; VT_BYREF|VT_DATE BSTR FAR* pbstrVal; VT_BYREF|VT_BSTR IUnknown FAR* FAR* ppunkVal; VT_BYREF|VT_UNKNOWN IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH SAFEARRAY FAR* FAR* pparray; VT_ARRAY|* V ARIANT FAR* pvarVal; VT_BYREF|VT_V ARIANT void FAR* byref; VT_BYREF _variant_t是V ARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。 例如: long l=222; ing i=100; _variant_t lVal(l); lVal = (long)i; COleVariant的使用与_variant_t的方法基本一样,请参考如下例子: COleVariant v3 = "字符串", v4 = (long)1999; CString str =(BSTR)v3.pbstrVal; long i = v4.lVal; 附录 CString,string,char*的综合比较 (一)概述 string和CString均是字符串模板类,string为标准模板类(STL)定义的字符串类,已经纳入C++标准之中; CString(typedef CStringT char*为C编程中最常用的字符串指针,一般以’\0’为结束标志; (二)构造 ?string是方便的,可以从几乎所有的字符串构造而来,包括CString和char*; ?CString次之,可以从基本的一些字符串变量构造而来,包括char*等; ?char*没有构造函数,仅可以赋值; ?举例: char* psz = “joise”; CString cstr( psz ); string str( cstr ); (三)运算符重载 a)operator= ?string是最方便的,几乎可以直接用所有的字符串赋值,包括CString和char*; ?CString次之,可以直接用些基本的字符串赋值,包括char*等; ?char*只能由指针赋值,并且是极危险的操作,建议使用strcpy或者memcpy,而且char*在声 明的时候如未赋初值建议先设为NULL,以避免野指针,令你抓狂; ?举例: char *psz = NULL; psz = new char[10]; //当然,以上的直接写成char *psz = new char[10];也是一样 memset( psz, 0, 10 ); strcpy( psz, “joise” ); CString cstr; cstr = psz; string str; str = psz; str = cstr; delete []psz; b)operator+ ?string与CString差不多,可以直接与char*进行加法,但不可以相互使用+运算符,即string str = str + cstr是非法的,须转换成char*; ?char*没有+运算,只能使用strcat把两个指针连在一起; ?举例: char* psz = “joise”; CString cstr = psz; cstr = cstr + psz; string str = psz; str = str + str + psz; strcat( psz, psz ); strcat( psz, cstr );//合法 strcat( psz, str );//非法,由此可见,CString可自动转换为const char*,而string不行 c)operator += ?string是最强大的,几乎可以与所有的字符串变量+=,包括CString和char*; ?CString次之,可以与基本的一些字符串变量进行+=而来,包括char*等; ?char*没有+=运算符,只能使用strcat把两个指针连在一起; d)operator[] ?CString最好,当越界时会抛出断言异常; ?string与char*下标越界结果未定义; ?举例: char* psz = “joise”; CString cstr = psz; cout << cstr[8]; string str = psz; cout << str[8]; cout << psz[8]; e)operator== 、operator!=、operator> 、operator< 、operator>= 、perator<= ?CString与string之间不可以进行比较,但均可以与char*进行比较,并且比较的是值,而不 是地址; cout << ( psz == cstr ); cout << ( psz == str ); cout << ( str == psz ); cout << ( cstr == psz );//以上代码返回均为1 (四) 常用算法 a) 查找 注:find_if 中是把范围内的值挨个代入匹配函数直至返回true b) 比较 注:返回值如果<0则前面的值小于后面的值,反之亦然 c) 替换 d) 插入 e) 增加 f)截取 g)移除 h)转换大小写 i)与其他类型转换 j)格式化 k)得到长度 l)判断为空 m)重定义大小 n)释放资源 (五)安全性 CString > string > char*; (六)灵活性 CString > string >char*; (七)可移植性 char* = string > CString (八)MFC中常用字符串结构图(此非比较,但为了方便查阅就一并算在这儿了) (九)总结 综上所述,我个人认为,在MFC、ATL中使用字符串尽量使用CString,毕竟都是微软的孩子,各方面都比其它更有优势,而在非微软平台上或对移植性要求较高的场合推荐使用string,标准模板库提供了那么强大的泛型算法,没必要再自己去造车轮。 (十)参考文献 主要参考的是MSDN,就不一一列出了。