string类的模拟实现
- 0:类的成员变量:
- 一.构造析构赋值:
- 1.构造:
- 2.析构:
- 3.赋值:
- 二.容量相关:
- 1.size()
- 2.capacity()
- 3.reserve()
- 4.clear()
- 5.empty()
- 三.c_str和operator[]
- 1.c_str
- 2.operator[]
- 四.push_back 和 append 和 operator+=
- 1.push_back:
- 2.append:
- 3.operator+=:
- string& operator+= (const string& str);
- string& operator+= (const char* s);
- string& operator+= (char c);
- 五:insert 和 erase 和 swap
- 1.insert:
- 1-1: 在pos位置插入单个字符:
- 1-2:在pos位置插入const char* 数据:
- 2.erase:
- 3.swap:
- 六. find() 和 substr()
- 1.find()
- 1-1:size_t find (const char* s, size_t pos = 0) const;
- 1-2:size_t find (char c, size_t pos = 0) const;
- 2.substr()
- 七:iterator:
- 八:流插入和流提取:
- 流插入:
- 流提取:
0:类的成员变量:
//测试:遍历用来测试代码:void print_str(){assert(_str != nullptr);for (size_t pos = 0; pos < _size; pos++){std::cout << _str[pos];}std::cout << std::endl;}
一.构造析构赋值:
1.构造:
1.我们观察一下实现1和4可以实现一个缺陷省参数去把两个构造给包含在一起:
//1-1:空和const char* sstring(const char* str="\0")//const char* str = "" C语言特性空字符串就是一个"\0"{//问题一:建议不要使用初始化列表进行:因为初始化列表的顺序是根据成员变量声明的顺序。//问题二:应该开辟的空间大小?//_size 的意义是:当前有效字符的个数 _capacity的意义是:当前可以存放的最多的有效字符的个数:if (str == "\0"){_str = new char[1] {'\0'};_size = 0;_capacity = 0;}else{size_t len = strlen(str);_str = new char[len+1];strcpy(_str, str);_size = len;_capacity = len;}}
2.2是我们的拷贝构造是需要实现的!
string(const string& str){if (str._size == str._capacity){if (str._capacity == 0){_str = new char[1] {'\0'};_size = 0;_capacity = 0;}else{_str = new char[str._capacity + 1];for (int i = 0; i < str._size; i++){_str[i] = str._str[i];}_size = str._size;_capacity = str._capacity;}}}
3.6是使用n个C字符实现去构造一个字符串也可以实现一下:
string(size_t n, const char c){if (n == 0){_str = new char[1] {'\0'};_size = 0;_capacity = 0;}else{_str = new char[n + 1];size_t pos = 0;for (pos = 0; pos < n; pos++){_str[pos] = 'c';}_str[pos] = '\0';_size = n;_capacity = n;}}
2.析构:
//2:析构函数:~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}
3.赋值:
1.string 类型的赋值:
//2-1:字符串赋值:string& operator=(const string& str){//1.排除自己给自己赋值的情况!if (this == &str)return *this;//2.考虑str比较长的情况:if (str._size > _capacity){//1.开一个空间:char* tmp = new char[str._size + 1];//2.拷贝数据到新空间:strcpy(tmp, str._str);//3.释放旧空间:delete[] _str;_str = tmp;_size = str._size;_capacity = str._size;}//3.被赋值的变量的_capacity是足够的!else{strcpy(_str, str._str);_size = str._size;}return *this;}
2.const char* 类型的赋值:
//2-2:const char* 赋值:string& operator=(const char* str){size_t len = strlen(str);//2.考虑str比较长的情况:if (len > _capacity){//1.开一个空间:char* tmp = new char[len + 1];//2.拷贝数据到新空间:strcpy(tmp, str);//3.释放旧空间:delete[] _str;_str = tmp;_size = len;_capacity = len;}//3.被赋值的变量的_capacity是足够的!else{strcpy(_str, str);_size = len;}return *this;}
二.容量相关:
1.size()
//3-1:size():不对对象进行修改只去读数据的代码给*this加一个const修饰! size_t size()const{return _size;}
2.capacity()
//3-2: capacity()size_t capacity()const{return _capacity;}
3.reserve()
//3-3:reserve():n为多大就开多大的有效空间:void reserve(size_t n){//1.不考虑容量减少的情况://2.C++ 下是没有realloc函数://2-1:开一个大小为n的新的空间:char* tmp = new char[n+1];//2-2:把字符串用来的内容放到新开辟好的空间里面:strcpy(tmp, _str);//2-3:原来空间释放+数值的更新:delete[] _str;_str = tmp;_capacity = n;}
4.clear()
//3-4:clear():擦除字符串内容+把字符串变成空字符串void clear(){delete[] _str;_str = new char[1] {'\0'};_size = 0;_capacity = 0;}
5.empty()
//3-5:empty():判断字符串是否为空:bool empty(){if (_size == 0){return true;}return false;}
三.c_str和operator[]
1.c_str
//4-1:c_str():const char* c_str()const{return _str;}
2.operator[]
//4-2:operator[]//4-2-1:只读://const string * this 修饰内容://1.引用返回造就了可读可写!//2.双const修饰防止了引用返回导致的修改的可能性!const char& operator[](size_t pos)const{assert(_str != nullptr);return _str[pos];}//4-2-2:可读可写://1.引用返回造就了可读可写!char& operator[](size_t pos){assert(_str != nullptr);return _str[pos];}
四.push_back 和 append 和 operator+=
1.push_back:
//5-1:push_back()void push_back(char c){assert(_str != nullptr);if (_size == _capacity){//1.处理开始为0的情况,正常就去扩二倍:_capacity = _capacity == 0 ? 4 : _capacity*2;//2.使用reserve非常方便:reserve(_capacity);}//3.要保持住结尾的'\0'_str[_size++] = c;_str[_size] = '\0';}
2.append:
1.加上一个字符串:
//5-2-1:添加一个字符串:string& append(const string& str){assert(_str != nullptr);size_t len = str.size();if (len + _size > _capacity){reserve(len + _size + 1);}strcpy(_str+_size, str._str);_size += str._size;return *this;}
2.加上一个const char*
//5-2-2:添加一个const char* 的值:string& append(const char* str){assert(_str != nullptr);size_t len = strlen(str);if (len + _size > _capacity)ize{reserve(len + _size + 1);}strcpy(_str + _size, str);_size += len;return *this;}
3.operator+=:
string& operator+= (const string& str);
string& operator+= (const string& str){append(str);return *this;}
string& operator+= (const char* s);
string& operator+= (char c){push_back(c);return *this;}
string& operator+= (char c);
string& operator+= (const char* s){append(s);return *this;}
五:insert 和 erase 和 swap
1.insert:
1-1: 在pos位置插入单个字符:
string& insert(size_t pos , char c){assert(pos < _size);if (_size + 1 > _capacity){reserve(_size + 1);}size_t end = _size + 1;while (pos < end){_str[end] = _str[end - 1];end--;}_str[pos] = c;_size += 1;_str[_size] = '\0';return *this;}
1-2:在pos位置插入const char* 数据:
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 (pos < end){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str,len);_size += len;_str[_size] = '\0';return *this;}
2.erase:
string& erase(size_t pos = 0, size_t len = npos){assert(_str != nullptr);if (len == npos || len > _size - pos){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);}return *this;}
3.swap:
1.swap 为什么会有三个重载:
2.string 类实现的swap方法:
3.swap一个全局的:
4.使用全局函数模板生成的一个string
void swap(string& s1, string& s2){char* tmp = s1._str;size_t tmp_1 = s1._size;size_t tmp_2 = s2._capacity;s1._str= s2._str;s1._size= s2._size;s1._capacity= s2._capacity;s2._str = tmp;s2._size = tmp_1;s2._capacity = tmp_2;}//6-3:swap()void swap(string& str){swap(*this, str);}
六. find() 和 substr()
1.find()
1-1:size_t find (const char* s, size_t pos = 0) const;
size_t find(const char* ch, size_t pos = 0){assert(pos < _size);//1.有可能找不到子串:const char* ptr = strstr(_str, ch);if (ptr == nullptr){return npos;}else{return ptr - _str;}}
1-2:size_t find (char c, size_t pos = 0) const;
//7:find() substr()size_t pos(char ch , size_t pos = 0){assert(pos < _size);for (size_t pos = 0; pos < _size; pos++){if (_str[pos] == ch){return pos;}}}
2.substr()
string substr(size_t pos , size_t len=npos){string str;if (len == npos || len > _size-pos){str.reserve(_size - pos);}for (size_t i = pos; i < _size; i++){str += _str[i];}return str;}
七:iterator:
1.begin()
//8:iterator()typedef char* iterator;iterator begin(){return _str;}
2.end()
iterator end(){return _str + _size;}
3.使用:
void text_8()
{sfpy::string s1("hello iterator");sfpy::string::iterator it_1 = s1.begin();while (it_1!=s1.end()){std::cout << (*it_1);it_1++;}}
八:流插入和流提取:
流插入:
std::istream& operator>>(std::istream& _cin, string& s1)
{//assert(string::_str != nullptr);char tmp = 0;while (scanf("%c", &tmp) != 0 && tmp != '\n'){s1.push_back(tmp);}return _cin;
}
流提取:
std::ostream& operator<<(std::ostream& _cout, string& s1)
{//assert(string::_str != nullptr);string::iterator it_1 = s1.begin();while (it_1 != s1.end()){_cout << (*it_1);it_1++;}return _cout;
}