当前位置: 首页 > backend >正文

【C++】string类(一)构造、重载、容量操作、访问与遍历(迭代器、范围for)、练习

文章目录

  • 一、string类介绍
  • 二、string构造
    • 1、常用3种构造(对应文档1、2、4)
    • 2、子字符串构造函数
    • 3、拷贝前n个构造
    • 4、填充构造
  • 三、operator[ ]重载
  • 四、string类对象的容量操作
    • 1、size、length
    • 2、max_size
    • 3、capacity
    • 4、reserver
    • 5、clear
    • 6、empty
    • 7、shrink_to_fit
  • 五、string类对象的访问及遍历(迭代器)
    • 1、正向迭代器iterator
    • 2、反向迭代器reverse_iterator
    • 3、const迭代器const_iterator
    • 4、const反向迭代器const_reverse_iterator
  • 六、string类对象的访问及遍历(auto和范围for)
    • 1、auto
    • 2、范围for
    • 3、结合使用
      • (1)遍历字符串
      • (2)遍历数组
  • 七、练习
    • 1、仅仅反转字母
    • 2、字符串中的第一个唯一字符
    • 3、字符串相加
      • 方法1:尾插,O(n)
      • 方法2:头插,O(N^2)
  • 八、谢谢观看!

一、string类介绍

以下讲解内容均围绕该文档:string介绍文档
string:管理字符串的类(其底层还是模板)
需要包头文件:< string >

#include <iostream>
#include <string>
using namespace std;
int main()
{return 0;
}

常用接口:
1、构造
2、[]重载
3、容量操作
4、访问与遍历
5、修改

二、string构造

在这里插入图片描述
string类的构造函数C++98中有以下7种,其中常用的有三种:无参构造,带参构造,拷贝构造。
在这里插入图片描述
注:string类重载了流插入、流提取,可以直接输入输出。

1、常用3种构造(对应文档1、2、4)

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1;//无参构造string s2("hello world");//带参构造string s3(s2);//拷贝构造//cin >> s1;//cout<<s2<<endl;string s4(s2,6,5);//从s2的下标为6的位置开始拷贝,拷贝5个字符存放到s4中。cout<<s4<<endl;//打印结果为worldreturn 0;
}

2、子字符串构造函数

在这里插入图片描述
用法介绍:
在这里插入图片描述
在这里插入图片描述
其中,npos为size_t的最大值。
在这里插入图片描述

int main()
{string s2("hello world");//4带参构造//用法1:string s4(s2,6,5);//从s2的下标为6的位置开始拷贝,拷贝5个字符存放到s4中。//用法2:string s5(s2,6,15);//复制的长度为15,越界了,但string会自动从下标6开始拷贝到字符串末尾//用法3:string s6(s2,6);//第三个参数len有缺省值npos,根据用法2,仍然是自动从下标6开始拷贝到字符串末尾cout<<s4<<endl;//打印结果为worldreturn 0;
}

3、拷贝前n个构造

在这里插入图片描述
在这里插入图片描述

拷贝字符串s的前n个字符,给该字符数组初始化。

int main()
{string s("hello world",5);//拷贝字符串的前5个字符,赋值给scout<<s<<endl;//结果为helloreturn 0;
}

4、填充构造

在这里插入图片描述
在这里插入图片描述
用n个字符c来填充,初始化该字符数组。

int main()
{string s(5,'a');//用5个'a'来初始化scout<<s<<endl;//结果为aaaaareturn 0;
}

三、operator[ ]重载

在这里插入图片描述
重载[ ]之后,我们可以直接通过[]来修改字符数组中的对应字符。能直接检查出来下标的越界。

int main()
{string s("hello world");s[0] = 'x';//s[15] 会越界报错cout<<s<<endl;//结果为xello worldreturn 0;
}

四、string类对象的容量操作

在这里插入图片描述

1、size、length

size和length的作用基本上没有区别,均为获取字符数组的长度
在这里插入图片描述
在这里插入图片描述

int main()
{string s("hello world");cout<<s.size()<<endl;//结果为11//或 cout<<s.length()<<endl;return 0;
}

2、max_size

获取最大长度,这个接口没啥意义。了解即可

3、capacity

获取空间总大小。编译器为str开了16(15+1)个空间,其中有一个为‘\0’,(capacity返回的容量大小不包含‘\0’)
在这里插入图片描述

4、reserver

为字符串预留空间(第一次开的空间大小会大于等于预留的空间)所开的空间中默认不包含‘\0’

提前开空间,提高效率

在这里插入图片描述
vs中开空间比预留的大:
在这里插入图片描述
情况分析:

