string底层实现,参考了网上的一些代码,注释都写在代码里了,比较清楚。供大家参考交流
#pragma once
#include <string.h>
class MyString
{
public:
typedef char* iterator;//定义一下迭代器类型,显得正式一点
typedef const char* const_iterator;
private:
char* _str;
size_t _size;//大小
size_t _capacity;//容量
public:
static char* MyStrcpy(char* dst, const char* src);
MyString(const char* str = "");
MyString(const MyString& str);
~MyString();
iterator begin();
const_iterator cbegin() const;
iterator end();
const_iterator cend() const;
size_t size() const;
size_t capacity() const;
char* c_str() const;
MyString& insert(size_t pos, char c);
MyString& insert(size_t pos, const char* str);
void push_back(const char c);
MyString& append(const char* str);
MyString& erase(size_t pos, size_t len=-1);
void reserve(size_t n = 0);
void resize(size_t n, char c = '\0');
size_t find(char c, size_t pos = 0) const;
size_t find(const char* str, size_t pos = 0) const;
MyString& operator+=(const char c);
MyString& operator+=(const char* str);
char& operator[](size_t pos);
};
#include "MyString.h"
//字符串复制函数,静态方法
char* MyString::MyStrcpy(char* dst, const char* src)
{
if (dst == nullptr || src == nullptr || dst == src)
return dst;
while (*src != '\0')
{
*dst = *src;
dst++;
src++;
}
*dst = '\0';
return head;
}
//构造函数
MyString::MyString(const char* str) :_size(strlen(str))
{
_capacity = _size;
_str = new char[_capacity + 1];//多一个是用来存'\0'的,之前的strlen()不会把'\0'算进去
MyStrcpy(_str, str);
}
//拷贝构造函数
MyString::MyString(const MyString& str)
{
char* temp = new char[str._capacity + 1];
MyStrcpy(temp, str._str);
_str = temp;
_size = str._size;
_capacity = str._capacity;
}
//析构函数
MyString::~MyString()
{
if (_str)
{
delete[] _str;
_size =0;
_capacity = 0;
}
}
MyString::iterator MyString::begin()
{
return _str;
}
MyString::const_iterator MyString::cbegin() const
{
return _str;
}
MyString::iterator MyString::end()
{
return _str + _size;
}
MyString::const_iterator MyString::cend() const
{
return _str + _size;
}
size_t MyString::size() const
{
return _size;
}
size_t MyString::capacity() const
{
return _capacity;
}
char* MyString::c_str() const
{
return _str;
}
//扩容函数
void MyString::reserve(size_t n)
{
//n大于现有容量的时候,会申请扩容,然后把之前的内容复制过去。否则什么都不做
if (n > _capacity)
{
char* temp = new char[n+1];
MyStrcpy(temp, _str);
delete[] _str;
_str = temp;
_capacity = n;
}
}
//插入字符
MyString& MyString::insert(size_t pos, char c)
{
//无法插入,直接返回
if (pos > _size)
return *this;
//如果此时存的字符串已经装满了,需要先两倍扩容一下
if (_size == _capacity)
{
size_t newcap = _capacity == 0 ? 4 : 2 * _capacity;
reserve(newcap);
}
//找到要插入的地方插入字符
//因为_capacity 若不够的话,此时已经扩容了,所以_str[it]是不会越界的
size_t it = _size + 1;
while (it != pos)
{
_str[it] = _str[it - 1];
it--;
}
_str[pos] = c;
_size++;
return *this;
}
//插入字符串
MyString& MyString::insert(size_t pos, const char* str)
{
//无法插入,直接返回
if (pos > _size)
return *this;
//验证是否要扩容
size_t len = strlen(str);
reserve(_size + len);
//找到并且插入字符串
size_t it = _size + len;
while (it - pos > len - 1)
{
_str[it] = _str[it - len];
it--;
}
for (size_t i = 0; i < len; i++)
{
_str[pos] = str[i];
pos++;
}
_size = _size + len;
return *this;
}
void MyString::push_back(const char c)
{
insert(_size, c);
}
MyString& MyString::append(const char* str)
{
insert(_size, str);
return *this;
}
MyString& MyString::erase(size_t pos, size_t len)
{
//-1是默认值,代表全部删除
if (len == -1 || len >= _size - pos)
{
_str[pos] = '\0';
_size = pos;
}
else
{
for (size_t i = pos + len; i <= _size; i++)
{
_str[i - len] = _str[i];
}
_size = _size - len;
}
return *this;
}
void MyString::resize(size_t n, char c)
{
reserve(n);
if (n >= _size)
{
memset(_str + _size, c, n - _size);
_size = n;
_str[_size] = '\0';
}
else
{
_str[n] = '\0';
_size = n;
}
}
size_t MyString::find(char c, size_t pos) const
{
while (pos < _size)
{
if (_str[pos] == c)
return pos;
pos++;
}
return -1;
}
size_t MyString::find(const char* str, size_t pos) const
{
const char* p = strstr(_str + pos, str);
if (p == nullptr)
return -1;
return p - _str;
}
MyString& MyString::operator+=(const char c)
{
insert(_size, c);
return *this;
}
MyString& MyString::operator+=(const char* str)
{
insert(_size, str);
return *this;
}
char& MyString::operator[](size_t pos)
{
return _str[pos];
}