【C++】—— string模拟实现(一)https://developer.aliyun.com/article/1621432
2、insert、erase
insert重载也比较多,比较冗余;这里也只实现其中的一部分;
erase这里只实现一个
//insert 、erase void insert(size_t pos, const string& str) { assert(pos >= 0 && pos < _size); size_t len = str._size; size_t n = _size + len; if (n > _capacity) { reserve(n); } //挪动数据 for (size_t i = n; i >= pos + len; i--) { _str[i] = _str[i - len]; } memcpy(_str + pos, str._str, str._size); _size += str._size; _str[_size] = '\0'; } void insert(size_t pos, const char* s) { assert(pos >= 0 && pos < _size); size_t len = strlen(s); size_t n = _size + len; if (n > _capacity) { reserve(n); } //挪动数据 for (size_t i = n; i >= pos + len; i--) { _str[i] = _str[i - len]; } memcpy(_str + pos, s, len); _size += len; _str[_size] = '\0'; } void insert(size_t pos, size_t n, char c) { assert(pos >= 0 && pos < _size); if (_size + n > _capacity) { reserve(_size + n); } //挪动数据 for (size_t i = _size+n; i >= pos + n; i--) { _str[i] = _str[i - n]; } for (size_t i = 0; i < n; i++) { _str[pos + i] = c; } _size += n; _str[_size] = '\0'; } void erase(size_t pos, size_t len = npos) { assert(pos >= 0 && pos < _size); if (len == npos) { _str[0] = '\0'; _size = 0; return; } for (size_t i = pos; (len + i) < _size; i++) { _str[i] = _str[i + len]; } _size -= len; _str[_size] = '\0'; }
3、find
//find size_t find(const string& str, size_t pos = 0) { assert(pos >= 0 && pos < _size); char* tmp = strstr(_str + pos, str._str); if (tmp == nullptr) { return -1; } return tmp - _str; } size_t find(const char* s, size_t pos = 0) { assert(pos >= 0 && pos < _size); char* tmp = strstr(_str + pos, s); if (tmp == nullptr) { return -1; } return tmp - _str; } size_t find(char c, size_t pos = 0) { assert(pos >= 0 && pos < _size); for (size_t i = pos; i < _size; i++) { if (_str[i] == c) { return i; } } return -1; }
4、swap
swap作为string的成员函数,交换两个string类类型的对象。
//swap void swap(string& str) { Swap(_str, str._str); Swap(_size, str._size); Swap(_capacity, str._capacity); }
这里swap函数内部也可以调用库里面的swap模版(这里我自己写了一个模版Swap)
有了swap函数,上面赋值运算符重载中就可以这样写了:
string& operator= (const string& str) { string tmp(str); swap(tmp); return *this; }
四、字符串操作函数
1、c_str
c_str()函数返回string类对象中的字符串;
const char* c_str() const { return _str; } char* c_str() { return _str; }
2、substr
获得,sting对象中字符串的子串。
//substr string substr(size_t pos = 0, size_t len = npos) const { assert(pos >= 0 && pos < _size); size_t n = 0; if (len == npos || pos + len > _size) { n = _size - pos; } else { n = len; } string ret; for (size_t i = 0; i < n; i++) { ret += _str[pos + i]; } return ret; }
五、其他成员函数
这里max_size是返回容器可以容纳的最大元素的数量,这里就不进行实现了。
reserve在增加元素前已经实现了。(扩容)
//其他成员函数 size_t size() const { return _size; } size_t length()const { return _size; } size_t capacity()const { return _capacity; } void clear() { _str[0] = '\0'; _size = 0; } bool empty()const { return _size == 0; } void resize(size_t n) { if (n > _capacity) { reserve(n); } _size = n; _str[_size] = '\0'; } void resize(size_t n, char c) { if (n > _capacity) { reserve(n); } for (size_t i = _size; i < n; i++) { _str[i] = c; } _size = n; _str[_size] = '\0'; }
六、流插入、流提取
因为成员函数有一个隐藏的this指针,会和istream 和istream 类对象抢占第一个参数的位置,所以我们不能将流插入和流提取写成string类的成员函数。
string中实现了访问元素方成员函数,就可以不将流插入、流提取写成string类的友元函数。
1、流插入运算符重载
std::ostream& operator<<(std::ostream& out, const HL::string& str) { //for (int i = 0; i < str.size(); i++) //{ // out << str[i]; //} //return out; for (auto ch : str) { out << ch; } return out; }
2、流提取运算符重载
1、 s.clear()清理缓冲区(上次cin流提取的剩余);
2、 创建一个数组,防止多次去开空间(输入到128或者输入结束(‘ ’或者‘\n’)才添加到str中)。
3、下面的代码处理缓冲区的空格。
char ch;
ch = in.get();
while (ch == ' ' || ch == '\n')
{
ch = in.get();
}
4、最后循环里if是遇到空格或者换行结束,将s中输入添加到s中,末尾添加'\0'。
std::istream& operator>>(std::istream& in, HL::string& str) { char s[128] = { 0 }; char ch; ch = in.get(); while (ch == ' ' || ch == '\n') { ch = in.get(); } str.clear(); int i = 0; while (ch != '\n') { s[i] = ch; i++; if (i == 127) { s[i] = '\0'; str += s; i = 0; } ch = in.get(); } if (i) { str += s; } return in; }
【C++】—— string模拟实现(三)https://developer.aliyun.com/article/1621435