c++字符串类的封装带引用计数

c++字符串类的封装带引用计数

ClassStr

ClassStr.h

cpp 复制代码
/*
想学习c++的伙伴们,一起加入c++学习群553235560   。
想学习c++的伙伴们,一起加入c++学习群553235560   。
想学习c++的伙伴们,一起加入c++学习群553235560   。
想学习c++的伙伴们,一起加入c++学习群553235560   。

*/
#pragma once
#include <iostream>
using namespace std;


class ClassStr
{
public:
/*******************构造函数系列开始***********************/
/*  
   * ClassStr
   * 参数一 : 无
   * 功能   :默认构造,初始化类成员 --为空
   * 返回值 :无
*/

	ClassStr();

/*
	* ClassStr(const char* Str)
	* 参数一 : 字符串指针
	* 功能   :带参构造,初始化类成员--初始化字符串
	* 返回值 :无
*/
	ClassStr(const char* Str);

/*
	* ClassStr(int nNumber)
	* 参数一 : 整形
	* 功能   :带参构造,初始化类成员--初始化字符串
	* 返回值 :无
*/
	ClassStr(int nNumber);

/*
	* ClassStr(ClassStr& cStr)
	* 参数一 : 类引用
	* 功能   :浅拷贝,当类相等的时候调用
	* 返回值 :无
*/

    ClassStr(ClassStr& cStr);//字符串设置为浅拷贝,字符串指向同一块内存,增加一个引用计数

/*
	* operator=
	* 参数一 : 引用
	* 功能   :=号运算符重载
	* 返回值 :自身
*/

/*
	* ~ClassStr
	* 参数一 : 无
	* 功能   :析构函数,释放类成员堆栈资源
	* 返回值 :无
*/
	~ClassStr();
/*******************构造函数系列结束***********************/


/*******************运算符重载系列开始***********************/
/*
	* operator=
	* 参数一 :类引用
	* 功能   :=号运算符重载
	* 返回值 :无

*/
	void operator= (ClassStr& cStr);// =号运算符重载
/*
	* operator=
	* 参数一 : 整形
	* 功能   :=号运算符重载
	* 返回值 :无
*/
	void operator= (int nNumber);// =号运算符重载

/*
	* operator+
	* 参数一 : 整形
	* 功能   :+号运算符重载
	* 返回值 :无
*/
	int operator+ (int nNumber);// =号运算符重载

/*
	* operator-
	* 参数一 : 整形
	* 功能   :+号运算符重载
	* 返回值 :无
*/
	int operator- (int nNumber);// =号运算符重载


/*
	* operator[]
	* 参数一 : 整形
	* 功能   :修改字符串索引值
	* 返回值 :无
	* 实现类可以直接[]修改值
	* ClassStr cStr = "wooaoaoa0ao";
    *  cStr[3] = 'b';
*/
	char& operator[] (int nIndex);// =号运算符重载
/*******************运算符重载系列结束***********************/




/*******************获取类成员系列开始***********************/
/*
	* GetStr
	* 参数一 : 无
	* 功能   :返回m_str字符串
	* 返回值 :char*
*/
	const char* GetStr();


/*******************获取类成员系列结束***********************/

/*   增删改查系列查这里开始*/

/*******************字符串增加功能开始***********************/
/*
	* Insert
	* 参数一 : int 插入位置
	* 参数二 :const char* 插入字符串
	* 功能   :往字符串里面插入字符
	* 返回值 :char*
*/
	ClassStr& Insert(int nPosition,const char* str);
/*
	* FrontInsert
	* 参数一 : 无
	* 功能   :往字符串头部插入字符
	* 返回值 :void
*/
	void FrontInsert(const char* str);

/*
	* TailInsert
	* 参数一 : 无
	* 功能   :往字符串尾部插入字符
	* 返回值 :void
*/
	void TailInsert(const char* str);

/*******************字符串插入功能结束***********************/


/*******************字符串删除功能开始***********************/
/*
	* Delete
	* 参数一 : int  索引
	* 参数二 : int  删除数量
	* 功能   :往字符串尾部插入字符
	* 返回值 :ClassStr& 
*/
	ClassStr& Delete(int nIndex,int nCount);




/*******************字符串删除功能结束***********************/

/*******************字符串查找功能开始***********************/
/*
	* HeadFind
	* 参数一 : const char* str
	* 功能   :首部开始查找字符串
	* 返回值 :返回索引,失败返回-1;

*/
	int HeadFind(const char* str);

/*
	* TailFind
	* 参数一 : const char* str
	* 功能   :尾部开始查找字符串
	* 返回值 :返回索引,失败返回-1;

*/
	int TailFind(const char* str);
/*
	* HeadFindCount
	* 参数一 : const char* str
	* 功能   :首部开始查找字符串,返回该字符串出现过的次数
	* 返回值 :int 返回次数;一次未出现过返回0

	直接调用了IsCmpContinuesHead函数来判断是否为-1 ,效率上会低点,可以优化;
*/
	int HeadFindCount(const char* str);


/*******************字符串查找功能结束***********************/

/*******************字符串修改功能开始***********************/
	

/*
	* Modify
	* 参数一 : const char* str nStr:字符串中需要被修改的字符
	* 参数二 : const char* str     :改变成这个字符串
	* 参数三 : bool                :是所有替换,还是只替换一次 false一次  true 所有替换
	* 功能   :字符串修改替换
	* 返回值 :int  成功返回修改次数  如果一次都没替换返回-2

*/
	int Modify(const char* nStr,const char* cStr,bool bmp = false);

/*******************字符串修改功能结束***********************/



/*******************字符串删除功能开始***********************/

