string如其名,就是一个字符串,string的成员对象有char* _str(指向存储的字符串),size_t _size(记录该字符串所含的字符个数),size_t _capacity(该指针指向空间的大小容量)。
1 实现构造函数
namespace GuYu
{
class string
{
public:
//构造函数
//如果直接给_str赋值,*str指向的字符串放在代码段,只能读,不能写,所以需要在堆上给_str开空间
string(const char*str="") // ""代表\0 表示空字符 // (1) (4)一起完成
{
_capacity = strlen(str);
_str = new char[_capacity + 1];
memcpy(_str,str,sizeof(char)*(_capacity+1)); // void *memcpy(void *str1, const void *str2, size_t n) (n是拷贝的字节数) // 我们算的_capacity是没有记录'\0'的位置,所以要加1,多拷贝一个'\0'字符
_size = _capacity;
}
string(const string& str)
{
_capacity = strlen(str._str);
_str = new char[_capacity + 1];
memcpy(_str,str._str,sizeof(char)*(_capacity+1));
_size = _capacity;
}
string(const string& str, size_t pos, size_t n) // 从pos下标开始拷贝n个数据给_str(this->_str)
{
_capacity = n;
_str = new char[_capacity + 1];
memcpy(_str,str._str+sizeof(char)*pos,sizeof(char)*_capacity);
_str[n] = '\0';
_size = _capacity;
}
string(const char* str,size_t n)
{
_capacity = n;
_str = new char[_capacity + 1];
memcpy(_str,str,sizeof(char)*_capacity);
_str[n] = '\0';
_size = _capacity;
}
void print()
{
int i = 0;
while(this->_str[i]!='\0')
{
cout << this->_str[i++] << " ";
}
cout << endl;
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
}
2. 实现增容函数reserve
void reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n+1];
memcpy(tmp, _str, sizeof(char) * _size+1); //将'\0'拷贝了过来
delete[]_str;
_str = tmp;
_capacity = n;
}
if (n < _capacity)
{
char* tmp = new char[n+1];
memcpy(tmp, _str, sizeof(char) * n );
tmp[n] = '\0';
delete[]_str;
_str = tmp;
}
}
注意:我们每次开空间时都要多开辟一个空间给'\0'。
3. push_back函数的实现
void push_back(char a)
{
if (_size == _capacity)
{
this->reserve(_capacity * 2);
}
_str[_size++] = a;
_str[_size] = '\0';
}
4. operator+=函数的实现
原理就是扩容加push_back。
string& operator+=(const string& str)
{
int len = str._size;
// 将空间增加到两个字符串长度之和
if (_size + len > _capacity)
{
reserve(_size + len);
}
int i = 0;
while (str._str[i] != '\0')
{
this->push_back(str._str[i++]);
}
_str[_size] = '\0';
return *this;
}
5. insert和erase用到的就是将元素往后推和往前推的思路
string& insert(size_t pos,const string& str,size_t subpos,size_t sublen)
{
assert(subpos + sublen < str._size);
assert(pos >= 0 && pos <= _size);
if (_size + sublen > _capacity)
{
reserve(_size + sublen);
}
//将subpos和其之后的元素向后移sublen长度
int i = 0;
while (_size - i >= pos)
{
_str[_size-i+ sublen] = _str[_size-i]; // 从'\0'开始后移直到pos位置结束
i++;
}
for (int j = 0; j < sublen; j++)
{
_str[pos + j] = str._str[subpos + j];
}
_size += sublen;
return *this;
}
6. operator=函数
string& operator=(string str) // 完成一个拷贝
{
swap(_str, str._str); // 完成地址的交换
int len = str.size();
_size = len;
_capacity = len;
// delete[] str._str; 函数结束(生命周期就是在该函数中)时str的析构函数会自动释放内存,如果手动释放,会发生双重释放的错误
return *this;
}