C++初阶——string(字符数组),跟C语言中的繁琐设计say goodbye

前言:在日常的程序设计中,我们会经常使用到字符串。比如一个人的身份证号,家庭住址等,只能用字符串表示。在C语言中,我们经常使用字符数组来存储字符串,但是某些场景(比如插入,删除)下操作起来很繁琐。在C++中,底层设计了一个string类,将经常使用的功能封装在其中,使用起来非常简单,便捷。
本文主要介绍string的使用方法和几个常用函数,最后再列举几个经典例题。
我们使用string时经常会用到它封装的函数,这里推荐一个网站:C++ Reference。函数忘了怎么使用时可以参考该网站。

目录

  • 一.介绍
  • 二.使用
    • 1.创建一个字符数组存储字符串hello world:
    • 2.截取部分字符串
    • 3.从键盘上输入
  • 三.常用重载运算符和函数
    • 1.+/+=
    • 2.size()
    • 3.capacity()
    • 4.reserve()
    • 5.[]运算符(遍历string)
    • 6.push_back()(尾部插入一个字符)
    • 7.append() (尾部插入一段字符串)
    • 8.insert() (头部插入)
  • 四.迭代器
    • 1.iterator 正向迭代器(重点)
    • 2.reverse_iterator 反向迭代器
    • 3.reverse函数(字符串逆置神器)
  • 五.例题
    • 1.字符串相加
    • 2.字符串最后一个单词长度

一.介绍

长话短说,不将它讲的太神秘:
string是用字符的顺序数组实现的类,用于管理字符数组。
我们平常怎么使用自定义的类,就怎么使用string。

二.使用

1.创建一个字符数组存储字符串hello world:

格式:string 对象("字符或字符串")
1.形如string str2("hello world"),实际上就是调用string类的构造函数初始化对象str2.
2.string类中有流提取流插入运算符重载,可以直接输出或者输出string类型数据。

//C语言
char str1[] = "hello world";
//C++
string str2("hello world"); //构造函数
string str3("#");  //单个字符
cout << str2 << endl; //string类中有流提取流插入运算符重载,可以直接输出或者输出string类型数据。

控制台输出如下:
在这里插入图片描述

2.截取部分字符串

string类对此也进行了设计:第一个参数为截取string对象,第二个为需要截取部分的起始下标,第三个参数为截取字符个数(单位是字节);
在这里插入图片描述

如下代码:想截取s1对象中的world给给s2,w的下标为6(第二个参数),world有5个字符(第三个参数)

int main()
{string s1("hello world");string s2(s1, 6, 5); //截取s1对象中的world给给s2cout << s2 << endl;
}

控制台输出如下,可以看到截取成功了:
在这里插入图片描述

3.从键盘上输入

这里就可以体现string的优点:
使用C语言,我们需要考虑给字符数组开多大的空间,而string不用我们考虑这点,我们只管输入,编译器会自动帮我们适配合适的空间。

int main()
{string s1; //实例化一个对象s1cin >> s1; // 输入cout << s1 << endl; //打印return 0;
}

如下:前两行为从键盘上输入的,后两行为打印的。
在这里插入图片描述

三.常用重载运算符和函数

string函数设计的接口,感兴趣的可以去文章开头给的网站看看。下面某些函数只给出常用的接口。

1.+/+=

单从这个题目,就能让你感受到string的魅力!

请看题目:从键盘上输入两个字符串,要求将后一个字符串拼接到前一个字符串后面,输出拼接后的前一个字符串。(字符串长度不超过50字节)
从C语言角度考虑:首先我们要开两个不小于50字节的字符数组,之后简单一点的就是使用strcat函数拼接。但是strcat函数长久不用我忘掉了呢,还要再去翻看笔记回忆。

C++string类对+运算符进行了重载,这个+的本质就是尾插

int main()
{string s1, s2;cin >> s1 >> s2;s1 = s1 + s2;  //s1,s2顺序不能颠倒//s1 += s2; //使用+=也可以cout << s1 << endl;return 0;
}

控制台输出如下:其中第一行为输入的s1,第二行为输入的s2,第三行为拼接后的s1
在这里插入图片描述

2.size()

返回string对象的有效字符长度(不包括\0),相当于C语言的strlen。

int main()
{string s1("hello world");cout << s1.size() << endl;return 0;
}

控制台输出如下:
在这里插入图片描述

3.capacity()

返回string对象的容量
我们知道string会自动扩容,而它当然不是一个一个字节阔的,它是按照一定倍率扩容。

int main()
{string s1("hello world");cout << "size:" << s1.size() << endl;cout << "capacity:" << s1.capacity() << endl;return 0;
}

控制台输出如下:可以看到有效字符大小为11字节,容量为15字节。
在这里插入图片描述

4.reserve()