	//删除功能如果做的话  需要重新重构类成员,要填写 start 和end 来记录字符串的起始和结束位置; 
	//我只做这个小型字符串 平时的修改的小功能
/*******************字符串删除功能结束***********************/

/*   增删改查系列查这里结束*/





	/*******************内部小功能函数系列开始***********************/
private://类内部调用函数
	/*
	* NumberCount
	* 参数一 : int --整数
	* 功能   :得到这个整数有多少个
	* 返回值 :整数的个数
*/
	int NumberCount(int nNumber);
/*
	* GetDivNum
	* 参数一 : int --整数的个数
	* 功能   :求出一个10 100  1000  10000
	* 返回值 :int
*/
	int GetDivNum(int NumberCount);

/*
	* IsStr
	* 参数一 :无
	* 功能   :检测初始化m_Str是否为空;如果NEW申请失败就会返回nullptr
	* 返回值 :bool
*/
	bool IsStr();

/*
	* IsPnCount()
	* 参数一 :无
	* 功能   :检测初始化m_p_nCount是否为空;如果NEW申请失败就会返回nullptr
	* 返回值 :bool
*/
	bool IsPnCount();


/*
	* FreeSpace()
	* 参数一 :无
	* 功能   :检测初始化m_p_nCount是否为空;如果NEW申请失败就会返回nullptr
	* 返回值 :bool
*/
	void FreeSpace();
/*
	* InitNumber()
	* 参数一 :无
	* 功能   :用户构造整数初始化和=号整数重载运算
	* 返回值 :bool
*/
	void InitNumber(int nNumber);

/*
	* StrToNumber
	* 参数一 :无
	* 功能   :把类成员m_Str字符串转化为数字返回;
	* 返回值 :int
*/
	int StrToNumber();


/*
	* FrontInsert
	* 参数一 :源地址;缓存地址
	* 参数二 :缓存大小
	* 参数三 : 目标地址;拷贝的地址
	* 参数四 :需要拷贝多少个字节
	* 功能   :前排插入
	* 返回值 :void
*/

