string是表示字符串的字符串类,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。. string在底层实际是:basic_string模板类的别名,typedef basic_string string,在使用string类时,必须包含#include头文件以及using namespace std;
本篇文章将重点讲解string类的使用和模拟实现
| string() | 构造空的string类对象,即空字符串 |
| string(const char*s) | 用C-string来构造string类对象 |
| string(size_t n,char c) | string类对象中包含n个字符C |
| string(const string& s) | 拷贝构造 |
| string(const char* s,size_t n) | 用字符串s的前n个字符来构造 |
| size() | 返回字符串的有效字符长度 |
| length() | 返回字符串的有效字符长度 |
| capacity() | 返回空间总大小 |
| empty() | 检测字符串是否为空,是返回true,否则返回false |
| clear() | 清空有效字符 |
| reserve(int) | 为字符串预留空间 |
| resize(int,char) | 将有效字符的个数该成n个,多出的空间用字符c填充,如果只给了一个参数,默认初始化为'\0' |
注意:
1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。
2. clear()只是将string中有效字符清空,不改变底层空间大小。
3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。
1.operator[]
- string str = "hello word";
- int size = str.size();
- for (int i = 0; i < size; i++)
- {
- //str.operator[](i);
- cout << str[i] << endl;
- }
2.迭代器
正向迭代器
- string str = "hello word";
- string::iterator it = str.begin();//得到一个指向首元素的指针
- while (it != str.end())//str.end()得到一个指向'\0'的指针
- {
- cout << *it << endl;
- it++;
- }

反向迭代器
- string str = "hello word";
- string::reverse_iterator it = str.rbegin();//得到一个指向最后一个有效元素的指针
- while (it != str.rend())//str.rend()得到一个指向首元素前一个的指针
- {
- cout << *it << endl;
- it++;
- }

string::iterator得到的是可读可写的指针,可以通过该指针修改原来的字符串
如果想保护原来的字符数,只读不让写string::const_iterator
为了方便,我们可以用auto的方式来自动识别类型


3.范围for
- string str = "hello word";
- for (auto e : str)
- {
- cout << e << endl;
- }
- return 0;
范围for的底层原理还是迭代器
| push_back | 在字符串后尾插字符c |
| append | 在字符后追加一个字符串 |
| operator+=(最常用的) | 在字符串后追加字符串str |
| c_str | 返回C格式字符串 |
| find+npos | 从字符串pos位置开始往后找字符c,返回该字符在字符串的位置 |
| rfind | 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置 |
| substr | 在str中从pos位置开始,截取n个字符,然后将其返回 |
注意:
1. 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般 情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。
| operator+ | 尽量少用,因为船只返回,导致深拷贝效率低 |
| operator>> | 流输入运算符重载 |
| operator<< | 流提起运算符重载 |
| getline | 获取一行字符串 |
| relational operators | 比较运算符重载 |
在标准库中没有对string变量赋初始值的话,会默认是空字符串,开15个空间

- string(const char* str = "")
- :_size(strlen(str))
- , _capacity(15)
- {
- if (_size>_capacity)
- {
- _capacity = _size;
- }
- _str = new char[_capacity + 1];
- strcpy(_str, str);
- }
reserve是string类中更改容量的一个成员函数,准确的来说是一个扩容函数,如果n 写拷贝构造函数前需要讲讲深浅拷贝问题 如果没有写拷贝构造函数,那么编译器就会自动生成一个浅拷贝的拷贝构造函数 如果是浅拷贝的话,str1和str2指向的字符串中间是同一片空间,会造成以下几个问题 1.如果str1修改,会影响str2的值,同样str2修改会影响str1的值 2.结束调用析构函数的时候会对同一片空间析构两次 所以需要深拷贝,深拷贝会重新开辟一个空间给str2 上面这个拷贝构造函数是传统的写法,现在的拷贝构造函数会复用构造函数 和拷贝构造函数一样, 获得c语言形式的字符串 获得字符串长度 []运算符重载,获取字符串中i位置的字符 同时需要考虑到只读的情况 同样赋值运算符重载也可以复用构造函数 比较函数的实现 比较原则:比较第一个不匹配的字符的大小,如果都匹配就比较字符串的长度 我们就实现两个重载,一个是从pos位置插入一个字符,一个是从pos位置插入字符串 insert函数与顺序表的插入一样,可以参考下面这篇文章 (4条消息) 【数据结构】顺序表_Patrick star`的博客-CSDN博客 尾插一个字符,可以复用insert 尾插一个字符串,同样复用insert 复用push_back和append string类中的迭代器实际上就是char指针的别名 当我们使用范围for进行遍历的时候,编译器会自动调用迭代器,所以这也要求我们命名必须规范,如果命名不规范就不能使用范围for进行遍历

2.3拷贝构造函数


2.4 operator=()
2.4 c_str()
2.5 size()
2.6 capacity()
2.7 operator[]()
2.8 operator=()
2.9relational operator

2.10 insert()


2.11push_back()
2.12 append()
2.13 operator+=()
2.14 迭代器
2.15 流提取和流插入运算符重载