reserve——保留(不要把它当成reverse(逆置))
功能:请求容量的变化
价值:如果确定大概需要开多大的空间,可以提前开好,减少扩容,提高效率。(扩容是有代价的,特别是异地扩容,需要拷贝旧空间的数据移到新空间)

int main()
{string s1("hello world");cout << "size:" << s1.size() << endl;cout << "原capacity:" << s1.capacity() << endl;s1.reserve(100);cout << "新capacity:" << s1.capacity() << endl;return 0;
}

控制台输出如下:
在这里插入图片描述

5.[]运算符(遍历string)

string类对[]运算符进行了重载,使得我们可以借助[]像访问数组一样访问string。对于解决一些与字符串有关的题很有帮助。

以遍历string为例:

int main()
{string s1("hello world");for (size_t i = 0; i < s1.size(); i++) //运用size()函数{cout << s1[i] << " ";  //下标访问}return 0;
}

控制台输出如下:
在这里插入图片描述

6.push_back()(尾部插入一个字符)

在string对象尾部插入一个字符

int main()
{string s1("hello world");s1.push_back('x');cout << s1 << endl;return 0;
}

控制台输出如下:
在这里插入图片描述

7.append() (尾部插入一段字符串)

形式:append(字符串/string对象)
实际上设计的有些冗余,插入的话我们直接用+=就行了,何必再使用append函数呢?

int main()
{string s1("hello world");string s2("!!!");s1.append("xxx");s1.append(s2);cout << s1 << endl;return 0;
}

控制台输出如下:
在这里插入图片描述

8.insert() (头部插入)

插入一个字符:
1.常规做法:s.insert(起始位置下标,插入个数,要插入字符)
2.迭代器做法:s.insert(s.begin(),要插入字符)

int main()
{string s1("hello world");string s2("hello world");string s3("hello world");s1.insert(1,1,'x'); // 在h后插入一个xs2.insert(1, 2, 'x'); // 在h后插入两个x s3.insert(s3.begin(), 'x'); // 头插x cout << "s1 = " << s1 << endl;  //hxello worldcout << "s2 = " << s2 << endl;  //hxxello worldcout << "s3 = " << s3 << endl;  //xhello worldreturn 0;
}

插入一段字符串:s.insert(起始位置下标,字符串)

int main()
{string s1("hello world");s1.insert(1,"xx");cout << s1 << endl; //hxxello worldreturn 0;
}

四.迭代器

1.iterator 正向迭代器(重点)