	void FrontInsert(char* NewStr, int nSumLen, const char* str, int nLen);

/*
	* TailInsert
	* 参数一 :源地址;缓存地址
	* 参数二 :缓存大小
	* 参数三 : 目标地址;拷贝的地址
	* 参数四 :需要拷贝多少个字节
	* 功能   :尾部插入
	* 返回值 :void
*/
	void TailInsert(char* NewStr, int nSumLen, const char* str, int nLen);

/*
	* MiddleInsert
	* 参数一 :源地址;缓存地址
	* 参数二 :缓存大小
	* 参数三 : 目标地址;拷贝的地址
	* 参数四 :需要拷贝多少个字节
	* 参数五 :插入的位置
	* 功能   :中间插入一个字符串
	* 返回值 :void
*/
	void MiddleInsert(char* NewStr, int nSumLen, const char* str, int nLen,int nPosition);

/*
	* IsCmpByte(char chByte)
	* 参数一 :char  字节
	* 功能   :查字符串里面是否包含这个字节
	* 返回值 :int ---返回查找到的字符串位置索引
*/
	int IsCmpByteHead(char chByte,int nIndex);


/*
		* IsCmpByte(char chByte)
		* 参数一 :char  字节
		* 功能   :查字符里面是否出现过这个字节
		* 返回值 :int ---返回查找到的字符串位置索引
*/
	int IsCmpByteTail(char chByte, int nIndex);

/*
*    
	* IsCmpByteContinues(const char* str, int nLen,int nIndex)
	* 参数一 :const char* str 需要对比的字符串
	* 参数二 :int   str长度
	* 参数三 :int   nIndex m_Str索引
	* 参数四 :int   nIn    str的索引
	* 功能   :给定目标和源目标索引,连续对比每一个字节是否匹配
	* 返回值 :int ---返回查找到的字符串位置索引
*/
	bool IsCmpByteContinues(const char* str, int nLen, int nIndex, int nIn);
/*
*	
	* IsCmpContinuesHead(char chByte) 正向查找
	* 参数一 :const char* str   
	* 参数二 :int  nLen字符串长度  
	* 参数三 :int  nIndex m_Str索引 
	* 功能   :查字符里面是否出现过这个字节
	* 返回值 :int ---返回查找到的字符串位置索引
*/

	int IsCmpContinuesHead(const char* str, int nLen, int nIndex);


/*
	* IsCmpContinuesTail(char chByte) 反向查找
	* 参数一 :const char* str    
	* 参数二 :int  nLen字符串长度
	* 参数三 :int  nIndex m_Str索引
	* 参数四 :TailIndex  判断对比到时候退出
	* 功能   :查字符里面是否出现过这个字节
	* 返回值 :int ---返回查找到的字符串位置索引
*/

	int IsCmpContinuesTail(const char* str, int nLen, int nIndex);
/*
	*Replace(const char* cStr,int nIndex) 
	* 参数一 :const char* str  替换的字符串
	* 参数二 :nIndex this字符串的索引
	* 功能   :替换字符串
	* 返回值 :无
*/
	void Replace(const char* cStr,int nIndex);

	/*******************内部小功能函数系列结束***********************/


private://类成员以m_开头定义

	int m_nCount;//记录字符串的个数
	char* m_Str;//字符串指针
	int* m_p_nCount;//记录有多少个指针指向它;
	

};

ClassStr.cpp

cpp 复制代码
#include "ClassStr.h"


ClassStr::ClassStr()
{
	m_nCount = 0;
	m_Str = nullptr;
	m_p_nCount = new int(0);
}


ClassStr::ClassStr(const char* Str)
{
	//先求传入字符串的长度  strlen长度为字符串,不包含/0;
	m_p_nCount = new int(0);
	int nLen = strlen(Str);
	//在申请空间
	m_nCount = nLen + 1;
	m_Str = new char[m_nCount];
	if (!IsStr())
	{
		cout << "str内存初始化失败" << endl;

	}
	else
	{
		//申请的地址初始化为0
		memset(m_Str, 0, m_nCount);
		//在传入的地址进行拷贝操作
		memcpy_s(m_Str, nLen, Str, nLen);
	}


}

ClassStr::ClassStr(int nNumber)
{

	FreeSpace();
	//先求出整形有几位 NumberCount返回整形有几位数字;
	InitNumber(nNumber);
}

