手把手教你C++——string(上)
1.为什么学习string类
文章目录
- 1.为什么学习string类
- 1.3 C语言中的字符串
- 2. 标准库中的string类
- 2.1 string类的了解
- 2.2 string类的常用接口说明
- 2.3 auto和范围for
- 2.3.1 auto关键字:
- 2.3.2 范围for
1.3 C语言中的字符串
C语言中,字符串是以‘\0’结尾的一些字符的集合,为了方便操作,C标准库中提供了一系列str的库函数,但是由于这些库函数和字符串是分开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不注意可能还会造成越界访问
2. 标准库中的string类
2.1 string类的了解
string类的文档介绍
在使用string类时一定要包含头文件#include 和using namespace std;
2.2 string类的常用接口说明
这里就可以看出string的一些优势,对比C来说,C++不需要考虑字符串的大小等因素,因为对于C语言来说数据和函数时分开作用的,但是对于C++来说并不是,这样更方便使用
- string
- operator
- operator[ ]
这里两个函数一个是加了const的一个是不加const,之所以要写两个的原因是普通字符是可读可写的,但是加了const之后就是只能读不能写。如果传过来的是加了const的字符那就必须得用用const修饰的函数,写成两个也是让字符能按照自己的情况找到符合的类型
这个操作符在C++中使用是很方便的,使用的场景也是比较多的
虽然这些功能看似数组也是可以实现的,但是数组有很多功能是无法直接实现的,必须要用特定的函数来实现,但string就方便很多。而且C语言的数组对于越界问题检查能力是比较弱的,但是像string一旦越界就会报错,可以让我们及时的修正错误
当然也可以实现遍历并且更改原数据的作用
- 诸如此类的还有max_size、capacity等
length的用处跟size其实是一样的,而且是比size要早的,之所以后来又有size是为了适配一些length形容起来不太适配的场景。之所以留下length是因为要向前兼容 - 小试牛刀
那我们现在就来做几道题目看看
仅仅反转字母 - 这道反转字符的题目首先就是判断该字符到底是不是字母,如果是则前后发生反转,如果不是那就跳过再继续判断
- 找字符串中第一个只出现一次的字符
- 这道题的核心在于先统计每个字母出现的次数,然后再判断该字母是不是只出现了一遍,如果是则返回其下标,如果不是则返回-1
- 遍历的方式不止for循环一种,用迭代器也是可以遍历的
这里之所以有const和非const两个版本的原因是:加了const时就是可读不可写,数值是不能被改变的,不加const时可读也可写,数值是可以更改的
也可以从后往前遍历
其实迭代器的使用面远不止于此,像我们之前做过的反转字符的题目等这些都可以用迭代器更加高效的完成,因为迭代器对于各种类型都是支持的,而且会支持运算符重载中的++等
- 为什么明明有了for循环还要用迭代器遍历呢?其实迭代器才是主流的用法,而且适用于各种类型的遍历,比如说链表、二叉树,这些是for循环无法完成遍历的,但是迭代器可以,像上代码中其实it++并不是简单的++而是运算符重载其实是operator++;这样就会按照不同的类型来完成遍历从而适用于各种类型
- 还有一种更加简洁的遍历方式就是auto遍历,其底层还是依靠迭代器。
再来看这一组
- push_back为插入一个字符
- push_back为插入一个字符
- append
- append
- operator+=
- operator+=
- insert
- insert
- erase
- erase
- replace
- replace
- swap
- swap
- pop_back
- pop_back
在一部分我们就来看一下reserve和resize的区别,二者相同之处是都是用来预留空间的,这样会比扩容效率更加高一点,当然也有不同之处
- reserve
- reserve
reserve只对空间预留,但是对于空间是否过剩时要缩减这种问题并没有给出详细的答案,但是resize给出了定义
- resize
- resize
那我们再来看道题目
验证一个字符串是否是回文
字符串相加
我们知道头插损耗是比较大的,那我们就可以换一种方式,让效率更高
2.3 auto和范围for
2.3.1 auto关键字:
在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。在C++11中,标准委员会变废为宝赋予了auto新的含义即:auto不再是一个存储类型的指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。
用auto声明指针类型时,用auto和auto*是没有任何区别的,单用auto声明引用类型是必须要加&
当在一行声明多个变量时这些变量必须是统一类型否则编译器就会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
auto不能作为函数的参数,可以做返回值,但是也建议谨慎使用(这里是C++11时不能够作为参数,在后面的版本中就可以)
auto做返回值谨慎使用的原因是如果用auto来做返回值,如果不写注释,别人看你的代码可能就不知道你返回的到底是什么auto不能直接用来声明数组
2.3.2 范围for
- 对于一个有范围的集合而言,由程序员来说明程序员的范围是多余的,有时候还会容易犯错误。因此C++111中引入了基于范围的for循环。for循环后的括号由冒号“:”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。
- 范围for可以作用到数组和容器对象上进行遍历
- 范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到
在C++中遍历数组(只要版本在C++11以上),也是支持用auto来遍历的