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

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

前言&#xff1a;在日常的程序设计中&#xff0c;我们会经常使用到字符串。比如一个人的身份证号&#xff0c;家庭住址等&#xff0c;只能用字符串表示。在C语言中&#xff0c;我们经常使用字符数组来存储字符串&#xff0c;但是某些场景(比如插入&#xff0c;删除)下操作起来很…...

Android Bitmap详解(下)之图片缓存详解

前言&#xff1a; 之前有出过俩篇关于bitmap相关的讲解&#xff0c;分别是Bitmap详解(上)常用概念和常用API和Bitmap详解(中)之像素级操作&#xff0c;今天主要是来一个系统的总结。 认识Bitmap&#xff1a; Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像…...

020-从零搭建微服务-认证中心(九)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;https://gitee.com/csps/mingyue 源码地址&#xff08;前端&#xff09;&#xff1a;https://gitee.com/csps…...

孤注一掷中的黑客技术

最近孤注一掷电影很火&#xff0c;诈骗团伙的骗术实在厉害&#xff0c;就连电影中的黑客潘生都未能幸免。电影中的陆经理说&#xff1a;不是我们坏&#xff0c; 是他们贪。这句话我觉得有一部分是对的&#xff0c;诈骗分子抓住了人的本性贪婪&#xff0c;才使得被骗的人逐步走向…...

机器学习笔记 - PyTorch Image Models图像模型概览 (timm)

一、简述 PyTorch Image Models (timm)是一个用于最先进的图像分类的库,包含图像模型、优化器、调度器、增强等的集合;是比较热门的论文及代码库。 虽然越来越多的低代码和无代码解决方案可以轻松开始将深度学习应用于计算机视觉问题,但我们经常与希望寻求定制解决方案的客户…...

Java 实现证件照底图替换,Java 实现照片头像底图替换

效果图 这里前端用layui实现的案例截图 color底图颜色可以在网页上这样取色 new Color(34, 133, 255) 实现案例下载链接&#xff1a;https://download.csdn.net/download/weixin_43992507/88237432...

周易卦爻解读笔记——未济

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

AI 绘画Stable Diffusion 研究(十三)SD数字人制作工具SadTlaker使用教程

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

伦敦金走势图行情值得关注

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

机器学习之数据清洗

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

T599聚合物电容器:在汽车应用中提供更长的使用寿命的解决方案

自从电子技术被引入汽车工业以来&#xff0c;汽车的技术含量一直在提升。诸多技术被应用在汽车上&#xff0c;使汽车的形象更接近于轮子上的超级计算机。更多传感器、更强大的计算能力和电力被装载到汽车上&#xff0c;汽车应用中的电子产品数量正在迅速增长。随着电动汽车和自…...

学习ts(五)类

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

EasyImage简单图床 - 快速搭建私人图床云盘同时远程访问【无公网IP内网穿透】

憧憬blog主页 在强者的眼中&#xff0c;没有最好&#xff0c;只有更好。我们是移动开发领域的优质创作者&#xff0c;同时也是阿里云专家博主。 ✨ 关注我们的主页&#xff0c;探索iOS开发的无限可能&#xff01; &#x1f525;我们与您分享最新的技术洞察和实战经验&#xff0…...

从SVG到Canvas:选择最适合你的Web图形技术

SVG 和 Canvas 都是可以在 Web 浏览器中绘制图形的技术。 众所周知&#xff0c; icon 通常使用 svg&#xff08;如 iconfont&#xff09;&#xff0c;而交互式游戏采用 Canvas。二者具体的区别是什么&#xff1f;该如何选择&#xff1f; 声明式还是命令式&#xff1f;绘制的图形…...

基于 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文件为例&#xff0c;实现点击按钮下载文件&#xff0c;其中icon结构如下&#xff1a; const DownloadSvg (props) > {function download(downfile) {const tmpLink document.createElement("a");const objectUrl URL.createObjectURL(downfi…...

【STM32】FreeRTOS软件定时器学习

软件定时器 FreeRTOS提供了现成的软件定时器功能&#xff0c;可以一定程度上替代硬件定时器&#xff0c;但精度不高。 实验&#xff1a;创建一个任务&#xff0c;两个定时器&#xff0c;按键开启定时器&#xff0c;一个500ms打印一次&#xff0c;一个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

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

YOLO目标检测——动漫头像数据集下载分享

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

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...