ClassStr::ClassStr(ClassStr& cStr)
{
	
	m_nCount = cStr.m_nCount;
	m_Str = cStr.m_Str;

	m_p_nCount = cStr.m_p_nCount;

	if (m_p_nCount != nullptr)
	{
		(*m_p_nCount)++;
	}
}

void ClassStr::operator=(ClassStr& cStr)
{
	//先清除自身
	FreeSpace();

	m_Str = cStr.m_Str;
	m_nCount = cStr.m_nCount;
	m_p_nCount = cStr.m_p_nCount;
	(*m_p_nCount)++;
	
}

void ClassStr::operator=(int nNumber)
{
	FreeSpace();
	//先求出整形有几位 NumberCount返回整形有几位数字;
	InitNumber(nNumber);

}



int ClassStr::operator+(int nNumber)
{

	//先把字符串转化为数字
	int nTmp = StrToNumber();
	nTmp = nTmp + nNumber;

	return nTmp;
}

int ClassStr::operator-(int nNumber)
{
	int nTmp = StrToNumber();
	nTmp = nTmp - nNumber;

	return nTmp;
}

char& ClassStr::operator[](int nIndex)
{
	char* ch = nullptr;
	if (nIndex < 0 || nIndex> m_nCount)
	{
		return *ch;
	}
	return m_Str[nIndex];
}

ClassStr::~ClassStr()
{
  //判断引用计数是否为0
	if (*m_p_nCount != 0)
	{
		(*m_p_nCount)--;
	}
	else //释放内存空间
	{
		delete[] m_Str;
		delete m_p_nCount;

	}
}


const char* ClassStr::GetStr()
{
	return m_Str;
}

ClassStr& ClassStr::Insert(int nPosition, const char* str)
{
	if (0 > nPosition || nPosition > m_nCount || str == NULL)
	{
		cout << "插入错误:请选择正确的位置或str指针为NULL" << endl;
		return *this;
	}
	int nLen = strlen(str);//字符串的长度
	int nSumLen = nLen + m_nCount;

	char* NewStr = new char[nSumLen];//字符串申请总长度
	if (NewStr == nullptr)
	{
		cout << "内存申请失败" << endl;
		return *this;
	}
	memset(NewStr,0,nSumLen);//申请的内存设置为0

	//可以分为插入头部 尾部  还有是中部
	if (nPosition == 0)//头部处理
	{
		FrontInsert(NewStr, nSumLen, str, nLen);

	}
	else if (nPosition == m_nCount)//尾部处理
	{
		TailInsert(NewStr, nSumLen, str, nLen);
	}
	else//中部
	{
		MiddleInsert(NewStr, nSumLen, str, nLen, nPosition);
	}

	//释放自身字符串空间
	delete[] m_Str;
	m_Str = NewStr;
	m_nCount = nSumLen;
	return *this;
}

void ClassStr::FrontInsert(const char* str)
{
	Insert(0, str);
}

void ClassStr::TailInsert(const char* str)
{
	Insert(m_nCount, str);
}

ClassStr& ClassStr::Delete(int nPosition, int nCount)
{
	//删除头部  中间 尾部
	int nLen = m_nCount - nPosition - 1;

		if (nLen = nCount)
		{
			m_Str[nPosition] = '\0';

		}


		return*this;
}

int ClassStr::HeadFind(const char* str)
{
	if (str == NULL)return -1;
	int nLen = strlen(str);
	int nIndex = 0;//字符串开始查找的位置
	int nCount = 0;
	//一 :这是判断的是一个字符对比的情况
	if (nLen == 1)
	{
		return IsCmpByteHead(str[0], nIndex);//IsCmpByteHead 一个字符 在m_Str字符串中循环判断一次
	}
	//二:长度和字符串长度一样,就匹配每一个字节是否相等
	if (nLen == (m_nCount -1))
	{
		
		if (IsCmpByteContinues(str, nLen, 0,0))//IsCmpByteHead 一个字符 在m_Str字符串中循环判断一次
		{
			return 0;
		}

	}

	//三:这判断是多个字符的对比情况
	return IsCmpContinuesHead(str, nLen, nIndex);
	
}

