一、标准库中的string类
1.string类文档介绍
(1)字符串是表示字符序列的类。
(2)标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
(3)string类是使用char(即作为他的字符类型,使用它的默认char_traits和分配器类型)。
(4)string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并使用char_traits和allocator作为basic_string的默认参数。
(5)这个类独立于所使用的编码来处理字节,如果用来处理多字节或变长字符(如utf-8)的序列,这个类的所有成员(如长度、大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
2.string类常用接口介绍
2.1string类对象的常见构造
2.2string类对象的容量操作
注意:
(1)size和length方法的底层实现原理完全相同,引入size的原因是为了与其他容器的接口保持一致,一般情况下基本都是使用size。
(2)clear只是将string中有效字符清空,不改变底层空间大小。
(3)resize(size_t n)与resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时,resize(size_t n)用0来填充多出的元素空间,而resize(size_t n, char c)是用字符c来填充多出的元素空间。
注意:resize在改变元素个数时,若是将元素个数增多,可能会改变底层容量的大小,若是将元素个数减少,底层空间总大小不变。
(4)reserve(size_t res_arg=0):为string预留空间,不改变有效元素的个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。
2.3string类对象的访问及遍历操作
2.4string类对象的修改操作
二、模拟实现string类
1.实现的接口
1.1类默认的成员函数
构造函数
拷贝构造函数
赋值运算符重载
析构函数
1.2迭代器相关
迭代器通过指针模拟实现。
1.3容量相关
1.4元素访问
1.5元素修改相关
字符/字符串追加
1.6字符串操作相关
获取C语言格式字符串
查找字符
获取子串
字符串交换
1.7IO操作相关
输入输出
2.代码实现
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
#include <assert.h>
using namespace std;namespace MyString {class string {public://用指针模拟实现迭代器typedef char* iterator;typedef char* reverse_iterator;/*--------------默认成员函数--------------*///默认构造string(const char* str = "") {if (str == nullptr) str = "";_size = strlen(str);_capacity = _size;_str = new char[_size + 1];//需要加上\0所占的空间strcpy(_str, str);}//拷贝构造string(const string& s): _str(nullptr), _size(0),_capacity(0){//传统写法//_str = new char[strlen(s._str) + 1];//strcpy(_str, s._str);string str_temp(s._str);this -> swap(str_temp);}//n_char构造string(size_t n, char ch) {_size = n;_capacity = n;_str = new char[n + 1];memset(_str, ch, n);_str[n] = '\0';}//赋值运算符重载string& operator=(string s) {if (this != &s) {//防止自己给自己赋值//传统写法//char* temp = new char[strlen(s._str) + 1];//strcpy(temp, s._str);//delete[] _str;//_str = temp;this -> swap(s);}return *this;}//析构~string() {if (_str) {delete[] _str;_str = nullptr;}}/*--------------迭代器--------------*//*使用指针模拟实现*/iterator begin() {return _str;}iterator end() {return _str + _size;}reverse_iterator rbegin() {return end();}reverse_iterator rend() {return begin();}/*--------------容量--------------*/size_t size() const {return _size;}size_t capacity() const {return _capacity;}bool empty() const {return 0 == _size;}void clear() {_size = 0;}void resize(size_t new_size, char ch) {if (new_size > _size) {size_t old_size = _size;if (new_size > _capacity) {//需要扩容reserve(new_size);}memset(_str + _size, ch, new_size - old_size);}_size = new_size;_str[_size] = '\0';}void resize(size_t n) {resize(n, 0);}void reserve(size_t new_capacity) {//扩容size_t old_capacity = _capacity;if (new_capacity > old_capacity) {char* temp = new char[new_capacity + 1];strcpy(temp, _str);delete[] _str;_str = temp;_capacity = new_capacity;}}/*--------------元素访问--------------*/char& operator[](size_t index) {assert(index < _size);return _str[index];}const char& operator[](size_t index) const {assert(index < _size);return _str[index];}/*--------------元素修改--------------*/void push_back(char ch) {if (_size == _capacity) {//需要扩容if (_capacity == 0) _capacity = 1;//若初始为0,按2倍扩容方式则无法扩容reserve(_capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';}string& operator+=(char ch) {push_back(ch);return *this;}string& operator+=(const string& s) {*this += s._str;return *this;}string& operator+=(const char* s) {size_t len = strlen(s);char* temp = new char[_size + len + 1];strcpy(temp, _str);strcat(temp, s);delete[] _str;_str = temp;_size += len;_capacity = _size;return *this;}/*--------------字符串操作--------------*/const char* c_str() const {return _str;}size_t find(char ch, size_t pos = 0) {for (size_t i = pos; i < _size; ++i) {if (_str[i] == ch) return i;}return npos;}size_t rfind(char ch, size_t pos = npos) {//注意无符号-1是一个非常大的数字pos = pos < _size ? pos : _size - 1;for (int i = pos; i >= 0; --i) {if (_str[i] == ch) return i;}return npos;}string substr(size_t pos, size_t n = npos) {if (n == npos) n = _size;// 没有传入n时,最多截取_size长度if (pos + n >= _size) {n = _size - pos;}char* temp = new char[n + 1];strncpy(temp, _str + pos, n);temp[n] = '\0';string sub(temp);delete[] temp;return sub;}//交换函数void swap(string& s) {std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}/*--------------IO操作--------------*/friend ostream& operator<<(ostream& _cout, const string& s) {_cout << s._str;return _cout;}friend istream& operator>>(istream& _cin, string& s) {//直接输入无法扩容while (1) {char ch = _cin.get();if (ch == '\n' || ch == ' ') break;s.push_back(ch);}return _cin;}private:char* _str;size_t _size;size_t _capacity;public:static size_t npos;};size_t string::npos = -1;
}