3.迭代器的实现
我们先来看看STL库中的string类的迭代器
3.1begin和end的实现
typedef char* iterator; iterator begin() { return _str; } iterator end() {//返回迭代器最后一个位置的下一个位置 return _str + _size; }
3.2迭代器的扩展引用——范围for
for (auto ch : s1) { std::cout << ch << " "; } std::cout << std::endl;
这里可以支持范围for,范围for的底层是迭代器实现的
🔥范围for遇上const类型的对象,会报错,因此要提供const迭代器
typedef const char* const_iterator;
const迭代器,自己可以修改,指向的对象不可以修改,有点像const指针
4.一些常用的运算符重载
bool operator>(const string&str) { return strcmp(_str, str._str) > 0; } bool operator==(const string& str) { return strcmp(_str, str._str) == 0; } bool operator>=(const string& str) { return *this > str || *this == str; } bool operator<(const string& str) { return !(*this >= str); } bool operator<=(const string& str) { return !(*this > str); }
5.string类的增删查改
5.1reserve函数
reserve是一个增容函数
我们先来实现一下reserve函数,再来检验一下实用性
void reserve(size_t n) { if (n > _capacity) { char* tmp = new char[n + 1]; strcpy(tmp, _str); delete[] _str; _str = tmp; _capacity = n; } }
5.2push_back函数
这是一个增加字符到字符串的函数
首先检查是否需要增容,如果需要就调用我们上面实现的 reserve 函数,
参数传递可以用三目操作符,防止容量是0的情况,0乘任何数都是0从而引发问题的情况。
然后在 \0 处插入要追加的字符 append_ch,然后 _size++ 并手动添加一个新的 \0 即可。
void push_back(char ch) { if (_size + 1 > _capacity) { reserve(_capacity * 2); } _str[_size] = ch; ++_size; _str[_size] = '\0'; }
5.3append函数
append函数是追加字符串的函数
void append(const char* str) { size_t len = strlen(str); if (_size + len > _capacity) { reserve(_size + len); } strcpy(_str + _size, str); _size += len; }
5.4 operator+= 的实现
比起push_back和append函数,我们更加喜欢用+=运算符来追加字符串或字符
string& operator+=(char ch) { push_back(ch); return *this; } string& operator+=(const char* str) { append(str); return *this; }
5.5insert函数
🔥如果npos是const可以在类内初始化,这种情况只能出现在整形的情况,double不可以
static const size_t npos=-1;
但是不推荐这样写,推荐老老实实写,这里语法有点冲突,但是不会报错
void insert(size_t pos, char ch) { assert(pos <= _size); if (_size + 1 > _capacity) { reserve(2 * _capacity); } size_t end = _size;//size_t是一个无符号整数 while (end >= pos) { _str[end + 1] = _str[end]; --end; } _str[pos] = ch; ++_size; }
🔑详细解析:
上面代码是错的,end是一个无符号整数,-1的话变为max-1了,这里是等号两边的类型不同,会发生整形提升,有符号会变成无符号的
string& insert(size_t pos, char ch) { assert(pos <= _size); if (_size == _capacity) { size_t newcapacity = _capacity == 0 ? 3 : 2 * _capacity; reserve(newcapacity); } //int cur = pos; size_t end = _size + 1;//size_t是一个无符号整数 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) { size_t newcapacity = _capacity == 0 ? 3 : 2 * _capacity; reserve(newcapacity); } size_t str_cur = 0;//str的下标 size_t end = _size + 1; return *this; }
5.6resize函数
n有三种情况
void resize(size_t n, char ch = '\0') { if (n <= _size) { _size = n; _str[n] = '\0'; } else { if (n > _capacity) { reserve(n); } size_t i = _size; while (i < n) { _str[i] = ch; ++i; } _size = n; _str[n] = '\0'; } }
5.7erase函数
erase的三种情况
string& erase(size_t pos, size_t len = npos) { assert(pos < _size); if (pos + len >= _size || len == npos) { _str[pos] = '\0'; _size = pos; } else { strcpy(_str + pos, _str + pos + len); _size -= len; } return *this; }
5.8find函数
size_t find( char ch,size_t pos=0) { assert(pos < _size); for (size_t i = pos; i < _size; ++i) { if (_str[i] == ch) return i; } return npos; } size_t find(const char* str, size_t pos = 0) { assert(pos < _size); char* p = strstr(_str + pos, str); if (p == nullptr) { return npos; } else { return p - _str; } }
在这里插入代码片