reserve(n)
n < size
size < n < capacity
n > capacity

(以VS编译器为例)

void test01()
{string s("hello worldxxxxxxxxxxx");cout << "初始:" << endl;cout << "size:" << s.size() << endl;		//22cout << "capacity:" << s.capacity() << endl;//31cout << endl;cout << "n<size时:" << endl;s.reserve(10);//n=10cout << "size:" << s.size() << endl;		//22cout << "capacity:" << s.capacity() << endl;//31cout << endl;cout << "size<n<capacity时:" << endl;s.reserve(25);//n=25cout << "size:" << s.size() << endl;		//22cout << "capacity:" << s.capacity() << endl;//31cout << endl;cout << "n>capacity时:" << endl;s.reserve(100);//n=100cout << "size:" << s.size() << endl;		//22cout << "capacity:" << s.capacity() << endl;//111
}

在这里插入图片描述

由上可知,在VS编译器下,当n>capacity时,才会进行扩容,其它情况时,容量不变。
在g++下,其它情况时,容量会缩小至n

5、clear

清空有效字符,不会清除容量。
在这里插入图片描述

void test02()
{string s("hello world");cout << "size:" << s.size() << endl;cout << "capacity:" << s.capacity() << endl;s.clear();cout << "size:" << s.size() << endl;		cout << "capacity:" << s.capacity() << endl;
}

在这里插入图片描述

6、empty

检测字符串是否为空串,是返回true,不是返回false
在这里插入图片描述

7、shrink_to_fit

将多余的容量去除,缩小容量至size
在这里插入图片描述

五、string类对象的访问及遍历(迭代器)

迭代器分为正向迭代器和反向迭代器。
顾名思义,正向迭代器是正向地从首元素开始迭代。反向迭代器是反向地从末元素开始迭代。

简单来说,迭代器是像指针一样的东西,但又不是指针。所有的容器都可以用它来访问!
迭代器的指向范围是左闭右开
vector < int >::iterator 其中,vector为容器名
string相关迭代器:
在这里插入图片描述

1、正向迭代器iterator

begin、end为例:

在这里插入图片描述
返回第一个位置的迭代器
在这里插入图片描述
返回最后一个元素的下一个位置的迭代器

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");string::iterator it = s.begin();while (it != s.end()){cout << *it;++it;}cout << endl;return 0;
}

在这里插入图片描述

2、反向迭代器reverse_iterator

这里以rbegin、rend为例,写法:

#include <iostream>
#include <string>
using namespace std;
int main()
{string str("abcdefg");string::reverse_iterator rit = 	str.rbegin();while (rit != str.rend()){cout << *rit << " ";++rit;}return 0;
}

在这里插入图片描述

3、const迭代器const_iterator

特点:只读,不能修改
begin和end支持const类型(begin和end支持const和非const,而cbegin、cend只返回const迭代器)
在这里插入图片描述

const string str("abcdefg");
string::const_iterator cit = str.begin();
//或 auto cit = str.begin(); 使用auto自动推导类型
while(cit != str.end())
{cout<< *cit << " ";++cit;
}

4、const反向迭代器const_reverse_iterator

rbegin、rend支持const类型(crbegin、crend确定返回const迭代器)
在这里插入图片描述

const string str("abcdefg");
string::const_reverse_iterator rcit = str.rbegin();
//或 auto rcit = str.rbegin();  使用auto自动推导类型
while(rcit != str.rend())
{cout<< *rcit << " ";++rcit;
}

六、string类对象的访问及遍历(auto和范围for)

1、auto

  • 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得
  • 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
  • 在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
  • auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
  • auto不能直接用来声明数组

2、范围for

  • 对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。
  • for循环后的括号由冒号":"分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围自动迭代,自动取数据,自动判断结束
  • 范围for可以作用到数组容器对象上进行遍历
  • 范围for的底层很简单,容器遍历实际就是替换为迭代器。

所有的容器都支持迭代器,迭代器支持范围for,即所有的容器都支持范围for

3、结合使用

当我们需要遍历字符串时,使用auto和范围for非常方便:

(1)遍历字符串

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("hello world");//auto用来判断ch的类型,ch : s 是将s中的每一个元素存入ch中,然后通过cout打印每一个元素for (auto ch : s){cout << ch << " " ;}cout << endl;return 0;
}

在这里插入图片描述

(2)遍历数组

#include <iostream>
#include <string>
using namespace std;
int main()
{//遍历数组int arr[] = { 1,2,3,4,5,6,7,8,9 };for (auto e : arr){cout << e << " ";}return 0;
}

在这里插入图片描述

七、练习

1、仅仅反转字母

