MFC CString类成员函数实现原理

时间:2023-01-31 18:57:17

        在MFC框架中,CString类用的很多,它是对原来标准c中字符串类型的一种包装,因为里面有两个成员变量char* m_pData和int m_nLength来维护这个类。

对于成员函数:

1、几个默认的构造函数

CString(); //缺省构造

CString( const CString& stringSrc );//拷贝构造
CString( const char* lpsz );//根据字符串常量初始化
CString( char ch, int nRepeat = 1);//串内有n个ch字符

CString(const char* cstr,int nLength);//根据字符串常量的一部分


实现函数:


CString::CString()
{
	//m_pData = new char;
	//m_pData[0] = 0
	m_pData = new char(0);//new一个字符串 并且等于0
	m_nLength = 0;
}



//拷贝构造发生的条件是:当用一个已有的对象作为初始化数据构造一个新对象时
CString::CString( const CString& str )	//拷贝构造
{
	m_nLength = str.m_nLength;

	//由于是拷贝构造,不需要删除原来的空间
	//申请内存空间
	m_pData = new char[m_nLength+1];

	//m_pData = str.m_pData;//浅拷贝

	strcpy(m_pData,str);//深拷贝

}


CString::CString( const char* lpsz )		//根据字符串常量初始化
{
	m_nLength = strlen(lpsz);

	//申请空间
	m_pData = new char[m_nLength + 1];
	strcpy(m_pData,lpsz);
}
</pre><pre name="code" class="html">CString::CString( char ch, int nRepeat)	//串内有n个ch字符
{
	m_nLength = nRepeat;
	m_pData = new char[m_nLength+1];

	m_pData[m_nLength] = '\0';//最后一个字符表示为0;
	int i = m_nLength;
	while(i--)
	{
		m_pData[i] = ch;
	}
}

</pre><pre name="code" class="html">CString::CString(const char* cstr,int nLength)//根据字符串常量的一部分
{
	//m_nLength = nLength;
	//m_pData = new char[nLength+1];
	//strncpy(m_pData,cstr,nLength);//函数根据长度进行拷贝
	m_nLength = strlen(cstr);
	m_nLength = m_nLength>nLength ? nLength:m_nLength;
	m_pData = new char[m_nLength+1];
	m_pData[m_nLength] = '\0';
	int i =0;
	while(i<m_nLength)
		m_pData[i] = cstr[i++];

}


2、赋值操作函数

CString& operator=(const char* cstr) ;//删除已有文字的堆空间,重新分配
CString& operator=(const CString &str);//删除已有文字的堆空间,重新分配

<span style="font-size:18px;">//重载赋值操作
CString& CString::operator=(const char* cstr) 	//删除已有文字的堆空间,重新分配
{
	int nLen = strlen(cstr);
	if (nLen>m_nLength)
	{
		//删除已有的堆空间
		delete []m_pData;
		m_pData = new char[m_nLength+1];
	}
	//m_pData = cstr;//浅拷贝
	m_nLength = nLen;
	strcpy(m_pData,cstr);
	return *this;

}
CString& CString::operator=(const CString &str)	//删除已有文字的堆空间,重新分配
{
	int nlen = str.m_nLength;
	if (nlen > m_nLength)
	{
		//删除已有长度
		delete []m_pData;
		m_pData = new char[nlen + 1];
	}

	m_nLength = nlen;
	strcpy(m_pData,str.m_pData);

	return *this;
}</span>

3、类型转化

operator const char* () const;

char operator []( int nIndex ) const;//获取串内上的某个字符

	//类型转化
	operator const char* () const
	{
		return m_pData;
	}
	//凡是单行函数放在头文件中,编译器会自动使用inline内联格式编译
	char operator []( int nIndex ) const	//获取串内上的某个字符
	{
		return m_pData[nIndex];
	}


4、友元函数

