C++语言·string类

发布于:2024-05-09 ⋅ 阅读:(24) ⋅ 点赞:(0)

1. 为什么有string类

        C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数(strcpy,strcat),但是这些库函数与字符串是分离开的,不太符合OOP(Object Oriented Programming面向对象编程)的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

        所以在C++中用string类统一管理字符串和其方法,简化编程。其实string并不是一个正经的STL库中的内容,它的出现比STL略早,内容也没有STL中的别的模块成熟。

2. 标准库中的string类

2.1 string类

        官网资料:string - C++ Reference

        string是一个管理char的类模板,是一个管理字符的顺序表,或者说是一个字符数组。

        该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作,容器就是指栈、队列这些写好了可以装数据的东西。

        在使用string类时,要包含它的头文件 <string> 

2.2 string类的常用接口说明

2.2.1 string类的常见构造

        官网资料:string::string - C++ Reference

        98版中有7种构造方案其中1、2、4是比较常用的。

        1号构造:就是默认构造,会构造一个长度为0的空字符串

        2号、4号构造:拷贝构造,只不过参数不同,一个是string类型,一个是C字符串

        3号构造:从pos位置拷贝len个字符去构造,如果字符串较短,就能拷几个就拷几个。npos是一个size_t类型的-1,也就是24亿多的一个数,用这样一个字符串不可能达到的长度作为len的缺省值,其意义就是在不传len参的时候拷贝到字符串结尾

        5号构造:将一个C字符串的前n个字符拷贝构造

        6号构造:用n个字符c构造

        7号构造:用另一个string类对象的迭代区间构造

                        

        可能有的同学已经发现了我上面打印string的时候用的是流插入 << 操作符,当然是因为这个string类中为了方便我们进行打印写了友元重载函数。

2.2.2 string类对象的容量操作

2.2.2.1 size 与 length 与 capacity

        size 返回字符串有效数据个数(有效字符长度),不包括 '\0'

        length 返回字符串有效字符长度,不包括 '\0'

        那为什么要设计两个功能一样的成员函数呢,实际上这就是设计上的失误,在之后我们学的各种容器中,都是只有size没有length,length的出现只是一个特例。为了保持一致,今后我们也只使用size

        capacity 返回该string的容量,或者说string总空间的大小,因为string类中存了不止字符串本身的内容,所以其实际长度一定不等于字符串长度

                

        不过不用担心string的容量不够,string会自己扩容的,换句话说,当这个capacity填满了,就会扩容到更大的capacity。

2.2.2.2 empty 与 clear

        clear 清空有效字符

        empty 检测字符串是否为空串,是空返回true,不是空返回false

                  

2.2.2.3 reserve 与 resize

        reserve是给string扩容的,直接改变capacity的大小,当我们知道一个string需要多大空间的时候就可以提前reserve,把这块空间开好。当然,reserve改变capacity的大小,因此也可以缩容,但是VS下不支持缩容操作。

        注意,reserve(保留)  reverse(逆转),这俩个函数要分清楚,逆转函数reverse是算法函数,其参数是两个迭代器,用来控制将容器中迭代器所划分出来的数据顺序反转,如果用在string身上的含义就是反转字符串。

        resize 将有效字符的个数改成n个,多出的空间用选定的字符c填充,如果不指定字符c,编译器就会自动补上默认字符 '\0'

        resize因为给字符串本身扩容了,所以它也会影响capacity

        如果用resize强制缩短字符串长度,会使多出的字符串删掉,但是不会影响capacity的大小                                

2.2.2.4 shrink_to_fit

        这个是正经的缩容接口,当我们把一个很长的字符串删除多次之后会出现很多空出来的空间,造成一定程度上的浪费,此时就用这个接口让 capacity 的大小更适应字符串长度 size

        但是不要频繁缩容,因为缩容的本质是将原本大空间中的东西拷贝到小空间中去,这个过程会造成时间上的消耗。

2.2.3 string类对象的访问及遍历操作

2.2.3.1 operator[]

        官网资料:https://legacy.cplusplus.com/reference/string/string/operator[]/

        经过对于操作符 [ ] 的重载,string类对象也可以像C字符串那样访问和操作,这种遍历方案明显简单于迭代器,但缺点就是不通用,链表和树中无法用这种方案遍历。

                

        我们看官网上对于这个运算符的重载声明:

        首先,返回值是一个引用,这是为了可以对字符串中提取出来的某个字符进行修改(第一行的声明)。

        第二,它重载了两个,一个是正常的,另一个带了const修饰,这是为了防止在使用 [ ] 操作一个const string类型的字符串时,用第一种重载就会出现权限放大的问题,所以用const修饰了this指针指向的内容,和重载函数的返回值。

 PS: 范围for遍历(C++11)

        说到遍历,我们前面还提过一种范围for的遍历方案,自动++,自动判断结束。

        范围for遍历所有容器都可以用,因为范围for的底层就是迭代器,但范围for每次拿出来的这个e还是s1中一次一次正在遍历的字符的拷贝,如果 auto& 加上引用之后就可以修改s1了。

                

2.2.3.2 at访问

        at访问与方括号[ ] 访问的区别在于,at越界会抛异常,而[ ]会断言。抛异常后面的章节会讲到,这个是可以更改的,但是断言报错就直接崩掉程序了。

