本章目标
1.熟悉String类
2.熟悉各种String函数用法
3.能够熟练运用String类解决题目
一. String类的介绍
1.1 String类的由来
C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函
数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
oop思想: 指的是面向对象编程
C++中对于string的定义为:typedef basic_string string; 也就是说C++中的string类是一个泛型类,由模板而实例化的一个标准类,本质上不是一个标准数据类型。
至于我们为什么不直接用String标准数据类型而用类是因为一个叫做编码的东西
我们每个国家的语言不同 比如说英语使用26个英文字母基本就能表述所有的单词 但是对于中文的字符呢?是不是就要用其他编码方式啊(比如说utf-8)
1.2 String函数接口
常用函数如下
我们会讲解大部分重要的函数
二. String类读写
2.1 访问两种方式
我们这里有两种访问方式
下标访问
使用operator[]实现数组下标式的访问
但是在这之前 我们首先来看看这一段代码
string s1("hello world"); cout << s1.size() << endl;
这里第一行代码的意思是初始化构造一个string类 初始化赋值为 hello world
s1.size()是表示的s1字符串的大小(这里使用s1.length())
之后我们开始使用下标进行访问 代码表示如下
string s1("hello world"); //cout << s1.size() << endl; // s1.length() for (size_t i = 0; i < s1.size(); i++) { cout << s1[i] << ' '; }
这里其实等价于这一行代码
cout << s.operator[](i) << " ";
函数重载嘛
at访问
代码表示如下
for (size_t i = 0; i < s1.size(); i++) { cout << s1.at(i) << ' '; }
运行结果如下
两种访问方式的区别
唯一的区别就是报错的时候
下标访问报断言错误
at访问报异常
2.2 迭代器读写
正向迭代器
老规矩 我们先来看迭代器的语法
string::iterator it = s.begin();
我们首先写个String类名 后面跟上iterator(迭代器) 再后面加上一个it
等于号的右边写上对象的begin() 或者 end()
我们目前将它当作指针来看待 目前这个阶段这样子理解就好
使用方式如下
string s("hello world"); string::iterator it = s.begin(); while (it != s.end()) { cout << *it; it++; }
当然我们也可以来修改迭代器里面的内容
反向迭代器
我们先来看语法格式
string::reverse_iterator it = s.rbegin();
我们这里可以看到 其实变化的就是一个 reverse 还有最后的rbegin()
代码表示如下
string s("hello world"); string::reverse_iterator it = s.rbegin(); while (it != s.rend()) { cout << *it; it++; }
我们发现 这里是不是代码有很多啊 那么我们练习到之前的知识 是不是就能想起来一个auto关键字
那么我们试试行不行
所以这里是不是更能明确一点了 知识之间不是相互孤立的
const正向迭代器
相比于迭代器 其实这里的改变就是不能写了 只能读(权限缩小)
代码表示如下
int main() { const string s("hello world"); string::const_iterator it = s.begin(); while (it != s.end()) { cout << *it; it++; } return 0; }
这里肯定就不能修改啦 不然肯定会报错的
const反向迭代器
和正向迭代器一样 这里就不多解释了
代码跟运行图如下
int main() { const string s("hello world"); string::const_reverse_iterator it = s.rbegin(); while (it != s.rend()) { cout << *it; it++; } return 0; }
2.3 语法糖 范围for读写
这个我们也是在之前的auto语法里面讲过了 代码表示如下
string s("hello world"); for (auto x : s) { cout << x << ' '; }
那么我们想要修改呢?
是不是也讲过 直接使用他们的引用就可以了(不引用肯定是不可以的 因为这里只是一个简单的赋值)
三. String类的构造函数
构造函数几种重要的格式如下
这里只讲解三个重点构造函数
无参构造
代码表示如下
string s;
我们debug来看看是什么效果
这里就是一个空字符串了
有参构造
和无参构造差不多 代码表示如下
string s("hello world");
还是一样debug看看
这里可以发现 字符串的大小(size)变成了11 然后字符串里面的内容变成了 hello world
拷贝构造
代码表示如下
string s("hello world"); string s1(s);
还是一样 debug看看
s1也变成了hello world捏
四. String容量接口函数
还是一样捏 咱们挑重点的介绍
size
首先还是一样 上代码
cout << s.size();
我们输出之后可以发现大小是11
这里是不是有点眼熟 我们debug看到的size是不是也是11啊 所以说这里就是将debug的值返回而已
empty
这个也很简单 判断是否为空的
比如说我们创建两个字符串 一个为空 一个不为空试试看
这里表示的很清楚了
clear
这里的clear函数可以和empty联动一下
我们发现清除之后两个字符串就变成全空了
reserve
这个函数用于预先开空间 因为每当字符串长度大于容量的时候都会扩容
所以如果我们知道我们需要的空间是多少我们就可以使用这个函数了
我们可以发现 这里的空间变成了1007 (因为是按照1.5倍开空间的)
resize
我们这里使用resize可以改变size的大小 假如说我们size的大小大于字符串的size 后面就会以‘\0’结尾
假如我们resize的大小小于原来的大小 后面的字符就会截断