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.字符串最后一个单词长度
- 3.反转字符串中的单词 III
一.介绍
长话短说,不将它讲的太神秘:
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;
}
3.反转字符串中的单词 III
点击链接
运用迭代器reverse函数
class Solution {
public:string reverseWords(string s) {int i = 0,k = 0;while(s[i]!='\0'){if(s[i] == ' ') //找空格{reverse(s.begin()+k,s.begin()+i); //借助reverse反转单词k = i + 1;}i++;}reverse(s.begin()+k,s.end()); //反转仅有或仅剩一个单词的情况return s;}
};
文末BB:对哪里有问题的朋友,尽管在评论区留言,若哪里写的有问题,也欢迎朋友们在评论区指出,博主看到后会第一时间确定修改。最后,制作不易,如果对朋友们有帮助的话,希望能给博主点点赞和关注.
相关文章:

C++初阶——string(字符数组),跟C语言中的繁琐设计say goodbye
前言:在日常的程序设计中,我们会经常使用到字符串。比如一个人的身份证号,家庭住址等,只能用字符串表示。在C语言中,我们经常使用字符数组来存储字符串,但是某些场景(比如插入,删除)下操作起来很…...
Android Bitmap详解(下)之图片缓存详解
前言: 之前有出过俩篇关于bitmap相关的讲解,分别是Bitmap详解(上)常用概念和常用API和Bitmap详解(中)之像素级操作,今天主要是来一个系统的总结。 认识Bitmap: Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像…...
020-从零搭建微服务-认证中心(九)
写在最前 如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。 源码地址(后端):https://gitee.com/csps/mingyue 源码地址(前端):https://gitee.com/csps…...

孤注一掷中的黑客技术
最近孤注一掷电影很火,诈骗团伙的骗术实在厉害,就连电影中的黑客潘生都未能幸免。电影中的陆经理说:不是我们坏, 是他们贪。这句话我觉得有一部分是对的,诈骗分子抓住了人的本性贪婪,才使得被骗的人逐步走向…...
机器学习笔记 - PyTorch Image Models图像模型概览 (timm)
一、简述 PyTorch Image Models (timm)是一个用于最先进的图像分类的库,包含图像模型、优化器、调度器、增强等的集合;是比较热门的论文及代码库。 虽然越来越多的低代码和无代码解决方案可以轻松开始将深度学习应用于计算机视觉问题,但我们经常与希望寻求定制解决方案的客户…...

Java 实现证件照底图替换,Java 实现照片头像底图替换
效果图 这里前端用layui实现的案例截图 color底图颜色可以在网页上这样取色 new Color(34, 133, 255) 实现案例下载链接:https://download.csdn.net/download/weixin_43992507/88237432...

周易卦爻解读笔记——未济
第六十四卦未济 火水未济 离上坎下 未济卦由否卦所变,否卦六二与九五换位,象征尚未完成。 天地否 未济卦和既济卦既是错卦又是覆卦,这也是最后一卦,序卦传【物不可穷也,故受之以未济终焉】 未济卦象征尚未完成&…...

AI 绘画Stable Diffusion 研究(十三)SD数字人制作工具SadTlaker使用教程
免责声明: 本案例所用安装包免费提供,无任何盈利目的。 大家好,我是风雨无阻。 想必大家经常看到,无论是在产品营销还是品牌推广时,很多人经常以数字人的方式来为自己创造财富。而市面上的数字人收费都比较昂贵,少则几…...

伦敦金走势图行情值得关注
不知道大家是否了解过伦敦金这个投资品种,或者有否财经网站以及金融终端上看到过它的行情走势图。其实,伦敦金并不是一种实实在在的黄金,而是一种跟踪伦敦现货黄金市场价格走势的黄金保证金交易品种,它每天的行情走势变化…...

机器学习之数据清洗
一、介绍 数据清洗是机器学习中的一个重要步骤,它涉及对原始数据进行预处理和修复,以使数据适用于机器学习算法的训练和分析。数据清洗的目标是处理数据中的噪声、缺失值、异常值和不一致性等问题,以提高数据的质量和准确性。 二、方法 处理…...

T599聚合物电容器:在汽车应用中提供更长的使用寿命的解决方案
自从电子技术被引入汽车工业以来,汽车的技术含量一直在提升。诸多技术被应用在汽车上,使汽车的形象更接近于轮子上的超级计算机。更多传感器、更强大的计算能力和电力被装载到汽车上,汽车应用中的电子产品数量正在迅速增长。随着电动汽车和自…...

学习ts(五)类
定义 是面向对象程序设计(OOP)实现信息封装的基础 类是一种用户定义的引用数据类型,也称类类型 JavaScript的class,虽然本质是构造函数,但是使用起来已经方便了许多,js中没有加入修饰符和抽象类等特性 ts的class支持面…...

EasyImage简单图床 - 快速搭建私人图床云盘同时远程访问【无公网IP内网穿透】
憧憬blog主页 在强者的眼中,没有最好,只有更好。我们是移动开发领域的优质创作者,同时也是阿里云专家博主。 ✨ 关注我们的主页,探索iOS开发的无限可能! 🔥我们与您分享最新的技术洞察和实战经验࿰…...

从SVG到Canvas:选择最适合你的Web图形技术
SVG 和 Canvas 都是可以在 Web 浏览器中绘制图形的技术。 众所周知, icon 通常使用 svg(如 iconfont),而交互式游戏采用 Canvas。二者具体的区别是什么?该如何选择? 声明式还是命令式?绘制的图形…...
基于 Redis 实现分布式限流
基于 Redis 实现分布式限流 一、 简介二、分布式限流1 数据结构1.1 Redis List1.2 Redis Set1.3 Redis Sorted Set 2 实现分布式限流3 实现原理分析 三、分布式限流算法1. 计数器算法2. 漏斗算法3. 令牌桶算法 四、分布式限流实战1. 单机限流实现2. 基于Redis Clusters的分布式…...

前端下载文件方式(Blob)
以下以下载图标svg文件为例,实现点击按钮下载文件,其中icon结构如下: const DownloadSvg (props) > {function download(downfile) {const tmpLink document.createElement("a");const objectUrl URL.createObjectURL(downfi…...

【STM32】FreeRTOS软件定时器学习
软件定时器 FreeRTOS提供了现成的软件定时器功能,可以一定程度上替代硬件定时器,但精度不高。 实验:创建一个任务,两个定时器,按键开启定时器,一个500ms打印一次,一个1000ms打印一次。 实现&…...

【LeetCode】复写零
复写零 题目描述算法描述编程代码 链接: 复写零 题目描述 算法描述 编程代码 class Solution { public:void duplicateZeros(vector<int>& arr) {int n arr.size();int dest -1,cur 0;while(cur < n){if(arr[cur]){dest;}else{dest2;}cur;if(dest > n-1){…...

使用docker-maven-plugin插件构建镜像并推送至私服Harbor
前言 如下所示,建议使用 Dockerfile Maven 插件,但该插件也停止维护更新了。因此先暂时使用docker-maven-plugin插件。 一、开启Docker服务器的远程访问 1.1 开启2375远程访问 默认的dokcer是不支持远程访问的,需要加点配置,开…...

YOLO目标检测——动漫头像数据集下载分享
动漫头像数据集是用于研究和分析动漫头像相关问题的数据集,它包含了大量的动漫风格的头像图像。动漫头像是指以动漫风格绘制的虚构人物的头像图像,常见于动画、漫画、游戏等媒体。 数据集点击下载:YOLO动漫头像数据集50800图片.rar...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...