简单模拟一下C++中的string类
string类模拟
模拟string,存储字符串。
结构定义
namespace sun
{
class string
{
public:
const static size_t npos;
typedef char* iterator;
typedef const char* const_iterator;
//构造函数
//拷贝构造
//析构
//赋值=重载
/*****************************************************************************************/
//迭代器
//反向迭代器
/*****************************************************************************************/
//有效个数
//设置有效个数
//容量
//扩容
//清空
//判空
/*****************************************************************************************/
//[]重载
//+=重载
//尾插(字符)
//尾插(字符串)
//插入
//删除
//交换
/*****************************************************************************************/
//提取字符串
//查找(字符)
//查找(字符串)
//查找子串
/*****************************************************************************************/
//比较运算符重载
private:
char* _str;
size_t _size;
size_t _capacity;
};
const size_t string::npos = -1;
//流插入
//流提取
}
成员变量
char* _str;//存储字符串
size_t _size;//有效个数
size_t _capacity;//空间容量
迭代器类型
typedef char* iterator;
typedef const char* const_iterator;
成员函数
//构造函数
string(const char* str = "")
:_size(strlen(str))//计算有效个数
, _capacity(_size)//先将容量和个数保持一致
{
_str = new char[_capacity + 1];//开辟空间,+1多开一个方便存放'\0'
strcpy(_str, str);//将内容拷贝过去
}
//拷贝构造
string(const string& str)
{
//注意:深浅拷贝的问题
//深拷贝:
_str = new char[str._capacity + 1];//开辟一样大的空间
strcpy(_str, str._str);//拷贝过去
_size = str._size;
_capacity = str._capacity;
}
//析构
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
//赋值=重载
string& operator=(const string& str)
{
if (this != &str)
{
//借助临时变量
char* tmp = new char[str._capacity + 1];//开辟一样大的空间
strcpy(tmp, str._str);//拷贝过去
delete[] _str;//释放旧空间
_str = tmp;//指向新空间
_size = str._size;
_capacity = str._capacity;
}
return *this;
}
//迭代器
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator begin() const
{
return _str;
}
const_iterator end()const
{
return _str + _size;
}
//有效个数
size_t size() const
{
return _size;//返回有效个数
}
//设置有效个数
//设置有效个数,并在尾部位置插入字符
void resize(size_t n,char c = '\0')
{
//判断:n与_size的大小关系
if (n <= _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
//判断:是否扩容
if (n > _capacity)
{
reserve(n);
}
while (_size < n)
{
_str[_size] = c;
_size++;
}
_str[_size] = '\0';
}
}
//容量
size_t capacity() const
{
return _capacity;
}
//扩容
void reserve(size_t n)
{
//只有大于容量才扩容
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
//清空
//清空
void clear()
{
_str[0] = '\0';//清字符串
_size = 0;//置零
}
//判空
bool empty() const
{
return _size == 0;
}
//[]重载
//[]重载
char& operator[](size_t pos)
{
assert(pos < _size);//断言:有效下标
return _str[pos];
}
//[]重载(const版本,只读
const char& operator[](size_t pos) const
{
assert(pos < _size);//断言:有效下标
return _str[pos];
}
//+=重载
//+=一个字符
string& operator+= (char c)
{
//判断扩容
if (_size == _capacity)
{
//注意:_capacity == 0 的情况
/*size_t new_capacity = _capacity == 0 ? 4 : _capacity * 2;
reserve(new_capacity);*/
//简化:
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
_str[_size++] = c;
_str[_size] = '\0';
return *this;
}
//+=一个字符串
string& operator+= (const string& str)
{
//计算str长度
size_t len = strlen(str._str);
//判断扩容
if (_size+len >= _capacity)
{
reserve(_size + len);
}
strcpy(_str + _size, str._str);//拷贝到结尾位置
_size += len;
return *this;
}
//尾插(字符)
void push_back(char c)
{
//this->operator+=(c);
(*this) += c;
}
//尾插(字符串)
void append(const char* s)
{
(*this) += s;
}
//插入
//在pos位置插入一个字符
void insert(size_t pos,const char c)
{
assert(pos <= _size);
//判断:扩容
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
size_t end = _size+1;//记录'\0'的下一个位置
while (end > pos)
{
_str[end] = _str[end - 1];//从\0的位置依次往后挪动1个长度
end--;
}
_str[pos] = c;//在pos位置插入字符
_size++;
}
//在pos位置插入一个字符串
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
//判断:扩容
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end = _size + 1;
while (end > pos)
{
_str[end-1+len] = _str[end- 1];//从\0的位置依次往后挪动len个长度
end--;
}
strncpy(_str + pos, str, len);//在pos位置插入字符串
_size += len;
}
//删除
void erase(size_t pos = 0, size_t len = npos)//从pos位置开始删除,默认删到低
{
assert(pos < _size);
//判断:是否删到底
if (len == npos || len+pos >=npos)
{
_str[pos] = '\0';
_size = pos;
}
else
{
//往前挪动,覆盖掉删除的字符
size_t begin = pos + len;
while (begin<=_size)
{
_str[begin - len] = _str[begin];
begin++;
}
_size -= len;
}
}
//交换
void swap(string& str)
{
//利用库中的交换函数
std::swap(_str, str._str);
std::swap(_size, str._size);
std::swap(_capacity, str._capacity);
}
//提取字符串
const char* c_str() const
{
return _str;
}
//查找
//查找(字符)
size_t find(const char& c , size_t pos = 0) const
{
assert(pos < _size);
for (size_t i = pos ; i < _size; i++)
{
if (_str[i] == c)
return i;
}
return npos;
}
//查找(字符串)
size_t find(const char* str, size_t pos = 0) const
{
assert(pos < _size);
const char* p = strstr(_str+pos, str);
//找到
if (p != nullptr)
return p - _str;
//找不到
return npos;
}
//提取子串
string substr(size_t pos = 0, size_t len = npos) const//默认从头开始直到结尾
{
assert(pos < _size);
//判断:是否提取到底
if (len == npos || pos + len >= _size)
{
return _str + pos;//隐式类型转换
}
string s;//存储子串
s.reserve(len);
for (size_t i = pos; i < pos + len; i++)
{
s += _str[i];
}
return s;
}
//比较运算符重载
bool operator<(const string& s) const
{
return strcmp(_str, s._str) < 0;
}
bool operator==(const string& s) const
{
return strcmp(_str, s._str) == 0;
}
bool operator<=(const string& s) const
{
return _str < s._str || _str == s._str;
}
bool operator>(const string& s) const
{
return !(_str <= s._str);
}
bool operator>=(const string& s) const
{
return !(_str < s._str);
}
bool operator!=(const string& s) const
{
return !(_str == s._str);
}
//流插入
ostream& operator<<(ostream& out , const string& str)
{
//直接范围for
for (auto c : str)
{
out << c;
}
return out;
}
//流提取
istream& operator>>(istream& in, string& str)
{
//清空
str.clear();
char c;
c = in.get();
while (c != ' ' || c != '\n')//直到遇到空格或换行,停止
{
str += c;
c = in.get();
}
return in;
}