👦个人主页:@Weraphael
✍🏻作者简介:目前学习C++和算法
✈️专栏:C++航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨
目录
一、什么是STL
STL
(standard template libaray
- 标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
STL的六大组件:
二、string类概念总结
string
是一个管理字符数组的类,准确来说是 管理字符数组的顺序表。- 容器本质上就是数据结构。因此,容器的接口都有增删查改等功能。
- 在使用
string
类时,必须包含头文件#include <string>
三、string类的常用接口(重点)
3.1 常见的四种构造(初始化)
3.1.1 构造空对象,即空字符串
3.1.2 C字符串构造
3.1.3 拷贝构造函数
3.1.4 赋值运算符重载
3.2 常见容量操作
3.2.1 size(重点)
返回字符串的有效长度(不包含
'\0'
)
注意:
'\0’
是标识字符串结束的特殊字符,不算有效字符
3.2.2 resize(了解)
功能:调整字符串大小
【文档描述】
- 如果
n
小于当前字符串长度,则当前对象的大小size
调整到n
,并删除大于size
以后的字符
- 如果
n
大于当前字符串长度,则通过在末尾插入所需数量的字符以达到n
大小来扩展当前内容。如果指定了c
,则新元素初始化为C
,否则,初始化字符为空字符。
这个接口大家现阶段了解即可,这是为后面模拟实现string
做铺垫。
3.2.3 empty(重点)
功能:检测字符是否为空字符串。如果是空字符串返回
true
,否则返回false
3.2.4 clear
功能:清空有效字符
注意:clear
只会清除有效的字符,因此size
会改变,但是容量capacity
不会改变
3.2.5 reserve(了解)
功能:改变容量
【文档描述】
注意:reserve
一般很少会缩容,一般都是扩容
四、string类对象的修改操作
4.1 push_back
功能:尾插一个字符
4.2 append
功能:尾插字符串
4.3 运算符重载+=
功能:
- 既可以尾插一个字符,也能尾插一个字符串。
- 字符串拼接
4.4 insert
- 功能:插入字符或者字符串
- 缺点:效率低,特别是头插
【函数原型】
4.5 erase
功能:删除某个位置的字符或者字符串
【函数原型】
4.6 c_str
功能:将
string
转化为C字符串。
比如printf
只能打印内置类型,如果想打印string
类型,可以使用c_str
先将string
类型转化为C形式的字符串
4.7 find
功能:查找字符。找到第一次出现的字符下标,如果没有找到会返回
npos
,npos
是string
的静态成员变量,其默认值为-1
【函数原型】
4.8 pop_back
功能:尾删一个字符
4.9 substr
功能:截取子串
4.10 rfind
功能:从字符串的后面开始往前找第一次出现的字符,找到后会返回下标
4.11 operator+
string
类重载了运算符+
,可以拼接2个字符串
五、迭代器iterator
5.1 什么是迭代器
现阶段可以理解迭代器是像指针一样的类型,但也有可能是指针,也有可能不是指针。
string
迭代器的语法形式:
// iterator是string类的内置类型
// it是变量名
string::iterator it = xxx;
5.2 常见的string类迭代器
5.2.1 begin
【文档描述】
5.2.2 end
【文档描述】
5.2.3 rbegin + rend — 反向迭代器
【文档描述】
注:如果觉得
string::reverse_iterator
太长,可以使用auto
代替。
5.2.4 const修饰的对象
注:
const
修饰的对象不能用普通迭代器
看看以下代码
#include <iostream>
#include <string>
using namespace std;
void print(const string& s)
{
string::iterator sit = s.begin();
while (sit != s.end())
{
cout << *sit;
sit++;
}
cout << endl;
}
int main()
{
string s1("hello world");
//封装print函数来打印
print(s1);
return 0;
}
【错误报告】
因为权限不能放大,因此,const
修饰的对象只能用const
的迭代器
【正确代码】
#include <iostream>
#include <string>
using namespace std;
void print(const string& s)
{
string::const_iterator sit = s.begin();
while (sit != s.end())
{
cout << *sit;
sit++;
}
cout << endl;
}
int main()
{
string s1("hello world");
//封装print函数来打印
print(s1);
return 0;
}
【输出结果】
六、string类遍历操作
因为
string
底层是支持流提取>>
,用cout
就可以直接打印string
字符串的内容,但是打印的结果比较固定。因此以下三种方式既可以访问遍历,也可以对其内容修改打印。
6.1 string的底层重载operator[]
相当于数组下标的访问
当然还可以对字符串进行修改
以下是将字符串的内容都+1
注意:这里需要区分
string
和普通数组
s2[i]
的底层是调用s2.operator[](i)
函数
- 普通数组的底层是解引用操作
char ch1[] = "abcdef"; ch1[0];// 访问下标为0的元素
ch1[0]
的底层含义是:*(ch1 + 0)
6.2 迭代器遍历
当然也可以对字符串的内容进行修改
在这里就有的人想,迭代器的代码要写这么多,还不如用下标来访问。所以,迭代器的意义是什么呢? 让我们接着往下看
6.3 语法糖(范围for)
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1("hello world");
for (auto x : s1)
{
cout << x;
}
cout << endl;
return 0;
}
【输出结果】
范围for
同样支持修改
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1("hello world");
// 修改
for (auto& x : s1)
{
x++;
}
// 输出结果
for (auto x : s1)
{
cout << x;
}
cout << endl;
return 0;
}
【输出结果】
范围
for
虽然很香,但是有个致命的缺点:不能倒着遍历,只有反向迭代器可以倒着遍历。
6.4 补充:迭代器的意义
范围for又和迭代器有啥关系呢?迭代器的意义又是什么呢?
- 其实,范围
for
代码短,之所以是这么好用是因为:范围for的底层就是用迭代器实现的!!!
我们可以利用反汇编来看看代码底层:
范围for
的底层就是调用了begin
和end
。
- 迭代器提供了一种统一的方式访问和修改容器的数据
以下以vector
容器为例
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
// 尾插数据
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
// 迭代器
vector<int>::iterator vit = v.begin();
while (vit != v.end())
{
cout << *vit << ' ';
vit++;
}
cout << endl;
// 范围for
for (auto e : v)
{
cout << e << ' ';
}
cout << endl;
return 0;
}
【输出结果】
如果一个容器支持迭代器,那么它必定支持访问
for
,反之就不一定了。
这里再提一嘴,很多人认为下标访问是主流,但是使用下标访问的空间必须是连续的,所以当我拿出链表,阁下又该如何应对呢?因此迭代器是可以访问链表的。
- 迭代器可以和算法配合使用
这里给大家介绍一个浅浅介绍一个算法(后序会补充),-- sort
【文档描述】
【代码演示】
#include <vector>
#include <iostream>
#include <algorithm> // 算法库头文件
using namespace std;
int main()
{
vector<int> v;
// 尾插数据
v.push_back(10);
v.push_back(3);
v.push_back(2);
v.push_back(5);
// 迭代器
cout << "sort前:";
for (auto x : v)
{
cout << x << ' ';
}
cout << endl;
sort(v.begin(), v.end());
// 迭代器打印sort后的结果
cout << "sort后:";
vector<int>::iterator vit = v.begin();
while (vit != v.end())
{
cout << *vit << ' ';
vit++;
}
cout << endl;
return 0;
}
【程序结果】
七、string的读入与输出
7.1 getline - 输入
注意:cin
和scanf
读取到空格或者回车就不再往后读取了
而getline
可以读入空格
7.2 puts - 输出
因为
string
类重载了流插入<<
和流提取>>
,因此可以支持cin
和cout
的输入输出。除此之外还能用puts
来输出string
类的字符串(自带换行的)。注意:puts
和printf
只能打印内置类型的字符串,因此可以用c_str
转化为C语言的字符串
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1("hello world");
puts(s1.c_str());
return 0;
}
【输出结果】