题目链接:仅仅反转字母
在这里插入图片描述

class Solution {
public://判断是否为字母bool isChar(char a){if((a>='a'&&a<= 'z')||(a>='A'&&a<='Z'))return true;elsereturn false;}string reverseOnlyLetters(string s) {//前后指针int left = 0,right=s.size()-1;while(left<right){while(left<right && !isChar(s[left]))left++;while(left<right && !isChar(s[right]))right--;swap(s[left++],s[right--]);}return s;}
};

2、字符串中的第一个唯一字符

题目链接:字符串中的第一个唯一字符
在这里插入图片描述

class Solution {
public:int firstUniqChar(string s) {//记录出现次数int count[26]={0};//遍历,统计次数for(auto ch : s){count[ch-'a']++;//相对位置的count值++}//返回下标for(int i=0;i<s.size();i++){//s[i]-'a'为该字符在count数组中的相对位置if(count[s[i]-'a']==1)return i;}return -1;//未找到}
};

3、字符串相加

题目链接:字符串相加
在这里插入图片描述

方法1:尾插,O(n)

在这里插入图片描述

reverse用法
reverse 封装在< algorithm >中,参数为begin()迭代器和end()迭代器,左闭右开
作用:将该字符串进行逆置

在这里插入图片描述

class Solution {
public:string addStrings(string num1, string num2) {int end1 = num1.size()-1,end2 = num2.size()-1;string str;//存放加完后的字符串//进位int next = 0;while(end1>=0 || end2>=0)//当两个字符串都结束时,才结束{int val1=end1>=0 ? num1[end1--]-'0' : 0; //当该字符串结束时,对应位 置为0,后进行相加int val2=end2>=0 ? num2[end2--]-'0' : 0;//和int ret = val1+val2+next;next = ret/10;//进位ret %= 10;//对应位应放的值//尾插str+=(ret+'0');}//处理最高位进位if(next==1)str+='1';//逆置reverse(str.begin(),str.end());return str;}
};

方法2:头插,O(N^2)

该方法的大致思路与尾插相似,只是结果插入str时进行的是头插,最终结果不必进行逆置

class Solution {
public:string addStrings(string num1, string num2) {int end1 = num1.size()-1,end2 = num2.size()-1;string str;//存放加完后的字符串//进位int next = 0;while(end1>=0 || end2>=0)//当两个字符串都结束时,才结束{int val1=end1>=0 ? num1[end1--]-'0' : 0; //当该字符串结束时,对应位 置为0,后进行相加int val2=end2>=0 ? num2[end2--]-'0' : 0;//和int ret = val1+val2+next;next = ret/10;//进位ret %= 10;//对应位应放的值//头插str.insert(str.begin(),ret+'0');}//处理最高位进位if(next==1)str.insert(str.begin(),'1');return str;}
};

在这里插入图片描述

八、谢谢观看!

http://www.xdnf.cn/news/5247.html

相关文章:

  • 计算机网络:WiFi路由器发射的电磁波在空气中的状态是什么样的?
  • 打工人TOP,截图工具天花板
  • 智能商品推荐系统技术路线图
  • RabbitMQ深入学习
  • Taccel:一个高性能的GPU加速视触觉机器人模拟平台
  • yum install 如何卸载
  • vue3的响应式设计原理
  • DHT11温湿度传感器
  • 05 mysql之DDL
  • 复习javascript
  • MindSpore框架学习项目-ResNet药物分类-模型评估
  • 前端EXCEL插件,智表ZCELL产品V3.0 版本发布,底层采用canvas全部重构,功能大幅扩展,性能极致提升,满足千万级单元格加载
  • git 忽略 打包文件
  • CSS弹性布局
  • 深入解析进程地址空间:从虚拟到物理的奇妙之旅
  • PySide6 GUI 学习笔记——常用类及控件使用方法(常用类字体QFont)
  • Linux基本指令(一)
  • HDFS 常用基础命令详解——快速上手分布式文件系统
  • [python] 类
  • AtCoder Beginner Contest 405(CD)
  • 问题及解决01-面板无法随着窗口的放大而放大
  • 互联网大厂Java求职面试:基于RAG的智能问答系统设计与实现-3
  • 游戏引擎学习第270天:生成可行走的点
  • 阿里云CDN的源站配置:权重的详解
  • AI安全之对抗样本攻击---FGSM实战脚本解析
  • C语言_程序的段
  • Lasso回归理论的起源
  • Python教程(四)——数据结构
  • 计算机网络:家庭路由器WiFi信号的发射和手机终端接收信号原理?
  • 智能时代下,水利安全员证如何引领行业变革?