文章目录
先赞后看,养成习惯!!!^ _ ^<3 ❤️ ❤️ ❤️
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦!
所属专栏:C++初阶
一、模拟实现构造函数,析构函数,拷贝构造
首先我们需要一个类域,防止与全局域混淆
namespace SF
{
}
然后开始实现我们需要的函数
class string
{
string(const char* str="")
:_size(strlen(str))//初始化列表
{
_capacity = _capacity==0 ? 3 : 2 *_capacity;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
string(const string& str)//深拷贝
:_size(str._size),//列表初始化
_capacity(str._capacity)
{
_str = new char[str._capacity + 1];
strcpy(_str, str._str);
}
}
这里讲解一下什么叫深拷贝什么叫浅拷贝
深拷贝就是重新开辟一块空间,然后把另外一块空间的值拷贝过来
浅拷贝并没有重新开辟一块空间,指针还是指向这块空间(严重会发生两次析构)
二、模拟实现迭代器
这里我们需要typedef一下,每个迭代器所指向的空间是有区别的
typedef char* iterator;
typedef const char* const_iterator;
class string
{
iterator begin()
{
return _str;
}
const_iterator begin() const
{
return _str;
}
iterator end()
{
return _str+_size;
}
const_iterator end() const
{
return _str + _size;
}
二、模拟实现运算符重载
strcmp是按ASCll进行比较的
第一个字符开始比较,相等就继续往后走,知道不相等,如果前面一个字符的ASCll值大于后面的,那么返回一个正数,小于就是返回-1
bool operator>(const string& s)const
{
return strcmp(_str,s._str);
}
bool operator==(const string& s) const
{
return strcmp(_str, s._str)==0;
}
bool operator<(const string& s)const
{
return !(*this == s || *this > s);
}
bool operator<=(const string& s)const
{
return !(*this > s);
}
bool operator>=(const string& s)const
{
return !(*this < s);
}
string& operator+=(const string& str)
{
append(str._str);
return *this;
}
三、模拟实现寻找字符或者字符串
从str1中寻找是否存在str2的字串,存在就返回该子串在母串的首字符的下标
size_t find(char c, size_t pos = 0) const//找字符
{
assert(pos >= _size);
for (int i = pos;i<_size;i++)
{
if (_str[i] == c)
return i;
}
return npos;
}
size_t find(const char* s, size_t pos = 0) const//找子串
{
assert(pos<_size);
char* p = strstr(_str+pos,s);
if (p == nullptr)
return npos;
else
{
return p - _str;
}
}
三、模拟实现reserve和resize
reserve只会扩容改变容量,不会改变字符的个数
resize既会改变字符的size,还会改变容量capacity,同时还会初始化(缺省值,如果字符串本来有值就不用,没有就初始化)
void reserve(size_t n)
{
char* tmp = new char[n+1];
_capacity = n;
strcpy(tmp, _str);
delete[]_str;
_str = tmp;
}
void resize(size_t n, char c='\0')
{
if (n < _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
if (_capacity < n)
reserve(n);
while (_size < n)
{
_str[_size++] = c;
}
_str[_size] = '\0';
}
}
四、模拟实现insert(插入字符或者字符串)
string& insert(size_t pos, char ch)
{
size_t end = _size;
if (_size + 1 > _capacity)
reserve(_size + 1);
while (end >= pos)
{
_str[end + 1] = _str[end];
end--;
}
_str[pos] = ch;
_size++;
return *this;
}
string& insert(size_t pos, char* ch)
{
assert(pos <= _size);
size_t len = strlen(ch);
if (_size + len > _capacity)
{
reserve(_capacity + len);
}
size_t end = _size;
while (end >= pos)
{
_str[end + len] = _str[end];
end--;
}
_size += len;
return *this;
}
五、模拟实现erase(删除字符串)
string& erase(size_t pos = 0, size_t len = npos)
{
if (len == npos || pos + len > _size)
{
_size = pos;
_str[_size] = '\0';
}
else
{
//方法一
/*size_t exbegin = pos + len;
size_t begin = pos;
for (int i = exbegin; i < _size; i++)
{
_str[begin] = _str[exbegin];
begin++;
exbegin++;
}
_size = begin + 1;
_str[_size] = '\0';*/
//方法二
strcpy(_str+pos,_str+pos+len);
_size -= len;
}
return *this;
}
五、模拟实现substr(取串中某一连续的子串)
string substr(size_t pos = 0, size_t len = npos) const
{
assert(pos < _size);
string s;
s.resize(len);
strncpy(s._str,_str+pos,len);
return s;
}
六、模拟实现流插入、流提取
需要用友元函数进行声明,不然会多出一个参数*this
friend istream& operator>>(istream& is, string& str)//流插入
{
str.clear();//每次读完数就清理一下
char ch = is.get();
char buff[128];
int i = 0;
while (ch != ' ' && ch != '\n')
{
buff[i++] = ch;
ch = is.get();
if (i == 127)
{
buff[127] = '\0';
str += buff;
i = 0;//每加127个字符就重新回置0,以此来继续读取数据
}
}
return is;
}
friend ostream& operator<<(ostream& out, string& str)//流提取
{
for (auto ch : str)
{
out << ch;
}
return out;
}
friend istream& getline(istream& is, string& str)
{
str.clear();//每次读完数就清理一下
char ch = is.get();
char buff[128];
int i = 0;
while (ch != '\n')
{
buff[i++] = ch;
ch = is.get();
if (i == 127)
{
buff[127] = '\0';
str += buff;
i = 0;//每加127个字符就重新回置0,以此来继续读取数据
}
}
return is;
}
七、模拟实现交换
使用库里面的swap达到交换的目的,库里面的swap是深拷贝,string里面的swap仅仅就是指针互换,不开辟新空间
void swap(string& str)
{
std::swap(_capacity, str._capacity);
std::swap(_size, str._size);
std::swap(_str, str._str);
}
七、模拟实现交append(追加字符串)
string& append(const char* s)
{
size_t len = strlen(s);
if (_size + len > _capacity)
{
reserve(_capacity+len);
}
strcpy(_str+_size,s);
_size += len;
return *this;
}
八、模拟实现交replace(将某个位置的字符替换成字符串)
string& replace(size_t pos, size_t len, const string& str)
{
assert(pos <= _size);
if (_size + len > _capacity)
{
reserve(_capacity + len);
}
size_t end = str._size+len;
while (end >= pos)
{
_str[end] = _str[end-len];
end--;
}
strncpy(_str + pos, str._str, len);
_size += len;
return *this;
}
九、模拟实现c_str(字符串拷贝)
const char* c_str() const
{
return _str;
}
十、模拟实现运算符+=
string& operator+=(const string& str)
{
append(str._str);
return *this;
}
十一、全部源码
namespace SF
{
static const size_t npos = -1;
typedef char* iterator;
typedef const char* const_iterator;
class string
{
iterator begin()
{
return _str;
}
const_iterator begin() const
{
return _str;
}
iterator end()
{
return _str+_size;
}
const_iterator end() const
{
return _str + _size;
}
string(const char* str="")
:_size(strlen(str))
{
_capacity = _capacity==0 ? 3 : 2 *_capacity;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
string(const string& str)//深拷贝
:_size(str._size),//列表初始化
_capacity(str._capacity)
{
_str = new char[str._capacity + 1];
strcpy(_str, str._str);
}
string& operator=(const string& s)
{
char* tmp = new char[s._capacity + 1];
delete[] _str;
_size = s._size;
_capacity = s._capacity;
_str = tmp;
}
bool operator>(const string& s)const
{
return strcmp(_str,s._str);
}
bool operator==(const string& s) const
{
return strcmp(_str, s._str)==0;
}
bool operator<(const string& s)const
{
return !(*this == s || *this > s);
}
bool operator<=(const string& s)const
{
return !(*this > s);
}
bool operator>=(const string& s)const
{
return !(*this < s);
}
string& operator+=(const string& str)
{
append(str._str);
return *this;
}
void swap(string& str)
{
std::swap(_capacity, str._capacity);
std::swap(_size, str._size);
std::swap(_str, str._str);
}
size_t find(char c, size_t pos = 0) const//找字符
{
assert(pos >= _size);
for (int i = pos;i<_size;i++)
{
if (_str[i] == c)
return i;
}
return npos;
}
size_t find(const char* s, size_t pos = 0) const//找子串
{
assert(pos<_size);
char* p = strstr(_str+pos,s);
if (p == nullptr)
return npos;
else
{
return p - _str;
}
}
void reserve(size_t n)
{
char* tmp = new char[n+1];
_capacity = n;
strcpy(tmp, _str);
delete[]_str;
_str = tmp;
}
void push_back(const char ch)
{
if (_size + 1 > _capacity)
reserve(_size + 1);
_str[_size] = ch;
_size++;
_str[_size] = '\0';
}
string& append(const char* s)
{
size_t len = strlen(s);
if (_size + len > _capacity)
{
reserve(_capacity+len);
}
strcpy(_str+_size,s);
_size += len;
return *this;
}
string& insert(size_t pos, char ch)
{
size_t end = _size;
if (_size + 1 > _capacity)
reserve(_size + 1);
while (end >= pos)
{
_str[end + 1] = _str[end];
end--;
}
_str[pos] = ch;
_size++;
return *this;
}
string& insert(size_t pos, char* ch)
{
assert(pos <= _size);
size_t len = strlen(ch);
if (_size + len > _capacity)
{
reserve(_capacity + len);
}
size_t end = _size;
while (end >= pos)
{
_str[end + len] = _str[end];
end--;
}
_size += len;
return *this;
}
string& replace(size_t pos, size_t len, const string& str)
{
assert(pos <= _size);
if (_size + len > _capacity)
{
reserve(_capacity + len);
}
size_t end = str._size+len;
while (end >= pos)
{
_str[end] = _str[end-len];
end--;
}
strncpy(_str + pos, str._str, len);
_size += len;
return *this;
}
void resize(size_t n, char c='\0')
{
if (n < _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
if (_capacity < n)
reserve(n);
while (_size < n)
{
_str[_size++] = c;
}
_str[_size] = '\0';
}
}
const char* c_str() const
{
return _str;
}
string& erase(size_t pos = 0, size_t len = npos)
{
if (len == npos || pos + len > _size)
{
_size = pos;
_str[_size] = '\0';
}
else
{
//方法一
/*size_t exbegin = pos + len;
size_t begin = pos;
for (int i = exbegin; i < _size; i++)
{
_str[begin] = _str[exbegin];
begin++;
exbegin++;
}
_size = begin + 1;
_str[_size] = '\0';*/
//方法二
strcpy(_str+pos,_str+pos+len);
_size -= len;
}
return *this;
}
void clear()
{
_size = 0;
_str[_size] = '\0';
}
string substr(size_t pos = 0, size_t len = npos) const
{
assert(pos < _size);
string s;
s.resize(len);
strncpy(s._str,_str+pos,len);
return s;
}
bool empty()
{
return _str == nullptr;
}
friend istream& operator>>(istream& is, string& str)//流插入
{
str.clear();//每次读完数就清理一下
char ch = is.get();
char buff[128];
int i = 0;
while (ch != ' ' && ch != '\n')
{
buff[i++] = ch;
ch = is.get();
if (i == 127)
{
buff[127] = '\0';
str += buff;
i = 0;//每加127个字符就重新回置0,以此来继续读取数据
}
}
return is;
}
friend ostream& operator<<(ostream& out, string& str)//流提取
{
for (auto ch : str)
{
out << ch;
}
return out;
}
friend istream& getline(istream& is, string& str)
{
str.clear();//每次读完数就清理一下
char ch = is.get();
char buff[128];
int i = 0;
while (ch != '\n')
{
buff[i++] = ch;
ch = is.get();
if (i == 127)
{
buff[127] = '\0';
str += buff;
i = 0;//每加127个字符就重新回置0,以此来继续读取数据
}
}
return is;
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
};