C++中STL的string类模板与MFC中Cstring类区别与联系

60 篇文章 5 订阅
54 篇文章 1 订阅
        最近在做一个linux上的C语言的项目,要频繁的用到char *字符串操作,即用C语言提供的string.h中的标准字符串操作API对字符进行操作,工作量非常的,怀念以前用C++做项目的时候用STL的 string模版类。当然如果是在windows上开发支持MFC的工程,也可以用MFC类库中的Cstring。在Linux上当然不会有微软的MFC 类库了咯,所以只能用标准C++的string类(也就是STL里面的string类)。

下面对Cstring类与string类做一个比较:

相同点:

(1)用他们都可以取代对char*的使用。

(2)都封装了有丰富的字符串操作接口。

(3)他们都是C++的类库。---也许你会说这不是明摆着的嘛,对,但是用的时候要记住。以string的使用为例,不能有如下用法:

     string * pstr = NULL;              //定义一个指向字符串的指针

     pstr->append("Hello world.");      //在该字符串的末尾粘接上另一个字符。

这样做编译器不会有任何警告和错误,但是运行的时候就会有异常。什么原因呢?

原因是没有理解string是一个类,而在定义类的对象的时候是需要调用其构造函数的。上面既没有调用string的构造函数,而且还把指针赋值为NULL,很明显调用该类的对象的接口的时候会出错。但是编译器却发现不了这个问题的。

正确的方法是如下:

/*这里必须要用c++的宏new,而不能用c中的malloc,原因是new不但会分配一块内存,*/
 /*还执行了类的构造函数。当然,string类的实例化还可以通过已有的某个string对象进行,请另查阅*/

 string * pstr = new string("Hello world.");
 pstr->append("Hello world.");
 cout<<"string * pstr is:"<<*pstr<<endl;

或者不用指针,如下也可以:

string str;     //会自动调用默认的构造函数,构造一个string类的对象。

str.apend("Hello world.");

cout<<"string str is:"<<str<<endl;

(4)他们都使用了模板的技术。

不同之处:

(1)CString 类是微软的visual c++提供的MFC里面的一个类,所以只有支持MFC的工程才可以使用。如在linux上的工程就不能用CString了,只能用标准C++中的 string类了。另外,因为string类是在c++标准库中,所以它被封装在了std命名空间中,使用之前需要声明using namespace std;而CString类并不在std命名空间中,因为它不是c++的标准库,只是微软的一个封装库。这点看来用string类的程序的移植性更好。

(2)string类既是一个标准c++的类库,同时也是STL(Standard Template Library,标准模版库)中的类库,所以支持Iterator操作。

(3)CString类和string类提供的方法接口并不完全相同,所以不要糊里糊涂的认为某个类中怎么没有另外一个类中的方法啊。:-)。。

(4)他们和char*之间的转黄方法也不一样。string类型的变量如果要转换成char*类型字符串,string类中提供了三个方法如下:

const charT* c_str() const                     //c_str 直接返回一个以\0结尾的字符串。 
const charT* data() const                      //data 直接以数组方式返回string的内容,其大小为size()的返回值,结尾并没有\0字符
size_type copy(charT* buf, size_type n, size_type pos = 0) const   //copy 把string的内容拷贝到buf空间中。
注意:c_str()的返回类型是指向常量charT类型的指针,说明指针所指空间的内容不允许修改,只可以读取不可以更改。c_str()返回的指针
     是string内部的指针,并没有像copy函数一样把其内容拷贝出来。这可以从下面例子中看出来:
 string * pstr = new string("Hello world.");

 const char * ptmp = pstr->c_str();              //并没有通过malloc或者new为指针ptmp分配内存,只是把string中的数据指针赋给了ptmp而已
 cout<<"Get the string->cstr is:"<<ptmp<<endl;   //正确的输出了Hello world.
但是如果用copy方法时必须如下方法:
 char * p = (char *)malloc(100*sizeof(char));    //必须为指针p分配内存空间用于存放从string里拷贝出来的数据
 pstr->copy(p,pstr->length(),0);                 //如果没有上面分配内存空间,这个语句在运行时就会报段错误。
 cout<<"char * p:copy from string is:"<<p<<endl; //正确的输出了字符串Hello world

CString类型字符串对象转换成char*字符串比较麻烦一点,方法也有3种,

方法一,使用强制转换。例如:

CString theString( "This is a test" );
LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;

  方法二,使用strcpy。例如:

CString theString( "This is a test" );
LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
_tcscpy(lpsz, theString);

  需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。

  方法三,使用CString::GetBuffer。例如:

CString s(_T("This is a test "));
LPTSTR p = s.GetBuffer();
// 在这里添加使用p的代码
if(p != NULL) *p = _T('\0');
s.ReleaseBuffer();
// 使用完后及时释放,以便能使用其它的CString成员函数
-------------------------------------------------------------------

