string(入门)

一. 为什么学习string类?

        

1.1 C语言中的字符串

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



二. 标准库中的string

        使用string类时,必须包含#include头文件以及using namespace std;

        2.1 auto关键字和范围for

        

auto 关键字
在这里补充 2 C++11 的小语法,方便我们后面的学习。
在早期 C/C++ auto 的含义是:使用 auto 修饰的变量,是具有自动存储器的局部变量,后来这个
不重要了。 C++11 中,标准委员会变废为宝赋予了 auto 全新的含义即: auto 不再是一个存储类型
指示符,而是作为一个新的类型指示符来指示编译器, auto 声明的变量必须由编译器在编译时期
推导而得
auto 声明指针类型时,用 auto auto* 没有任何区别,但用 auto 声明引用类型时则必须加 &
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际
只对第一个类型进行推导,然后用推导出来的类型定义其他变量
auto 不能作为函数的参数,可以做返回值,但是建议谨慎使用
auto 不能直接用来声明数组
        
        这里的auto关键字会根据后面的变量类型自动推出类型,不用我们手动来写类型。
        
        如上图的代码,我们的d是通过返回值来确定类型的,证明也是可以通过返回值来确定类型的。
         auto auto*的区别
        这两个基本没啥区别,就是我们的第一个auto右边可以是任意类型,而auto*的右边只能是地址。
        表示引用的话,必须在auto后面加上&。
        
        我们在同一行定义的时候,必须是两个变量是同一个类型,要不然就会报错了。
        
        它也无法通过数组来推出类型。
        
        auto在一些比较新的编译器上是可以作为定义参数的,但是大部分是不行的,虽然不能作为参数但是可以作为返回值,如图func3。
        
        这是我们范围for的使用,我们来看一下。
        第一个for循环就是我们常用的打印数组的形式,但是我们都知道,我们只需要打印的话,这样做还是有点麻烦的,接下来就可以使用我们的范围for了,就是图中的第二个循环,如果我们可以确定类型的话,我们可以直接将auto换成对应的类型也是可以的,可以理解为就是每次我们把数组中的元素从第一个开始依次给了e,然后打印e,直到结束。
        我想对原数组里面的数据都*2,怎么办呢?
        我们发现我们写的第三个循环我们通过第四个for循环打印出来的原数组的结果 是没有变的,这是因为没有成功原因就是我们这是拷贝,只是把数据拷贝给了e,改变的是e的值而不是原数组,所以我们该怎么办呢,这里我们就想到了引用和指针了。
        我们图中使用了引用,发现是可以达到预期的效果的。
        
        我们使用指针为什么就报错了呢?

        for (auto* e : a) 会出错,这是因为 a 是一个整数数组,并非指针数组。for (auto* e : a) 尝试把数组元素当成指针来处理,然而整数并不能隐式转换为指针,所以会产生编译错误。你可以直接使用范围 for 循环遍历数组元素,或者使用传统的 for 循环配合指针来遍历。

        因为我们每次返回的是数组中的值,我们这个数组只是一个简单的整数数组而非指针数组,所以没办法通过指针来接受,我们返回来给e的不是每个元素的地址,所以不能用。
        


2.2 string类的常用接口说明(注意下面我只讲解最常用的接口)

        2.2.1. string类对象的常见构造

        

        第一个就是无参构造,第二个就是通过给的一个字符串来构造我们的目标字符串的,第三个就是用几个那个字符来构造的字符串,第四个就是通过一个已经存在的对象拷贝给我们的目标字符串,我们来用一下吧。

        

        我们来看一下,第一个就是无参构造,s2是通过给定一个字符串来初始化自己,第三个就是通过拷贝构造来初始化,第四个就是通过5个c初始化s4.

        

        无参构造默认为/0,不打印。

        相信大家可能有疑问string(const char* s)和string(const string&s)有什么区别呢?

        第一个就相当于我们类的有一个参数的构造函数,而第二个就相当于是拷贝构造。

        再介绍几个常用的吧。

        我们看一下这个,s1表示是通过s3的第五个字符到第十个字符初始化自己。

        s2表示从s3的第六个到最后一个字符来初始化自己,这些都是很常用的。

        这是我们的运行结果。

2.2.2 string类对象的容量操作        

功能说明
size (重点)
返回字符串有效字符长度
length
返回字符串有效字符长度
capacity
返回空间总大小
empty (重点)
检测字符串释放为空串,是返回 true ,否则返回 false
clear (重点)
清空有效字符
reserve (重点)
为字符串预留空间 * *
resize (重点)
将有效字符的个数该成 n 个,多出的空间用字符 c 填充
  
        这里的size和length的作用一摸一样没区别,只是为了规范又写了一个size函数。

        reserve() 函数会让 std::vector 至少预留 new_cap 个元素的空间。若 new_cap 比当前的 capacity() 大,那么 std::vector 会重新分配内存,将容量扩充到至少 new_cap;若 new_cap 小于等于当前的 capacity(),则不会有任何操作。

注意:
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 不会改变容量大小。

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

        相信大家看到上面的代码可能会有疑惑,为什么字符串也可以用[]的运算符呢?

        这是因为底层实现了这个操作运算符的重载。

        

        大概的实现过程就如上图所示,底层还是指针的解引用操作实现了这个功能。

        在字符串中虽然最后是以/0结尾的,但是/0是不会影响字符串的大小的。

        const修饰的字符串也是不能修改的。

        

        修改就会报错了。

        下面我们将讲一个东西叫做迭代器,它是string类中的一个工具,很实用。

        

        通过类域找到迭代器,定义一个迭代器的对象,begin返回的是字符串的第一个字符的位置
    ,end返回的是最后一个字符的下一个位置。

        就是这个样子。

        

        我们刚才写了,s2是我们的const修饰的,我们要是还用普通的迭代器,就会出现权限被放大的情况了,因为你的s2.begin()返回的是const 类型的,而我们的迭代器接收的是非const类型的,权限被放大了,此时我们就要调用它对应的迭代器了。

        

        这就是我们const修饰string类型所使用的迭代器了。

        

        就是这个样子,它会优先调用最适合自己的函数,函数返回值加上const表示我们的返回值无法 被修改,函数后面加上const则表示

        

        如果我们想从后往前来遍历字符串,我们该怎么办呢?

        此时,迭代器就提供了一个很好的方法

        我们用上图的迭代器就可以实现了。

        为什么我们++,它会往前走呢?这里就用到了++运算符的重载了。

        

        我们发现上面的类型都是很长了,此时我们就可以使用auto关键字了,是非常简便的。

        



三.结束语

        感谢大家的查看,希望可以帮助到大家,做的不是太好还请见谅,其中有什么不懂的可以留言询问,我都会一一回答。  感谢大家的一键三连。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值