int ClassStr::TailFind(const char* str)
{
	if (str == NULL)return false;
	int nLen = strlen(str);
	int nIndex = m_nCount - nLen -1;//字符串开始查找的位置
	int nCount = 0;

	if (nLen == 1)
	{
		return IsCmpByteTail(str[0], nIndex);
	}

	//二:长度和字符串长度一样,就匹配每一个字节是否相等
	if (nLen == (m_nCount - 1))
	{
		if (IsCmpByteContinues(str, nLen, 0,0))//IsCmpByteHead 一个字符 在m_Str字符串中循环判断一次
		{
			return 0;
		}

	}

	return IsCmpContinuesTail(str, nLen, nIndex);

}

int ClassStr::HeadFindCount(const char* str)
{
	if (str == nullptr)return -1;
	int nCount = 0;
	int nLen = strlen(str);
	int nIndex = 0;
	do{
		nIndex = IsCmpContinuesHead(str, nLen, nIndex);

		if (nIndex == -1)
		{
			return nCount;

		}
		nCount++;
		//找到了索引值就要增加nLen之后的位置开始查找
		nIndex = nIndex + nLen;
	} while (true);

	return nCount;
}

int ClassStr::Modify(const char* nStr, const char* cStr, bool bmp)
{
	//记录替换的次数
	int nCount = 0;
	int nLen = strlen(cStr);
	int nIndex = 0;
	do
	{
		nIndex = IsCmpContinuesHead(nStr, nLen, nIndex);

		if (nIndex == -1)
		{
			return nCount;

		}
		nCount++;
		// 在替换  --需要替换的字符串 和this字符串索引
		Replace(cStr,nIndex);

		//找到了索引值就要增加nLen之后的位置开始查找
		nIndex = nIndex + nLen;

	} while (bmp);


	return nCount;
}

int ClassStr::NumberCount(int nNumber)
{
	//求数字有多少位
	int nLen = 0;
	while (nNumber != 0)
	{
		nNumber = nNumber / 10;
		nLen++;

	}
	return nLen;
}

int ClassStr::GetDivNum(int nLen)
{
	int DivNum = 1;

	while ( nLen > 1 )
	{
		DivNum = DivNum * 10;
		nLen--;
	}

	return DivNum;
}

bool ClassStr::IsStr()
{
	if (m_Str == nullptr)
	{
		return false;
	}
	return true;
}

bool ClassStr::IsPnCount()
{
	if (m_p_nCount == nullptr)
	{
		return false;
	}
	return true;
}

void ClassStr::InitNumber(int nNumber)
{
	m_p_nCount = new int(0);
	int nLen = NumberCount(nNumber);

	m_nCount = nLen + 1;
	m_Str = new char[m_nCount];
	if (!IsStr())
	{
		cout << "内存初始化失败" << endl;

	}
	else
	{
		memset(m_Str, 0, m_nCount);

		int nDivNum = GetDivNum(nLen);
		int nIndex = 0;
		//在把每一位数字转换为字符串 数字的1 和字符串的1    先除,在取模
		for (int i = 0; i < m_nCount - 1; i++)
		{
			m_Str[nIndex] = (char)(nNumber / (1 * nDivNum)) + '0';
			nIndex++;

			nNumber = nNumber % (1 * nDivNum);

			nDivNum = nDivNum / 10;
		}

	}

}

int ClassStr::StrToNumber()
{
	int nTmp = 0;
	int nImu = GetDivNum(m_nCount - 1);
	for (int i = 0; i < m_nCount - 1; i++)
	{
		char chCtr = m_Str[i];
		int nNum = (int)chCtr - '0';
		nTmp += nNum * nImu;
		nImu = nImu / 10;   //nImu = 10
	}
	return nTmp;
}

void ClassStr::FrontInsert(char* NewStr, int nSumLen, const char* str,int nLen)
{
	//种方式也可以
	//memcpy_s(NewStr, nSumLen, str, nLen);
	//memcpy_s(NewStr + nLen, nSumLen, m_Str, m_nCount - 1);

	//另种方式也可以
	MiddleInsert(NewStr, nSumLen, str, nLen,0);
}