函数名作用(下面函数仅适用于正向迭代器!!!)
begin()返回string开头的地址
end()返回string最后一个有效字符的下一个位置的地址(一般都是\0

iterator是迭代器的意思,它封装在string类中(list,树等数据结构中都有迭代器),故而使用时要受string类域限制,要写成string::iterator形式。使用时可以将它想象成一个指针来理解。

借助迭代器遍历string:

int main()
{string s1("hello world");string::iterator str = s1.begin();//auto str = s1.begin(); 写成这样也可以,auto是类型指示符,可以根据begin推出正向迭代器while (str != s1.end())  {cout << *str << " ";++str;}cout << endl;return 0;
}

控制台输入如下:
在这里插入图片描述

在这里插入图片描述
上述代码借助begin()函数返回开始位置的迭代器,end()指向最后一个字符下一个位置(此处就是\0)。

问:可这样子不就是单纯的指针遍历吗,何必那么麻烦还使用迭代器?
答:迭代器的一个特点就是通用性,在vector,list,树等中都有迭代器。就以list举例,它是由一个一个的小结点组成的,物理空间中并不是连续的,使用结点指针++并不能找到它的下一个结点,但是像上述代码一样套上迭代器就可以遍历list。因此,迭代器遍历才是最主流的遍历方式。

2.reverse_iterator 反向迭代器

函数名作用(下面函数仅适用于反向迭代器!!!)
rbegin()返回string最后一个有效字符的下一个位置的地址(一般都是\0
rend()返回string开头的地址

顾名思义,跟正向迭代器相反,reverse_iterator是反正使用的。

借助反向迭代器倒着遍历string:

int main()
{string s1("hello world");string::reverse_iterator str = s1.rbegin();//auto str = s1.rbegin(); 写成这样也可以,auto是类型指示符,可以根据rbegin推出反向迭代器while (str != s1.rend()){cout << *str << " ";++str;}cout << endl;return 0;
}

控制台输入如下,可以看到它是倒着遍历的:
在这里插入图片描述

补:const迭代器:const_iterator const_reverse_iterator
总计共有4种迭代器。

3.reverse函数(字符串逆置神器)

传入迭代器区间: reverse(s.begin(),s.end());

int main()
{string s1("hello world");reverse(s1.begin(), s1.end()); //传入迭代器区间cout << s1 << endl;return 0;
}

控制台输出如下:
在这里插入图片描述

五.例题

1.字符串相加

点击链接

高精度,不能用整型或长整型直接相加。
运用string一位一位相加进位。

class Solution {
public:string s;string addStrings(string num1, string num2) {int end1 = num1.size()-1,end2 = num2.size()-1;int ret = 0,sum = 0;while(end1 >= 0 || end2 >= 0){int n1 = end1>=0?num1[end1]-'0':0;int n2 = end2>=0?num2[end2]-'0':0;sum = n1+n2+ret;ret = sum/10;s += sum%10+'0';--end1;--end2;}if(ret == 1)s += '1';reverse(s.begin(),s.end());return s;}
};

2.字符串最后一个单词长度

1.牛客要包头文件 < string >
2.rfind()若没找到,返回无符号的-1
3.string::npos == 无符号的-1
4.注意只有一个单词的情况

#include <iostream>
#include<string>
using namespace std;
int main()
{string s1;getline(cin,s1);size_t eblack = s1.rfind(' '); //倒着找第一个空格,没找到返回无符号的-1if(eblack != string::npos){cout << s1.size()-(1+eblack); //下标-1}else {cout << s1.size();}return 0;
}

文末BB:对哪里有问题的朋友,尽管在评论区留言,若哪里写的有问题,也欢迎朋友们在评论区指出,博主看到后会第一时间确定修改。最后,制作不易,如果对朋友们有帮助的话,希望能给博主点点赞和关注.
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/45331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git版本管理加合并笔记

1.创建空文件夹&#xff0c;右键Bash here打开 2.打开链接&#xff0c;点击克隆下载&#xff0c;复制SSH链接 3.输入git SSH链接 回车 遇到问题&#xff1a; 但明明我已经有权限了&#xff0c; 还是蹦出个这 4.换成https在桌面上进行克隆仓库就正常了 5.去vscode里改东西 …

删除远程桌面的下拉框ip地址

原因&#xff1a; 如下图&#xff0c;有时候想清理掉无法连接的IP。 方法&#xff1a; 一、进入 注册表编辑器 进入方法&#xff1a;一下两个方法都可以使用。 1. 在win10里面直接搜索 注册表编辑器&#xff0c;然后打开 2. 打开 运行&#xff08;Win R&#xff09;&#xff…

文件同步工具rsync

文章目录 作用特性安装命令服务端启动增加安全认证及免密登录 实时推送源服务器配置结合inotify实现实时推送 参数详解 学些过程中遇到的问题 作用 rsync是linux系统下的数据镜像备份工具。使用快速增量备份工具Remote Sync可以远程同步&#xff0c;支持本地复制&#xff0c;或…

在SpringBoot中添加拦截器忽略请求URL当中的指定字符串

1 自定义拦截器 Component public class GlobalInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String path request.getRequestURI();if (pa…

蛊卦-拨乱反正

目录 前言 卦辞 爻辞 总结 前言 题外话&#xff0c;今天占卜时&#xff0c;看错了&#xff0c;以为占到了蛊卦&#xff08;后续会对自己的占卦经历进行补充&#xff0c;不断完善这个易经学习的专栏&#xff09;&#xff0c;那顺便就学习一下蛊卦&#xff0c;蛊惑人心&#…

OkHttp 源码浅析一

演进之路:原生Android框架不好用 ---- HttpUrlConnect 和 Apache HTTPClient 第一版 底层使用HTTPURLConnect 第二版 Square构建 从Android4.4开始 基本使用: val okhttp OkHttpClient()val request Request.Builder().url("http://www.baidu.com").buil…

axios使用axiosSource.cancel取消请求后怎么恢复请求,axios取消请求和恢复请求实现

在前端做大文件分片上传&#xff0c;或者其它中断请求时&#xff0c;需要暂停或重新请求&#xff0c;比如这里大文件上传时&#xff0c;可能会需要暂停、继续上传&#xff0c;如下GIF演示&#xff1a; 这里不详细说文件上传的处理和切片细节&#xff0c;后续有时间在出一篇&a…

ubuntu22.04 找不到串口,串口ttyusb时断时续的问题(拔插以后能检测到,过会儿就检测不到了)

1. 问题描述 ubuntu22.04的PC&#xff0c;在连接USB串口的时候&#xff0c;有时能找到ttyUSB0,有时找不到&#xff0c;如下&#xff1a; base) airsairs-Precision-3630-Tower:~$ ls -l /dev/ttyUSB* crwxrwxrwx 1 root dialout 188, 0 Aug 17 16:36 /dev/ttyUSB0 (base) air…

【JS基础】一些个人积累的原生JS编码设计思想,和大家一起开拓下思维

文章目录 前言对象配置链式调用队列调用并发执行未完待续 前言 以下都是我个人遇到的前端JS原生编码设计上的一些案例记录&#xff0c;希望能帮助新手开拓写代码的思想&#xff0c;并且能够结合自己的想法应用在实际的项目中&#xff0c;写出更加易读&#xff0c;拓展&#xf…

2023国赛数学建模B题思路模型代码 高教社杯

本次比赛我们将会全程更新思路模型及代码&#xff0c;大家查看文末名片获取 之前国赛相关的资料和助攻可以查看 2022数学建模国赛C题思路分析_2022国赛c题matlab_UST数模社_的博客-CSDN博客 2022国赛数学建模A题B题C题D题资料思路汇总 高教社杯_2022国赛c题matlab_UST数模社…

解决“topk_cpu“ not implemented for ‘Half‘

一、问题描述 如题报错&#xff1a;“topk_cpu” not implemented for ‘Half’ 是在使用transformers库时本地导入某个模型&#xff0c;完整报错如下&#xff1a; File "/Users/guomiansheng/anaconda3/envs/ep1/lib/python3.8/site-packages/torch/utils/_contextlib.p…

安卓监听端口接收消息

文章目录 其他文章监听端口接收消息 建立新线程完整代码 其他文章 下面是我的另一篇文章&#xff0c;是在电脑上发送数据&#xff0c;配合本篇文章&#xff0c;可以实现电脑与手机的局域网通讯。直接复制粘贴就能行&#xff0c;非常滴好用。 点击连接 另外&#xff0c;如果你不…

AI 绘画Stable Diffusion 研究(十二)SD数字人制作工具SadTlaker插件安装教程

免责声明: 本案例所用安装包免费提供&#xff0c;无任何盈利目的。 大家好&#xff0c;我是风雨无阻。 想必大家经常看到&#xff0c;无论是在产品营销还是品牌推广时&#xff0c;很多人经常以数字人的方式来为自己创造财富。而市面上的数字人收费都比较昂贵&#xff0c;少则几…

使用yolov5进行安全帽检测填坑指南

参考项目 c​​​​​​​​​​​​​​GitHub - PeterH0323/Smart_Construction: Base on YOLOv5 Head Person Helmet Detection on Construction Sites&#xff0c;基于目标检测工地安全帽和禁入危险区域识别系统&#xff0c;&#x1f680;&#x1f606;附 YOLOv5 训练自己的…

Opencv 视频的读取与写入

目录 前言 通过路径获取视频内容 获取视频内容 检查是否正确打开 循环播放 完整代码 从摄像头读取视频数据 获取视频设备 其他与直接读取视频一致 完整实例 录制视频 用于创建视频编解码器的四字符码&#xff08;FourCC&#xff09; cv2.VideoWriter() 将视频帧…

Spring MVC 中的常见注解的用法

目录 认识 Spring MVC什么是 Spring MVCMVC 的定义 Spring MVC 注解的运用1. Spring MVC 的连接RequestMapping 注解 2. 获取参数获取单个参数获取多个参数传递对象表单传参后端参数重命名RequestBody 接收 JSON 对象PathVariable 获取 URL 中的参数上传文件 RequestPart获取 C…

C++系列-内存模型

内存模型 内存模型四个区代码区全局区栈区堆区内存开辟和释放在堆区开辟数组 内存模型四个区 不同区域存放的数据生命周期是不同的&#xff0c;更为灵活。 代码区&#xff1a;存放函数体的二进制代码&#xff0c;操作系统管理。全局区&#xff1a;存放全局变量&#xff0c;常…

AutoSAR配置与实践(基础篇)2.5 RTE对数据一致性的管理

传送门 点击返回 ->AUTOSAR配置与实践总目录 AutoSAR配置与实践&#xff08;基础篇&#xff09;2.5 RTE对数据一致性的管理 一、 数据一致性问题引入二、 数据一致性的管理2.1 RTE管理 (SWC间)2.2 中断保护 (SWC内)2.3 变量保护IRVS (SWC内)2.4 Task分配2.5 任务抢占控制 一…

【linux】kernel编译时相关报错

文章目录 1. 问题现象及解决方式1. cc1: error: code model kernel does not support PIC mode 1. 问题现象及解决方式 1. cc1: error: code model kernel does not support PIC mode 问题&#xff1a;编译module时报错 原因&#xff1a;未指定交叉编译器&#xff0c;导致默认…

44、TCP报文(二)

接上节内容&#xff0c;本节我们继续TCP报文首部字段含义的学习。上节为止我们学习到“数据偏移”和“保留”字段。接下来我们学习后面的一些字段&#xff08;暂不包含“检验和”的计算方法和选项字段&#xff09;。 TCP首部结构&#xff08;续&#xff09; “数据偏移”和“保…