@TOC
目录
string类可以对字符串进行详细的操作,所以要实现对string的模拟,下面是类成员的定义:
private:
size_t _capacity;
size_t _size;
char* _str;
// const static 语法特殊处理
// 直接可以当成定义初始化
const static size_t npos = -1;
通过之前类和对象的学习,我们知道了类有·默认成员函数
默认成员函数
构造函数
//构造函数(1)
string()
{
_str = nullptr;
_capacity = 0;
_size = 0;
}
//构造函数(2)
string()
:_str(new char[1])
, _size(0)
, _capacity(0)
{
_str[0] = '\0';
}
//构造函数(3)
string(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
这里面只有 构造函数(1)用不了,因为如果我们直接给一个空的字符串再运行c_str函数就会产生错误。
如下代码:
#include <iostream>
using namespace std;
namespace sslx
{
class string
{
public:
string()
{
_str = nullptr;
_capacity = 0;
_size = 0;
}
const char* c_str() const
{
return _str;
}
private:
size_t _capacity;
size_t _size;
char* _str;
// const static 语法特殊处理
// 直接可以当成定义初始化
const static size_t npos = -1;
};
void test_string1()
{
string s1;
cout << s1.c_str() << endl;
}
}
int main()
{
sslx::test_string1();
return 0;
}
c_str会遍历字符串直到遇到'\0',如果这样初始化的话,就会造成空指针错误,所以不能这样初始化
相比于构造函数(2),构造函数(3)的作用范围更广, 构造函数(3)可以初始化任意内容的字符串, 而构造函数(2)只能初始化空字符串
析构函数
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
拷贝构造函数
//传统写法
//s2(s1)
string(const string& s)
:_str(new char[s._capacity + 1])
, _size(s._size)
, _capacity(s._capacity)
{
strcpy(_str, s._str);
}
//现代写法
void swap(string& tmp)
{
::swap(_str, tmp._str);
::swap(_size, tmp._size);
::swap(_capacity, tmp._capacity);
}
string(const string& s)
:_str(nullptr)
, _size(0)
, _capacity(0)
{
string tmp(s._str);
swap(tmp);
}
现代写法就是用现有函数完成目标函数,拷贝构造函数的现代写法就是运用构造函数,创建一个和s一摸一样的对象,再把这个函数直接和我们的拷贝对象进行交换,就可以完成拷贝构造,临时创建的对象会在函数结束时,自动销毁。
操作符重载函数
赋值操作符重载函数
//s1 = s3
//s1 = s1
string& operator=(const string& s)
{
if (this != &s)
{
char* tmp = new char[s._capacity + 1];
strcpy(tmp, s._str);
delete[] _str;
_str = tmp;
_str = tmp;
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
//s顶替tmp做打工人
string& operator=(string s)
{
swap(s);
return *this;
}
比较操作符重载函数
bool operator>(const string& s) const
{
size_t size = (s.size() > this->size() ? this->size() : s.size());
for (size_t i = 0; i < size; i++)
{
if (_str[i] > s[i])
{
return true;
}
else if(_str[i] < s[i])
{
return false;
}
}
if (this->size() > size)
{
return true;
}
return false;
}
bool operator==(const string& s) const
{
if (s.size() == this->size())
{
for (size_t i = 0; i < s.size(); i++)
{
if (s[i] != _str[i])
{
return false;
}
}
return true;
}
return false;
}
bool operator>=(const string& s) const
{
return (*this > s) || (*this == s);
}
bool operator<=(const string& s) const
{
return (*this < s) || (*this == s);
}
bool operator<(const string& s) const
{
return (s > *this);
}
bool operator!=(const string& s) const
{
return !(*this == s);
}
迭代器
STL中,迭代器是非常重要的, 这边简单地实现一下。
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator begin() const
{
return _str;
}
const_iterator end() const
{
return _str + _size;
}
尾插一个字符
void push_back(char ch)
{
//满了就阔容
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
insert(_size, ch);
}
追加字符串
void append(const char* str)
{
size_t len = strlen(str);
//满了就阔容
if (_size + len > _capacity)
{
reserve(_size + len);
}
strcpy(_str + _size, str);
strcat(_str, str);
_size += len;
}
//追加字符
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
//追加字符串
string& operator+=(const char* str)
{
append(str);
return *this;
}
在任意位置添加
//添加字符
string& insert(size_t pos, char ch)
{
assert(pos <= _size);
//满了就扩容
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
挪动数据
//int end = _size;
//while (end >= (int)pos)
//{
// _str[end + 1] = _str[end];
// --end;
//}
size_t end = _size + 1;
while (end > pos)
{
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
++_size;
return *this;
}
//添加字符串
string& 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 + len;
while (end >= pos + len)
{
_str[end] = _str[end - len];
end--;
}
strncpy(_str + pos, str, len);
_size += len;
return *this;
}
删除部分字符串
void erase(size_t pos, size_t len = npos)
{
assert(pos < _size);
if (len == npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);
_size -= len;
}
}
查找函数
size_t find(char ch, size_t pos = 0) const
{
assert(pos <= _size);
for (size_t i = pos; i < _size; i++)
{
if (_str[i] == ch)
{
return i;
}
}
return -1;
}