string类自我实现
函数的实现方式以及必要解释都在下述代码中注释
class String
{
public:
String()//无参构造
//初始化
:_str(new char[16]),//对_str开空间
_size(0),//初始有效字符为0个
_capacity(0)//树池容量为0
{
_str[_size] = '\0';//给初始有效字符处置'\0
}
String(const char* str)//带参构造
{
_size = strlen(str);//算出str的长度,即为_str的有效字符
_str = new char[_size + 1];//为_str开新空间
strcpy(_str,str);//拷贝
_capacity = _size;//当前容量置为当前有效字符
}
~String()//析构函数
{
if(_str)//如果_str不为空
{
delete[] _str;//释放_str空间
_size = _capacity = 0;//当前游侠字符以及容量为0
_str = nullptr;//_str置为nullptr
}
}
//带参构造,与上述带参构造一样
String(const String& str)
:_str(new char[str._capacity + 1]),
_size(str._size),
_capacity(str._capacity)
{
strcpy(_str,str._str);
}
//=运算符重载
String& operator=(const String& str)
{
if(this != &str)//排除自己等号赋值
{
char* tmp = new char[str._capacity + 1];//临时对象tmp开空间
strcpy(tmp,str._str);//拷贝复制
delete[] _str;//释放当前_str
_str = tmp;//将临时对象赋给_str
_size = str._size;//_str的有效字符
_capacity = str._capacity;//_str的容量
}
return *this;//返回当前对象哎ing,完成=赋值
}
//尾插字符
void pushback(const char& ch)
{
//判断如果当前有效字符等于容量则需要开空间
if(_size == _capacity)
{
//新的容量大小
size_t newC = _capacity == 0?15:2*_capacity;//若为零则默认初始为15否则为容量的2倍
reserve(newC);//扩容函数
}
_str[_size] = ch;//有效位置的'\0'放置字符ch
++_size;//++有效字符
_str[_size] = '\0';//放置'\0'
}
//扩容函数
reserve(size_t n)//n为新的容量大小
{
//新的容量如果大于旧容量
if(n > _capacity)
{
char* tmp = new char[n + 1];//开你的空间
strcpy(tmp,_str);//复制
delete[] _str;//删除原有_str空间
_str = tmp;//将临时对象tmp赋给_str
_capacity = n;//新的容量为n
}
}
typedef char* iterator;//可读可写迭代器接口
typedef const char* const_iterator;//只读迭代器接口
//迭代器接口实际上是通过指针来实现
iterator begin()//字符串起始位置
{
return _str;//返回_str开始的指针
}
iterator end()//字符串有效字符结束位置
{
return _str + _size;//返回_str+_size的位置
}
//下面两个为只读迭代器需要加 const
//实现方法与上述类似
const_iterator begin() const
{
return _str;
}
const_iterator end() const
{
return _str + _size;
}
//[]重载函数
char& operator[] (size_t pos)//可读可写接口
[
if(pos<_size)
return _str[pos];
}
const char& operator[] (size_t pos) const//只读接口不能通过[]修改内容
{
if(pos<_size)
return _str[pos];
}
//当前字符串的有效字符个数
size_t size() const
{
return _size;
}
//将str拼接在_str后
void Append(const char* str)
{
int len = strlen(str);//计算str的长度
//判断是否需要扩容
if(_size + len >_capacity)
{//扩大容量
reserve(_size + len);
}
//再_str后拷贝str
strcpy(_str + _size,str);
_size+=len;//新的_str的长度
}
//+=运算符重载
String& operator+=(const char& ch)
{
//调用pushback函数接口
pushback(ch);
return *this;//返回+=后得字符串
}
//拼接字符串
String& operator+=(const char* str)
{
//调用Append函数完成字符串+=操作
Append(str);
return *this;
}
//插入函数
void insert(size_t pos,const char& ch)//pos为插入的位置,ch为要插入的字符
{
//判断当前插入位置是否大于有效字符位置
if(pos>_size)
return ;//大于则不做任何操作
//判断是否需要扩容
if(_size == _capacity)
{
//设定新的容量
size_t newC = _capacity ==0?15:2 * _capacity;
}
//end为_size的后一个位置
size_t end = _size + 1;
//逐步向后挪动字符
while(end>=pos)
{
//挪动字符
_str[end] = _str[end - 1];
--end;
}
//while循环结束后找到插入的位置
_str[pos] = ch;//插入字符ch
++_size;//有效字符个数+1
}
//插入字符串
void insert(size_t pos,const char* str)
{
int len = strlen(str);//计算要插入的字符串的长度
//判断是否需要将_str扩容
if(_size + len >_capacity)
{
//扩容到_size+len的长度
reserve(_size + len);
}
//找到需要向后移动的最后一个位置
size_t end = _size + len;
//逐步向后复制字符,留出需要放入str的长度len
while(end > pos + len - 1)
{
_str[end] = _str[end - len];
--end;
}
//在_str中插入str字符串
for(int i = 0;i<len;++i)
{
_str[i + pos] = str[i];
}
_size += len;//更新当前的有效字符个数
}
//扩充或缩短有效字符
void resize(size_t n,const char& ch = '\0')
{
if(n>_capacity)//n于容量则扩容
{
reserve(n);
}
if(n>_size)//n大于有效字符_size
{
//从_stzr+_size处开始复制字符ch,复制n-_size个
memset(_str + _size,ch,n - _size);
}
//更新新的有效字符个数
_size = n;
//在最后位置置'\0'
_str[_size] = '\0';
}
//尾删
void popback()
{
if(_size > 0)
{
//先更新有效字符个数,再在末尾置'\0'
_str[--_size] = '\0';
}
}
void erase(size_t pos,size_t len)//删除子串pos为删除的位置,len为删除的长度
{
if(pos<_size)//先判断是否在有效字符范围内
{
if(pos + len >= _size)//如果位置大于等于_size
{
//则更新新的有效字符个数
_size = pos;
//末尾置'\0'
_str[_size] = '\0';
}
else//否则
{
//找到需要删除的字符串的最后一个字符的下一个字符,开始向前复制
for(int i = pos + len;i<=_size;++i)
{
//从需要被删除的位置开始复制pos+len的位置开始的字符串
_str[pos++] = _str[i];
}
//更新新的有效字符个数
_size = _size - len;
}
}
}
//寻找函数
size_t find(const char* str)
{
//运用strstr函数分成两个字串
char* ptr = strstr(_str,str);
if(ptr)//如果ptr不为空
return ptr - _str;//指针相减返回找到的起始位置
else
//否则返回npos
return npos;
}
//返回C风格的字符串
const char* c_str() const
{
return _str;
}
private:
char* _str;//字符串兑现
size_t _size;//有效字符个数
size_t _capacity;//_str容量
static const size_t npos;//nops
};
//类外定义
const size_t String::npos = -1;
//+运算符重载
String operator+(const String& s,const String& str)//两个String类+
{
String ret(s);//拷贝构造ret
ret+=str.c_str();调用+=运算符重载拼接
return ret;//返回ret
}
String operator+(const String& s,const char* str)//String类和char* +
{
String ret(s);
ret+=str;
return ret;
}
String operator+(const String& s,const char& ch)//String类+字符ch
{
String ret(s);
ret+=ch;
return ret;
}
ostream& operator<<(ostream& cout,const String& str)//输出《《重载
{
for(const auto& ch:str)
cout<<ch;
return cout;
}