void ClassStr::TailInsert(char* NewStr, int nSumLen, const char* str, int nLen)
{
	//memcpy_s(NewStr, nSumLen, m_Str, m_nCount - 1);
	//memcpy_s(NewStr + m_nCount - 1, nSumLen, str, nLen);

	MiddleInsert(NewStr, nSumLen, str, nLen, m_nCount -1);
}

void ClassStr::MiddleInsert(char* NewStr, int nSumLen, const char* str, int nLen, int nPosition)
{
	memcpy_s(NewStr, nSumLen, m_Str, nPosition);//5wo ai6
	memcpy_s(NewStr + nPosition, nSumLen, str, nLen);
	memcpy_s(NewStr + nLen + nPosition, nSumLen, m_Str + nPosition, m_nCount - nPosition -1);

}


int ClassStr::IsCmpByteHead(const char chByte,int nIndex)
{
	for (int i = nIndex; i < m_nCount -1; i++)
	{
		if (m_Str[i] == chByte)
		{
			return i;
		}
	}

	return -1;
}

int ClassStr::IsCmpByteTail(const char chByte, int nIndex)
{
	for (int i = nIndex; i >= 0; i--)
	{
		if (m_Str[i] == chByte)
		{
			return i;
		}
	}

	return -1;
}

bool ClassStr::IsCmpByteContinues(const char* str, int nLen, int nIndex,int nIn)
{
	for (int i = nIn; i < nLen; i++)
	{
		if (m_Str[nIndex] != str[i])
		{
			return false;
		}
		nIndex++;
	}
	return true;
}


int ClassStr::IsCmpContinuesHead(const char* str,int nLen,int nIndex)
{

	int nLenCmp = 0;
	int nIn = 1;
	//正向查找
	do {
		//先查找第一个字节 ---在字符串中有没有,有返回索引
		
	   nIndex = IsCmpByteHead(str[0], nIndex);

	   //如果尾部查找到str[0],剩余的字节不够对比直接返回-1
	   //str "ghy"  m_str "erergh" 找到了g,但是m_str后面只有2个字符;肯定返回-1
	    nLenCmp = m_nCount - 1 - nIndex;

		if (nIndex == -1 || nLenCmp < nLen)
		{
			return -1;
		}
		//如果第一个字节存在,连续对比m_str和str的每一个字节

		if (IsCmpByteContinues(str, nLen, nIndex + nIn, nIn))
		{
			return nIndex;
		}

		nIndex++ ;//正向查找
	
		


	} while (true);

	return  -1;

}

int ClassStr::IsCmpContinuesTail(const char* str, int nLen, int nIndex)
{
	int nLenCmp = 0;
	int nIn = 1;

	do {
		//先查找第一个字节 ---在字符串中有没有,有返回索引
		
		nIndex = IsCmpByteTail(str[0], nIndex);//反向查找

		nLenCmp = m_nCount - 1 - nIndex;
		
		if (nIndex == -1 || nLenCmp < nLen)
		{
			return -1;
		}
		//如果第一个字节存在,连续对比m_str和str的每一个字节

		if (IsCmpByteContinues(str, nLen, nIndex + nIn, nIn))
		{
			return nIndex;
		}

		nIndex--;//反向查找
	

	} while (true);

	return  -1;
}

void ClassStr::Replace(const char* cStr, int nIndex)
{
	int nLen = strlen(cStr);
	for (int i = 0; i < nLen; i++)
	{
		m_Str[nIndex] = cStr[i];
		nIndex++;
	}
}

void ClassStr::FreeSpace()
{
	if (!IsStr())
	{
		return;
	}
	delete[] m_Str;
	delete m_p_nCount;
}
相关推荐
JSU_曾是此间年少11 分钟前
数据结构——线性表与链表
数据结构·c++·算法
此生只爱蛋1 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
何曾参静谧1 小时前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
lulu_gh_yu2 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
ULTRA??3 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者3 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者3 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
~yY…s<#>4 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
可均可可5 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
白子寰5 小时前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++