手撕容器string(了解底层)2
目录
简介:
1.指定位置插入删除的实现
1.1指定位置插入字符串
1.2指定位置删除指定长度字符串
1.3将字符串长度调整到指定长度
1.4从指定位置开始找指定字符和指定字符串
2.拷贝构造,赋值操作符重载,以及子字符串拷贝
2.1拷贝构造函数
2.2赋值操作符重载
2.3子字符串拷贝
3关系操作符的重载
4.输入输出操作符重载
摘要:
简介:
本文为上篇内容的后半部分,看本文之前最好先看前一部分内容
1.指定位置插入删除的实现
1.1指定位置插入字符串
void string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(std::max(_size + len, _capacity * 2));}// 挪动数据/*int end = _size;while (end >= (int)pos){_str[end + len] = _str[end];--end;}*/size_t end = _size + len;while (end > pos + len - 1)//与上边的情况相比避免了无符号整型溢出的情况{_str[end] = _str[end - len];--end;}//strncpy(_str + pos, str, len);memcpy(_str + pos, str, len);_size += len;}
1.2指定位置删除指定长度字符串
void string::erase(size_t pos, size_t len){assert(pos < _size);if (len == npos || len >= _size - pos)//npos是整数的最大值{// 删完_size = pos;_str[_size] = '\0';}else{// 删部分//strcpy(_str + pos, _str + pos + len);memcpy(_str + pos, _str + pos + len, _size - (pos + len) + 1);_size -= len;}}
1.3将字符串长度调整到指定长度
void string::resize(size_t n, char ch){if (n <= _size){// 删除,保留前n个_size = n;_str[_size] = '\0';}else{reserve(n);for (size_t i = _size; i < n; i++)//多出来的用指定字符补齐{_str[i] = ch;}_size = n;_str[_size] = '\0';}}
1.4从指定位置开始找指定字符和指定字符串
size_t string::find(char ch, size_t pos){assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == ch)return i;}return npos;//找不到返回-1}

size_t string::find(const char* str, size_t pos){assert(pos < _size);const char* ptr = strstr(_str + pos, str);if (ptr){return ptr - str;}else{return npos;}}
2.拷贝构造,赋值操作符重载,以及子字符串拷贝
2.1拷贝构造函数
// string s2(s1);string::string(const string& s){_str = new char[s._capacity + 1];//因为_capacity不包括\0,所以加一//strcpy(_str, s._str);memcpy(_str, s._str, s._size + 1);//与上同理_size = s._size;_capacity = s._capacity;}
2.2赋值操作符重载
当双目操作符作为成员函数重载时,第一个操作数为当前对象(this),第二个操作数通过参数传递
// s1 = s3string& string::operator=(const string& s){if (this != &s){char* tmp = new char[s._capacity + 1];//strcpy(tmp, s._str);memcpy(tmp, s._str, s._size + 1);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;}return *this;}
2.3子字符串拷贝
string string::substr(size_t pos, size_t len){assert(pos < _size);if (len == npos || len > _size - pos){len = _size - pos;}string sub;sub.reserve(len);for (size_t i = 0; i < len; i++){sub += _str[pos + i];}return sub;}
3关系操作符的重载
bool string::operator==(const string& s) const{return strcmp(_str, s._str) == 0;}bool string::operator<(const string& s) const{return strcmp(_str, s._str) < 0;}bool string::operator<=(const string& s) const{return *this < s || *this == s;}bool string::operator>(const string& s) const{return !(*this <= s);}bool string::operator>=(const string& s) const{return !(*this > s);}bool string::operator!=(const string& s) const {return !(*this == s);}
4.输入输出操作符重载
输入输出操作符只能被重载成全局函数,需要访问私有成员变量时可将其声明为友缘函数。
std::ostream& operator<<(std::ostream& out, const string& s){for (auto ch : s){out << ch;}return out;}std::istream& operator>>(std::istream& in, string& s){s.clear();char buff[256];int i = 0;char ch;//in >> ch;拿不到空格ch = in.get();//一个字符一个字符地拿while (ch != '\n' && ch != ' '){buff[i++] = ch;if (i == 255){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}std::istream& getline(std::istream& in, string& s, char delim ){s.clear();char buff[256];int i = 0;char ch;//in >> ch;ch = in.get();while (ch != delim){buff[i++] = ch;if (i == 255){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}
摘要:
本文是字符串类实现的后半部分,重点介绍了插入、删除、查找等核心功能的实现细节。通过指定位置插入字符串时处理容量不足和内存挪动,删除操作区分全删与部分删除的情况。查找功能支持字符和子串定位,拷贝构造与赋值操作确保深拷贝正确性。关系运算符重载基于strcmp实现字符串比较,输入输出运算符重载则通过缓冲机制高效处理流数据。整体实现了标准字符串类的关键功能。