我尝试了后面两种,都能成功,最后我还是选用了简单的第二种方法,因为采用第三种方法的话,需要用GetBuffer();函数,而该函数的使用需要非常的小心谨慎。

源码如下:

/**********
检查输入的手机型号是否合法。规定手机型号以CoolPad_开始。合法则返回TRUE,否则返回FALSE
***********/

BOOL CAutoBuildConfigDlg::CheckMobileName(CString strMobileName)
{
 wchar_t * pdest;
 CString strMobileName_temp;
 strMobileName_temp = strMobileName;
 TCHAR strCOOLPAD[] = L"COOLPAD_";

 LPTSTR lpsz =  new TCHAR[strMobileName_temp.GetLength()+1];
 wcsncpy_s(lpsz,(strMobileName_temp.GetLength()+1),strMobileName_temp, (strMobileName_temp.GetLength()+1));

 errno_t err;
 err = _wcsupr_s(lpsz,strMobileName_temp.GetLength()+1);//因为没有找到不区分大小写的查找子字符串的函数,所以决定转换成大写然后进行比较。
 pdest = wcsstr( lpsz,strCOOLPAD );

 if( pdest != NULL )
 {
   return TRUE;
 }
 else
 {
  return FALSE;
 }
}


===================================================================================================================================

转自:http://www.busfly.cn/csdn/post/cpp-CString-string-char.html

关键点:<CStirng>主要用于MFC的编写,而<string>属于STL,两者都是符合标准C++的,但是在非windows平台或者说VC上还是用<string>吧。另外还有一个<string.h>这是传统C++才有的~

(一) 概述
string和CString均是字符串模板类,string为标准模板类(STL)定义的字符串类,已经纳入C++标准之中;
CString(typedef CStringT> CString)为Visual C++中最常用的字符串类,继承自CSimpleStringT类,主要应用在MFC和ATL编程中,主要数据类型有char(应用于ANSI),wchar_t(unicode),TCHAR(ANSI与unicode均可);
char*为C编程中最常用的字符串指针,一般以''为结束标志;
(二) 构造
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) 查找
作用 char* string CString
查找指定值 strchr
strstr
strrstr
strspn find Find
第一个匹配的值 fild_first_of FindOneOf
从后面开始查找 ReserveFind
指定匹配方式 find_if


注:find_if中是把范围内的值挨个代入匹配函数直至返回true
b) 比较
作用 char* string CString
查找指定值(区分大小写) strcmp
strncmp
strcoll
_strncoll operator<
operator>
operator<=
operator>=
operator==
operator!= Collate
Compare
查找指定值(不区分大小写) _stricmp
_strnicmp
_stricoll
_strnicoll CollateNoCase
CompareNoCase


注:返回值如果<0则前面的值小于后面的值,反之亦然
c) 替换
作用 char* string CString
查找指定值 _strset
_strnset replace
replace_copy
replace_copy_if
replace_if
Replace


d) 插入
作用 char* string CString
查找指定值 insert Insert


e) 增加
作用 char* string CString
动态增加值 strcat push
append Append
AppendChar
AppendFormat


f) 截取
作用 char* string CString
得到部分值 用下标操作 substr Left
Mid
Right
Truncate


g) 移除
作用 char* string CString
移除部份值 remove Remove
移除空白值 RemoveBlanks
注:此为ATL提供,非C函数 remove_if Trim
TrimLeft
TrimRigth


h) 转换大小写
作用 char* string CString
转换大小写 _strlwr
_strupr MakeLower
MakeUpper


i) 与其他类型转换
作用 char* string CString
转化为数字 atoi
atod
atof Format
转化为char* c_str GetBuffer
GetBufferSetLength


j) 格式化
作用 char* string CString
格式化 sprintf Format


k) 得到长度
作用 char* string CString
得到长度 strlen length GetLength
得到大小 size GetAllocLength


l) 判断为空
作用 char* string CString
判断是否为空 判断是否==NULL或者第一个字符是否是’’ empty IsEmpty


m) 重定义大小
作用 char* string CString
重定义大小 realloc
new resize GetBufferSetLength


n) 释放资源
作用 char* string CString
释放 free
delete (delete[]) ReleaseBuffer
ReleaseBufferSetLength


(五) 安全性
CString > string > char*
(六) 灵活性
CString > string >char*
(七) 可移植性
char* = string > CString
总结
综上所述,在MFC、ATL中使用字符串尽量使用CString,毕竟都是微软的孩子,各方面都比其它更有优势,而在非微软平台上或对移植性要求较高的场合推荐使用string,标准模板库提供了那么强大的泛型算法,没必要再自己去造车轮。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值