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;或…

蛊卦-拨乱反正

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

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

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

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

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

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 训练自己的…

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 任务抢占控制 一…

44、TCP报文(二)

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

525. 连续数组

525. 连续数组 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 525. 连续数组 https://leetcode.cn/problems/contiguous-array/description/ 完成情况&#xff1a; 解题思路&#xff1a; 参考代码&#xff1a; …

解放数据库,实时数据同步利器:Alibaba Canal

文章首发地址 Canal是一个开源的数据库增量订阅&消费组件&#xff0c;主要用于实时数据同步和数据订阅的场景&#xff0c;特别适用于构建分布式系统、数据仓库、缓存更新等应用。它支持MySQL、阿里云RDS等主流数据库&#xff0c;能够实时捕获数据库的增删改操作&#xff…

JVM——垃圾回收(垃圾回收算法+分代垃圾回收+垃圾回收器)

1.如何判断对象可以回收 1.1引用计数法 只要一个对象被其他对象所引用&#xff0c;就要让该对象的技术加1&#xff0c;某个对象不再引用其&#xff0c;则让它计数减1。当计数变为0时就可以作为垃圾被回收。 有一个弊端叫做循环引用&#xff0c;两个的引用计数都是1&#xff…

如何用树莓派Pico针对IoT编程?

目录 一、Raspberry Pi Pico 系列和功能 二、Raspberry Pi Pico 的替代方案 三、对 Raspberry Pi Pico 进行编程 硬件 软件 第 1 步&#xff1a;连接计算机 第 2 步&#xff1a;在 Pico 上安装 MicroPython 第 3 步&#xff1a;为 Thonny 设置解释器 第 4 步&#xff…

【ARM-Linux】项目,语音刷抖音项目

文章目录 所需器材装备操作SU-03T语音模块配置代码&#xff08;没有用wiring库&#xff0c;自己实现串口通信&#xff09;结束 所需器材 可以百度了解以下器材 orangepi-zero2全志开发板 su-03T语音识别模块 USB-TTL模块 一个安卓手机 一根可以传输的数据线 装备操作 安…

高项4.项目管理核心技术.

第一部分 项目管理概论 价值驱动的项目管理知识体系: 十二项原则;生命周期四个阶段;五个过程组;十大PM知识领域;八大绩效域;外加价值交付系统; 自1987 年以来, PMBOK 一直是基于过程的项目管理标准的重要代表,项目管理从业者一 直坚持基于过程的项目管理方法。随着…

2023-8-20 单链表

题目链接&#xff1a;单链表 #include <iostream>using namespace std;const int N 100010;int head, e[N], ne[N], idx;void init() {head -1;idx 0; }// 将x插入到头结点 void add_to_head(int x) {e[idx] x;ne[idx] head;head idx;idx; }// 将x插入到下标k后面…

VGG分类实战:猫狗分类

关于数据集 数据集选择的是Kaggle上的Cat and Dog&#xff0c;猫狗图片数量上达到了上万张。你可以通过这里进入Kaggle下载数据集Cat and Dog | Kaggle。 在我的Github仓库当中也放了猫狗图片各666张。 VGG网络 VGG的主要特点是使用了一系列具有相同尺寸 3x3 大小的卷积核进…