一、序言
CString是对于原来标准c中字符串类型的一种的包装。因为,通过很长时间的编程,我们发现,很多程序的 bug多和字符串有关,典型的有:缓冲溢出、内存泄漏等。而且这些bug都是致命的,会造成系统的瘫痪。因此c++里就专门的做了一个类用来维护字符串指针。标准c++里的字符串类是string,在microsoft MFC类库中使用的是CString类。通过字符串类,可以大大的避免c中的关于字符串指针的那些问题。
MFC库的CString类是C++语言的一个很重要的扩展,CString类有许多非常有用的操作和成员函数,但最重要的一个特点莫过于他的动态内存分配,完全不用担心CString对象的大小。
CString 是一种很特殊的 C++ 对象,它里面包含了三个值:一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字符记数(它是不可存取的,是位于 CString 地址之下的一个隐藏区域)以及一个缓冲区长度。 有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数(因为字符串结尾有一个NULL字符)。字符记数和缓冲区长度被巧妙隐藏。
二、CString 常用方法与函数介绍
1. CString 对象的连接 +
CString类重载了操作符+,使+相当于字符串函数strcat。对象连接的例子如下:
CString gray("Gray");CString cat("Cat");CString graycat = gray + cat;
要比用下面的方法好得多:
char gray[] = "Gray"; char cat[] = "Cat"; char * graycat = malloc(strlen(gray) + strlen(cat) + 1);
strcpy(graycat, gray); strcat(graycat, cat);
2. CString对象格式化字符串 。Format()
与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串,还不如用 CString 对象的Format()方法:
CString s; s.Format(_T("The total is %d"), total);
用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大,这些工作由CString类替你完成。格式化是一种把其它不是字符串类型的数据转化为CString类型的最常用技巧,_T的作用,不用我再浪费口水了吧。
3. 改变大小写。CString::MakeUpper和CString::MakeLower两个成员函数(不带参数)能使整个字符串变成大/小写字母。举例如下:
str1 = “hello”; str1.MakeUpper(); afxDump << str1; // 输出结果是”HELLO”;
4. 反转字符串(逆置)void CString::MakeReverse();
5. 从.rc文件读入字符串:CString::LoadString函数把传入的字符串资源ID对应的字符串读入到CString对象中。如果成功就返回非零值。
BOOL bResult = LoadString(IDS_FILENOTFOUND);
6. 字串操作
6.1 去串左边空格:str1.TrimLeft();
6.2 去掉字符串右边空格:str1.TrimRight();
6.3 获得指定位置字符:char a = str1.GetAt(3); 相应的有CString::SetAt函数,修改指定位置字符。
6.4 删除字符串中所有指定字符:str1.Remove(char c)。举例如下:
str1 = “Hello test”; str1.Remove(‘t’); afxDump << str1; //输出”Hello es”;
6.5 删除指定位置指定长度的子串:str1.Delete。举例如下:
str1 = “Hello test”;
str1.Delete(3, 2); //第一个参数为index(从零开始) //第二个参数是长度
afxDump << str1; //输出”Hel test”;
6.6 清空对象的内容:void CString::Empty();
6.7 查找子串:
CString::Find函数有四个重载,可以进行字符和字串的搜索,同时还可以指定搜索的起始位置,并返回第一次查找到的index。
int Find( TCHAR ch ) const;
int Find( LPCTSTR lpszSub ) const;
int Find( TCHAR ch, int nStart ) const;
CString::ReverseFind是返回字符串中最后一个匹配字符的index(从正方向查找),与Find函数查找方向正好相反,可惜只有一种重载:
int ReverseFind( TCHAR ch ) const;int Find( LPCTSTR pstr, int nStart ) const;
CString::FindOneof查找的是第一个与指定字符串中任意一个匹配字符的index。
关于查找的举例如下:
str1 = “Hello test”; int j = str1.Find(“el”);
afxDump << “j=” << j << “/n”;
int k = str1.Find(‘e’, 3); afxDump << “k=” << k << “/n”;
int l = str1.ReverseFind(‘t’); afxDump << “l=” << l << “/n”;
int m = str1.ReverseFind(‘t’); afxDump << “m=” << m << “/n”;
int n = str1. FindOneOf(“stuv”); afxDump << “n=” << n << “/n”;
输出结果:
j=1 k=7 l=9 m=9 n=6
6.8 字串截断:
CString::Left、CString::Right函数都只带一个参数,并且都返回一个CString对象,作用是截取左/右边指定长度的子串。
CString::Mid函数第一个参数指定位置,第二个参数指定长度。
6.9 插入子串:用CString::Insert可以插入字符或者字串到指定位置
str1 = “Hello test”; str1.Insert(2,“ABCD”);
afxDump << str1; //输出”HeABCDllo test”
6.10 替换:CString::Replace的作用是将原来对象中的所有匹配相替换指定字符/子串。
有两个重载原型:
int Replace( TCHAR chOld, TCHAR chNew );
int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew );
6.11 CString对象分离子串 CString::SpanExcluding函数
以前回答过一个把CString对象分离子串的问题,现在想想,如果当时用这个函数的话,将使多么的方便。函数原型:CString SpanExcluding( LPCTSTR lpszCharSet ) const;
它查找CString对象中与lpszCharSet串中任意匹配的第一个字符,并返回一个CString对象,该对象的内容是原来对象从起始位置到查找到字符的前一个字符的部分。这在分离用分割符(逗号空格之类)隔开的子串的时候将十分方便: str1 = “Hello test”; str2 = str1.SpanExcluding(“ ,”); afxDump << str2; //输出”Hello”
同时,还有一个很方便的函数:CString::SpanIncluding,
函数原型:CString SpanIncluding( LPCTSTR lpszCharSet ) const;
它返回对象中前若干个字符,这些字符都必须在lpszCharSet之中:
str1 = “Hello test”; str2 = str1.SpanIncluding(“ABCDEFGHIJK”); afxDump << str2; //输出”H”
7. CString对象的属性操作:这些都很常用了,简要说明之
int GetLength( ) const; //获得buffer的长度
BOOL IsEmpty( ) const; //判断CString对象内容是否为空
int Compare( LPCTSTR lpsz ) const; //与lpsz按ASCII码比较
int CompareNoCase( LPCTSTR lpsz ) const; //与lpsz按ASCII码比较,忽略大小写
三、CString的对象的类型的转换
1. CString与int类型的转换
把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程。虽然通常你怀疑使用_atoi()函数是一个好的选择,它也很少会是一个正确的选择。如果你准备使用 Unicode 字符,你应该用_ttoi(),它在 ANSI 编码系统中被编译成_atoi(),而在 Unicode 编码系统中编译成_wtoi()。你也可以考虑使用_tcstoul()或者_tcstol(),它们都能把字符串转化成任意进制的长整数(如二进制、八进制、十进制或十六进制),不同点在于前者转化后的数据是无符号的(unsigned),而后者相反。看下面的例子:
CString hex = _T("FAB");
CString decimal = _T("4011");
ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));
2. CString 与char *的相互转换
2.1 char*转换成CString
若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:
char chArray[] = "Char test";
TCHAR * p = _T("Char test");( 或LPTSTR p = _T("Char test");)
CString theString = chArray;
theString.Format(_T("%s"), chArray);
theString = p;
2.2 CString转换成char*
若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:
方法一,使用强制转换。例如:
CString theString( (_T("Char test "));
LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;
方法二,使用strcpy。例如:
CString theString( (_T("Char test "));
LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
_tcscpy(lpsz, theString);
方法三,使用CString::GetBuffer。
如果你需要修改 CString 中的内容,它有一个特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一个可写的缓冲指针。 如果你只是打算修改字符或者截短字符串,例如:
CString s(_T("Char test "));
LPTSTR p = s.GetBuffer(); LPTSTR dot = strchr(p, ''.'');
// 在这里添加使用p的代码
if(p != NULL)
*p = _T('/0');
s.ReleaseBuffer(); // 使用完后及时释放,以便能使用其它的CString成员函数
在 GetBuffer 和 ReleaseBuffer 之间这个范围,一定不能使用你要操作的这个缓冲的 CString 对象的任何方法。因为 ReleaseBuffer 被调用之前,该 CString 对象的完整性得不到保障。
需要说明的是,strcpy(或可移值的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。