friend bool operator!=(const CString& str1,const CString& str2) ;
friend bool operator==(const CString& str1,const CString& str2) ;
friend bool operator<(const CString& str1, const CString& str2) ;
friend bool operator>(const CString& str1,  const CString& str2) ;


bool operator!=(const CString& str1,const CString& str2)
{
	return strcmp(str1,str2) != 0;
}
bool operator==(const CString& str1,const CString& str2) 
{
	return !strcmp(str1,str2);
}
bool operator<(const CString& str1, const CString& str2) 
{
	return strcmp(str1,str2)<0;
}
bool operator>(const CString& str1,  const CString& str2) 
{
	return strcmp(str1,str2)>0;
}


 
 

5、查找替换函数

CString Mid( int nFirst ) const;CString Mid( int nFirst, int nCount ) const;

CString Left( int nCount ) const;//截取右边的字符串 CString Right( int nCount ) const{ return Mid(m_nLength - nCount,nCount);}

CString CString::Mid( int nFirst ) const
{
	return Mid(nFirst,m_nLength - nFirst);
}

//原字符串不变
//需要进行条件判断
CString CString::Mid( int nFirst, int nCount ) const
{
	CString str;
	if (nFirst<0)
	{
		nFirst = 0;
	} 
	if (nCount <= 0 || nFirst > m_nLength -1)
	{
		return str;//直接返回空字符串
	}

	//在中间区域
	int nLen = m_nLength - nFirst;
	//如果nlen 比ncount大,则拷贝nfirst后面的所有字符
	nLen = nLen < nCount ? nLen:nCount;

	//释放原有的空间,一个字节
	delete []str.m_pData;//重要
	str.m_pData = new char[nLen+1];
	//逐一拷贝
	str.m_nLength = nLen;
	str.m_pData[nLen] = '\0';
	while(nLen--)
	{
		str.m_pData[nLen] = m_pData[nFirst+nLen];
	}

	//为什么会触发构造函数,,?
	return str;

}
//
CString CString::Left( int nCount ) const
{
	return Mid(0,nCount);
}

void CString::MakeUpper( )
{
	int i = m_nLength;
	while(i--)
	{
		m_pData[i] = _toupper(m_pData[i]);
	}

	//也可以用
	//_strupr(m_pData);直接转化
}
void CString::MakeLower( )
{
	_strlwr(m_pData);
}
void CString::MakeReverse( )
{
	//int i = 0,j = m_nLength-1;
	//char c;
	//while(i<j)
	//{
	//	c = m_pData[i];
	//	m_pData[i] = m_pData[j];
	//	m_pData[j] = c;
	//	++i;
	//	++j;
	//}

	int i = 0,j = m_nLength;
	char c;
	char *p = m_pData;
	char *q = m_pData+m_nLength-1;
	while(p<q)
	{
		c = *p;
		*p = *q;
		*q = c;
		++p;
		--q;
	}
}

int CString::Replace( char chOld, char chNew )
{
	int i = m_nLength;
	int nCount = 0;
	while(i--)
	{
		if (m_pData[i] == chOld)
		{
			m_pData[i] = chNew;
			++nCount;
		}
	}
	return nCount;
}

int CString::Find( char ch ) const
{
	int i = 0;
	while(i<m_nLength)
	{
		if (m_pData[i] == ch)
		{
			return i;
		}
		++i;
	}
	return -1;
}

//int CString::Find( const char* lpszSub ) const
//{
//	
//}
//int CString::Find( char ch, int nStart ) const
//{
//
//}
int CString::Find( const char* pstr, int nStart ) const
{
	//字串比较
	if (nStart>=m_nLength)
	{
		return -1;
	}
	char *p = strstr(m_pData+nStart,pstr);
	return p-m_pData;//返回的索引是基于首地址的
}

int CString::ReverseFind( char ch ) const
{
	int i = m_nLength;
	while(i--)
	{
		if (m_pData[i] == ch)
		{
			return i;
		}
	}
	return -1;
}