【c++】string类的模拟实现--1 https://developer.aliyun.com/article/1424720
四,容器接口函数的实现
1,增删操作
在实现增删之前,我们首先实现reserve增容接口。需注意reserve不能减小容量,只能增加容量。
void reserve(size_t n) { if (_capacity < n) //不能减小容量 { _capacity = _capacity == 1 ? n : 2 * n; char* str = new char[_capacity]; memcpy(str, _str, strlen(_str) + 1); delete[] _str; _str = str; } }
这里我们对push_back、erase、+=、append操作进行接口实现。其中,push_back只能在末尾增添一个字符,erase可删除多个字符或全部字符,“+=” 和append都是在末尾连接一个串。在实现中,要注意string为空和满载的情况。当满载时,需使用reserve进行增容操作,当为空时,要根据接口的功能来进行下一步作用。
//删除操作 string& erase(size_t pos, size_t len) { //防止错误操作 assert(len >= 0); assert(pos >= 0 && pos < _size); int deletelen = len; if (deletelen > _size - pos) //注意当len大于string大小的情况 { deletelen = _size - pos; } int _strlen = _size + 1; memcpy(_str + pos, _str + pos + deletelen, _strlen - pos - deletelen); return *this; } //增加操作 void push_back(char c) { if (_size == _capacity - 1) { reserve(_capacity + 1); } _str[_size++] = c; _str[_size] = '\0'; } void append(const char* str) { if (_capacity - 1 < _size + strlen(str)) { reserve(_size + strlen(str)); } for (int i = 0; i < strlen(str); i++) { push_back(str[i]); } } string& operator+=(char c) { push_back(c); return *this; } string& operator+=(const char* str) { append(str); return *this; }
2,查找与插入
这里我们模拟find查找和insert插入。实现find查找,若找到指定的数据,返回第一次出现的位置,若没有找到,返回无符号整型-1的数值。实现insert插入,只需注意要插入的位置在合理位置上即可。
//find查找操作 size_t find(char c, size_t pos = 0) const //返回c在string中第一次出现的位置 { for (int i = pos; i < _size && pos >= 0; i++) { if (_str[i] == c) { return i; } } return -1; } size_t find(const char* s, size_t pos = 0) const //返回子串s在string中第一次出现的位置 { for (int i = pos; i < _size && pos >= 0; i++) { int k = i; for (int j = 0; j < strlen(s) && i < _size; j++) { if (s[j] == _str[i]) { if (i - k + 1 == strlen(s)) return k; i++; } else break; } i = k; } return -1; } //insert插入操作 string& insert(size_t pos, char c) { assert(pos >= 0 && pos <= _size); //保证插入的位置在合理范围中 if (_capacity == _size) { reserve(_capacity + 1); } for (int i = _size; i >= pos; i--) { _str[i + 1] = _str[i]; } _str[pos] = c; _size++; return *this; } string& insert(size_t pos, const char* str) { assert(pos >= 0 && pos <= _size); //保证插入的位置在合理范围中 if (_capacity < _size + strlen(str) + 1) { reserve(_size + strlen(str) + 2); } for (int i = _size; i >= pos; i--) { _str[i + strlen(str)] = _str[i]; } int j = 0; for (int i = pos; i < pos + strlen(str); i++) { _str[i] = str[j++]; } _size += strlen(str); return *this; }
3,接口的常规操作
string容器其它的常规接口有resize、swap、c_str、size、capacity、empty、clear七大函数操作。之前已经说明了这七个接口的功能,它们的实现原理也很简单,这里就不做说明,代码如下:
void swap(string& s) { string tem = s; s = *this; *this = tem; } const char* c_str()const { return _str; } size_t size()const { return _size; } size_t capacity()const { return _capacity; } bool empty()const { return _size == 0 ? true : false; } void resize(size_t n, char c = '\0') { assert(n >= 0); for (int i = _size; i < n; i++) { push_back(c); } _size = n; _str[_size] = '\0'; } void clear() //注意:clear不会清理空间,只是将数据清理掉 { delete[] _str; char* str = new char[_capacity]; _str = str; memcpy(_str, "", 1); _size = 0; }
以上是对string容器实现的常规接口操作,实现的功能与正规的功能具有差别,这里只需保证我们实现功能用法与正规的一样并保证操作时不会出现bug即可。特别注意的是构造与析构、赋值运算符的模拟实现,这种形式在公司面试和笔试上经常会出现。