2.2.3.3 begin end 与 迭代器 

        begin:任何容器中都是返回第一个数据位置的 iterator(迭代器)

        end:任何容器中都是返回最后一个有效数据下一个位置的 iterator(迭代器)

        iterator(迭代器):可以理解成一个类似指针的东西,由它来控制目前访问的是第几号数据。之前我们学过访问数组中的某号元素时,是用下标来控制,但是这种 下标引用操作符 [ ] 的使用是有限制的,只能作用于顺序表。但是迭代器就比较通用,可以作用于顺序表,也可以作用于链表或树。

        不同容器的迭代器的实现是不尽相同的,所以 iterator 存在于各个容器的类域中,所以使用时要带上类域,否则全局范围内是找不到这个迭代器的。

                        

        因为 \0 不属于有效字符,算是一种标志,所以end返回的迭代器指向的位置就是 \0 而不是 \0 的下一个位置。

        可以看到再使用迭代器的时候我们用 * 来修改迭代器指向的内容的,其实这里是重载了 * 操作符,使得迭代器用起来更像指针。其他容器也是这么用 * 修改迭代器内容的。

        如果 s1 是const修饰的只读字符串,那么迭代器就要写成与其匹配的只读迭代器 const_iterator 防止权限放大。

                        

2.2.3.4 rbegin rend 与 反向迭代器

        这个就是把正向迭代器的所有用法反过来而已

        rbegn:返回最后一个有效数据的迭代器

        rend:返回第一个有效数据的前一位置的迭代器

        reverse_iterator:反向迭代器,++向前走,反向迭代器也有const版本

                        

PS: 算法排序 sort

        讲到迭代器就要提及sort算法,它是用来给各种容器内的数据排序的,默认是从小到大

        官网资料:sort - C++ Reference

        使用 sort() 要包含头文件 <algorithm> (算法),因为sort要给各类容器排序所以它是用模板写的,传的参数就是容器的迭代器,用两个迭代器来画出一块 左闭右开 的区域,此时sort就会在这块区域中排序了

                                ​​​​​​​

2.2.4 string类对象的修改操作

2.2.4.1 push_back append 与 operator+=

        push_back: string::push_back - C++ Reference

        append: string::append - C++ Reference

        operator+=: string::operator+= - C++ Reference

        push_back() 一次只能在string类对象后面添加一个字符。append()可以添加字符串、另一个string的实例化、用下标圈出来或用迭代器圈出来的另一个string等等,总之构造时能实现的所有方案它都能实现,不过那个是构造,但append是添加。

        但是上面两种都很少使用,operator+=操作符重载多方便啊,可以添加字符,字符串,或另一个string对象。

                ​​​​​​​        

2.2.4.2 pop_back 与 erase

        pop_back: string::pop_back - C++ Reference

        erease: string::erase - C++ Reference

        pop_back还是一次只能尾删一个字符,不太好用,它存在的意义就是和其他容器保持一致。

        erease可以通过 下标 和 元素个数 来进行删除,也可以通过迭代器但是用的比较少,注意迭代区间永远是左闭右开

        ​​​​​​​        ​​​​​​​        

2.2.4.3 assign 重新赋值

        官网资料:string::assign - C++ Reference

        这个成员函数的功能就是将string对象中的原有内容都删掉然后放入新内容,参数用法和构造的用法完全一样,唯一的区别就是不能修改成空string,而构造可以构造空string。

        

2.2.4.4 insert 插入

        官网资料:string::insert - C++ Reference

        前面的 += 操作符重载为我们提供了给string实例尾插的方法,那么insert就提供了在string实例的任意位置插入的方法。

        pos位置,用来选择在哪个位置插入,iterator迭代器也可以选择插入的位置。插入的内容可以是 char* 这种以 \0 结尾的C语言风格的字符串,也可以是C++的string类。        

        唯一要注意的是要插入一个字符的时候,用 5 号重载,插入一个字符时要给 n 传参为1,表示要插入 1 个字符。不能像传字符串那样,丢一串字符串就完事了,不去给字符数量。

                        

2.2.4.5 replace 替换

        官网资料:string::replace - C++ Reference

        别看这玩意一大堆,其实就是让你指出string中的一块地方,可以把这块地方的内容替换成别的内容而已,只是给出的替换方案相当多。

        ​​​​​​​        ​​​​​​​        

2.2.5 string类的其他操作

2.2.5.1 c_str 获取字符串指针

        可能之后写代码的时候C和C++混用,但是C没有string类,所以我们就获取字符转的底层指针,用来写C的代码段。

2.2.5.2 find 与 substr

        官网资料:string::find - C++ Reference

        find接口的功能是从 pos 位置向后找字符 c ,返回该字符在字符串中的下标

        find接口一般与substr接口一起使用,用于取下来字符串中用分隔符分隔开的某串字符串

        官网资料:string::substr - C++ Reference

        substr接口从 pos 位置开始,向后截取 len 个字符,然后将其返回

        ​​​​​​​   

2.2.5.3 operator+

        之前的operator+=只能支持基础string在前,后面加上一个string、char*或char。

        但是operator+的出现满足了基础string可以在后

                        

2.2.5.3 getline

        官网资料:getline (string) - C++ Reference

        cin与scanf一样,遇到空格或者换行都会认为是结束标志,于是就停止提取了,那如何获取一句带有空格的一句话呢?

        在C的时候我们会使用到 fgets 那么在C++的话我们就会用到getlin,同时getline还允许我们自己设置提取结束符 delim

        ​​​​​​​        ​​​​​​​        

        可以看到getline不会像fgets那样从前向后覆盖字符串,而是先清空string再获取新字符串。

        

2.2.5.4 to_string 与 stoi

        官网资料:to_string - C++ Reference

        to_string可以将各种数值转化成string,其功能类似于C库中的 itoa

        官网资料:stoi - C++ Reference

        stoi可以将string转化成整形,其功能类似于C库中的 atoi


网站公告

今日签到

点亮在社区的每一天
去签到