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;//记录有多少个指针指向它;
};
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;
}