C++详解string(全面解析)

news2024/9/24 1:27:18

目录

string的概念: 

string的框架:

1、成员函数

 2、迭代器(Iterators)​编辑

 3、容量

4、元素访问

5、修改

6、非成员函数重载

string的构造和拷贝构造: 

 string的析构:

string的访问:

1、operator[]

2、iterator迭代器 

3、const_iterator

 4、反向迭代器

string的扩容机制

reserve函数

resize函数

string插入:

1、push_back

2、append

3、opeator+=

 4、replace

5、insert 

 6、erase

 7、replace

查找函数:

1、find()函数

 find_first_of函数​编辑

比较函数:

字符重载:


 

基于模板的出现,C++中就出现了各种模板类,而我们仅需要调用对应的模板类即可使用,十分的方便,今天我们来学习C++中第一个模板类——string

string的概念: 

 string类是一个字符顺序表。

string的框架:

1、成员函数

 2、迭代器(Iterators)

 3、容量

4、元素访问

5、修改

6、非成员函数重载

string的构造和拷贝构造: 

1、默认构造

2、拷贝构造

3、一部分拷贝构造(从pos位置开始,拷贝len长度,如果给的len超过当前位置后面到结尾的长度或者没有给len,那么就是从当前位置直接取到结尾)

npos:实际上是‘-1’,底层存的是补码,也就是42亿九千万,换句话说’-1‘代表不可能开出这么大的连续空间,所以npos代表取到字符串的结尾

4、字符串构造

5、字符串部分构造

6、用n个相同的字符’c'构造一个字符串

7、构造一个字符串的迭代器区间

#include<iostream>
#include<string>
using namespace std;
int main() {
	string s0("Hello world");
	string s1;
	string s2(s0);
	string s3(s2, 6, 5);
	string s4("Hello world Hello bit");
	string s5("Hello world Hello bit", 7);
	string s6(5, 'x');
	string s7(s0.begin(), s0.begin() + 6);
	cout << "s0:" << s0 << endl;
	cout << "s1:" << s1 << endl;
	cout << "s2:" << s2 << endl;
	cout << "s3:" << s3 << endl;
	cout << "s4:" << s4 << endl;
	cout << "s5:" << s5 << endl;
	cout << "s6:" << s6 << endl;
	cout << "s7:" << s7 << endl;
	return 0;
}

 string的析构:

一般自动调用,无需注意。

string的访问:

1、operator[]

 【】重载,在函数重载的那章见过,所以这里就不过多介绍,普通版本可读可写,const版本只读

#include<iostream>
#include<string>
using namespace std;
int main() {
	string s1("Hello world");
	
	//可读
	for (size_t i = 0; i < s1.size(); i++) {
		cout << s1[i] << " ";
		//等价于下面
		//cout << s4.operator[](i) << " ";
	}
	cout << endl;
	//可修改
	for (size_t i = 0; i < s1.size(); i++) {
		s1[i]++;
	}
	for (size_t i = 0; i < s1.size(); i++) {
		cout << s1[i] << " ";
	}
	cout << endl;

	return 0;
}

2、iterator迭代器 

类似于指针的作用,但不是真的指针。

#include<iostream>
#include<string>
using namespace std;
int main() {
	string s1("Hello world");

	string::iterator it = s1.begin();
	while (it != s1.end()) {
		cout << *it << " ";
		it++;
	}
	cout << endl;

	return 0;
}

同样迭代器也可以进行修改。  

#include<iostream>
#include<string>
using namespace std;
int main() {
	string s1("Hello world");

	string::iterator it = s1.begin();
	while (it != s1.end()) {
		*it -= 3;
		it++;
	}
	it = s1.begin();
	while (it != s1.end()) {
		cout << *it << " ";
		it++;
	}
	cout << endl;

	return 0;
}

那既然有下标+【】为什么还要弄一个iterator这么奇怪的东西,因为下标+【】这种形式只有string用起来方便,而iterator则可以适配多种类型。

而之前学习的范围for的底层也是iterator

3、const_iterator

#include<iostream>
#include<string>
using namespace std;
int main() {
	//普通string(可读可写)
	string s1("Hello world");
	//const_string(只读)
	const string s2("Hello world");
	//正常修改
	string::iterator it = s1.begin();
	while (it != s1.end()) {
		*it -= 3;
		it++;
	}
	//无法修改
	string::const_iterator it2 = s1.begin();
	while (it2 != s2.end()) {
		*it2 -= 3;
		it2++;
	}
	
	return 0;
}

 当用普通迭代器,可以看到我们可以正常修改,但const修饰后就无法进行修改了。

 4、反向迭代器

#include<iostream>
#include<string>
using namespace std;
int main() {
	string s1("Hello world");

	string::reverse_iterator rit = s1.rbegin();
	while (rit != s1.rend()) {
		cout << *rit << " ";
		++rit;	
	}
	cout << endl;

	return 0;
}

 包括还有const_reverse_iterator,根据规律也能看出是什么意思,不再过多赘述,所以总共有四种迭代器:普通迭代器,const迭代器,反向迭代器,const反向迭代器

string的扩容机制

#include<iostream>
#include<string>
using namespace std;
int main() {
	string s1("Hello world");

	cout << s1.size() << endl;
	cout << s1.length() << endl;
	cout << s1.capacity() << endl;
	cout << s1.max_size() << endl;

	return 0;
}

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

	string s;
	size_t sz = s.capacity();
	cout << "capacity change: " << sz << endl;
	cout << "making s grow: \n";
	for (int i = 0 ; i < 100; i++) {
		s.push_back('c');
		if (sz != s.capacity()) {
			sz = s.capacity();
			cout << "capacity change: " << sz << '\n';
		}
	}

	return 0;
}

我们看运行结果,我用的是vs2022编译器,首先会进行2倍扩容,然后后面是1.5倍扩容,但是每个编译器可能结果不相同.

reserve函数

假如我们知道需要的大小,我们还可以进行手动扩容:

手动扩容可以一次达到需要的容量,而且vs2022编译器实际上还会多扩一点,这比让编译器自己一次一次的扩容要节省时间。而且只有大于capacity的时候才会进行扩容.

resize函数

也可以进行手动扩容,并且可以进行初始化。

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

	string s("Hello worldxxx");
	cout << s.size() << endl;
	cout << s.capacity() << endl << endl;

	s.resize(10);
	cout << s.size() << endl;
	cout << s.capacity() << endl << endl;

	s.resize(20);
	cout << s.size() << endl;
	cout << s.capacity() << endl << endl;

	s.resize(30);
	cout << s.size() << endl;
	cout << s.capacity() << endl << endl;
	return 0;
}

 

string插入:

1、push_back

作用:可以尾插一个字符,类似于数据结构

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

	string s1("Hello world");
	s1.push_back('x');
	cout << s1 << endl;

	return 0;
}

2、append

作用:可以在string后面追加字符串,而且有多种功能,例如:追加一个字符串的一部分,多个相同的字符等等,我们举一两个代码例子看一下。

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

	string s1("Hello world");
	string s2("xxxxxx");
	//追加一个string类型的s2
	s1.append(s2);
	//追加一个字符串
	s1.append("aaaaaa");
	//追加多个字符
	s1.append(5, 'c');
	//追加一个字符串的一部分
	s1.append("yeahyeahyeah", 3, 6);
	//迭代器追加
	s1.append(s1.begin() + 2, s1.end());

	cout << s1 << endl;

	return 0;
}

3、opeator+=

作用:可以直接将string类型字符串、一般字符串、字符像赋值一样的+=在前一个string后,也是我们使用最频繁的,非常的好用。

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

	string s1("Hello world");
	string s2("xxxxxx");
	
	s1 += s2;
	cout << s1 << endl;

	s1 += ("abcdef");
	cout << s1 << endl;

	s1 += ('c');
	cout << s1 << endl;

	return 0;
}

 4、replace

作用是:用新的字符串覆盖到原本的字符上。

格式:有上面的六种,最常用的就是前两个。

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

	string s1("Hello world");
	string s2("This is a dog");
	//直接将s2替换给s1
	s1.assign(s2);
	cout << s1 << endl;
	//string& assign (const string& str, size_t subpos, size_t sublen);
	//从subpos位置开始,替换sublen个单位长度
	s1.assign(s2, 2, 5);
	cout << s1 << endl;

	return 0;
}

5、insert 

  作用:在某一个位置后面插入字符串。

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

	string s1("Hello world");
	string s2(" This is a dog");
	s1.insert(5, s2);
	cout << s1 << endl;

	return 0;
}

 6、erase

作用:删除字符串的一部分,如果是erase()则直接删除整个字符串。 

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

	string s1("Hello world");
	string s2(" This is a dog");
	s1.erase(2, 5);
    //删除整个字符串
	s2.erase();

	cout << s1 << endl;
	cout << s2 << endl;

	return 0;
}

 7、replace

作用:字符串的替换。 

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

	string s1("Hello world");
	string s2(" This is a dog ");
	//将s2的字符串替换到s1字符串位置5,长度3的空间中
	s1.replace(5, 3, s2);

	cout << s1 << endl;
	cout << s2 << endl;

	return 0;
}

查找函数:

1、find()函数

作用:查找字符或字符串,找到返回下标,没找到返回npos

查找字符:

string s1("ababbbaa");

cout << (s1.find('a')) << endl;//第二个参数为空,默认从0开始查找
cout << (s1.find('a',0)) << endl;//从0位置开始查找
cout << (s1.find('a',1)) << endl;//从1位置开始查找
cout << (s1.find('a',3)) << endl;//从3位置开始查找,前面的跳过
cout << (s1.find('c')) << endl;//未找到,返回4294967295,这是32位的-1,也是npos
cout << (s1.find('a',100)) << endl;//超出查找范围也是返回npos

查找字符串:

string s1("you are the apple of my eyes");
string s2("apple");

cout << s1.find(s2) << endl;//查找s2
cout << s1.find("are", 2) << endl;//从位置2开始查找"are"
cout << s1.find("myself", 5, 2) << endl;//从位置5开始查找"myself"的前两个"my"

rfind函数和find差不多,只不过方向改变了,rfind是从后往前查找,大家可以参照find自行学习。 

 find_first_of函数

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

	string s1("https://www.csdn.net/");
	size_t found = s1.find_first_of("aeiou");
	while (found != string::npos) {
		s1[found] = '*';
		found = s1.find_first_of("aeiou", found + 1);
	}
	cout << s1 << endl;

	return 0;
}

这里把s1里面的aeiou全部替换成*号。

find_last_of函数同find_first_of函数一样,只是查找方向不一样,也望大家自行学习。

比较函数:

字符重载:

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

	string s1("abdef");
	string s2("abcdef");
	//字符串比较规则,跟c一样,按照ASCII码大小,谁ASCII大谁就大
	cout << (s1 > s2) << endl;
	cout << (s1 < s2) << endl;
	return 0;
}

 返回值:bool类型,如果满足等式返回1,不满足返回0.

以上就是我对string的一些认识,如有问题望指正,感谢观看

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

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

相关文章

树模式数据表设计学习

引子&#xff1a; 场景&#xff1a;某读书网站&#xff0c;支持读者评论文章&#xff0c;并且对评论支持回复功能。设计的表如下&#xff1a; 问题点&#xff1a;你想获取一个评论下所有的评论信息&#xff1f; 将所有评论一次性取出、轮巡遍历&#xff0c;获取到所有数据。 …

几款可以让销售管理事倍功半的CRM软件推荐!

本文将盘点几款CRM软件&#xff0c;为企业选型提供参考&#xff01; 想象一下这样一个场景&#xff0c;一家企业的销售团队每天忙碌地跟进客户&#xff0c;却因为信息分散、管理混乱而效率低下。CRM 软件就如同一位得力助手&#xff0c;将客户信息有序整合&#xff0c;助力企业…

Unity核心实践小项目

要源码包的私信我。 简介 衔接Unity核心学习后的实操小项目 需求分析 准备工作 面板基类 为了能够控制一画布整体的透明度&#xff0c;所以需要给每个面板都添加一个 CanvasGroup组件 UI管理器 UGUI方面的参数设置 开始场景 场景搭建 直接用资源包搭建好的场景&#xff1a;…

VD1013 DFN小封装芯片 适用于小电流的输出的电池保护芯片

VD1013内置高精度电压检测电路和延迟电路以及内置MOSFET&#xff0c;是用于单节锂离子/锂聚合物可再充电电池的保护IC。 本IC适合于对1节锂离子/锂聚合物可再充电电池的过充电、过放电和过电流进行保护 。 VD1013具备如下特点: 高精度电压检测电路 过充电检测电压…

chfsgui局域网共享局域网http服务 Cute HTTp File Server软件

Cute HTTp File Server https://wwaz.lanzouv.com/iGHIj29srj0b 密码:eaq3

OpenHarmony鸿蒙( Beta5.0)智能窗户通风设备开发详解

鸿蒙开发往期必看&#xff1a; 一分钟了解”纯血版&#xff01;鸿蒙HarmonyOS Next应用开发&#xff01; “非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; “一杯冰美式的时间” 了解鸿蒙HarmonyOS Next应用开发路…

区块链积分系统:革新支付安全与用户体验的未来

在数字时代&#xff0c;确保交易过程中的安全性和风险控制变得至关重要。随着传统支付系统在处理大规模交易时面临的挑战&#xff0c;如繁琐的审核、严格的监管以及欺诈风险&#xff0c;这些问题不仅影响了交易效率&#xff0c;还可能给用户和企业带来经济损失。因此&#xff0…

【CanMV K230 AI视觉】 跌倒检测

【CanMV K230 AI视觉】 跌倒检测 跌倒检测 动态测试效果可以去下面网站自己看。 B站视频链接&#xff1a;已做成合集 抖音链接&#xff1a;已做成合集 跌倒检测 跌倒检测主要根据人体姿态来判断&#xff0c;可以用于老人、小孩跌倒监护。 实验名称&#xff1a;跌倒检测 实验…

基于单片机的电子药箱控制系统设计

本设计采用STM32F103C8T6单片机作为电子药箱的主控单元&#xff0c;组成模块包括时钟芯片DS1302、语音提醒模块WT588D、液晶显示模块LCD1602、红外避障传感器FC-51、电磁锁驱动电路和通信模块SIM800C。系统初始化结束&#xff0c;红外传感器检测药物的剩余情况并将信息上传到主…

虚拟机器配置固定IP地址

新安装的虚拟机&#xff0c;如何配置固定的ip地址&#xff0c;废话少说直接上干货 第一步&#xff1a;在VMarea中 选中你要固定IP的虚拟机器&#xff0c;点击上面的“编辑”按钮&#xff0c;然后找到“虚拟网络编辑器”&#xff0c;选中你要修改的ip VMnet8&#xff0c;然后是…

力扣题解2555

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述&#xff1a; 两个线段获得的最多奖品 在 X轴 上有一些奖品。给你一个整数数组 prizePositions &#xff0c;它按照 非递减 顺序排列&#xff0c;其中 prizePositions[i] 是第 i 件奖品的位…

01 Docker概念和部署

目录 1.1 Docker 概述 1.1.1 Docker 的优势 1.1.2 镜像 1.1.3 容器 1.1.4 仓库 1.2 安装 Docker 1.2.1 配置和安装依赖环境 1.3镜像操作 1.3.1 搜索镜像 1.3.2 获取镜像 1.3.3 查看镜像 1.3.4 给镜像重命名 1.3.5 存储&#xff0c;载入镜像和删除镜像 1.4 Doecker…

逆向基础一阶段检测-1

前言&#xff1a; 记录一下&#xff0c;最开始学习逆向时&#xff0c;rkvir所出的题目~&#xff08;当时不会&#xff09; 查壳。 32ida打开。 进入main函数&#xff1a; 对于这种情况&#xff0c;我们可以考虑直接在if cmp判断时&#xff0c;下断点去查看值&#xff0c;因为…

Unet改进31:添加Star_Block(2024最新改进方法)|紧凑的网络结构和高效的运算

本文内容:在不同位置添加Star_Block 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 最近的研究引起了人们对网络设计中尚未开发的“星型操作”(元素智能乘法)潜力的关注。虽然有很多直观的解释,但其应用背后的基本原理在很大程度上仍未被探索。我们的研…

论文学习笔记 VMamba: Visual State Space Model

概览 这篇论文的动机源于在计算机视觉领域设计计算高效的网络架构的持续需求。当前的视觉模型如卷积神经网络&#xff08;CNNs&#xff09;和视觉Transformer&#xff08;ViTs&#xff09;在处理大规模视觉任务时展现出良好的表现&#xff0c;但都存在各自的局限性。特别是&am…

ROS入门教程(八)—— 路径规划导航实战

通过Gazebo仿真和RViz仿真的学习后,本文将通过Gazebo与RViz联合仿真实现机器人在Gazebo仿真环境中运动,通过远距搜索与近距搜索实现机器人路径规划导航。 目录 前言 实现思路 仿真模型 仿真源码 前言 前面的ROS入门教程提供ROS仿真的基础步骤,本文提供了实现思路,仿真…

Java面试篇基础部分-Java中常用的I/O模型

阻塞I/O模型 阻塞式的I/O模型是一种非常常见的I/O模型机制,在进行数据读写操作的时候,客户端会发生阻塞等待。 工作流程如图所示,该用户线程一直阻塞,等待内存中的数据就绪;内存中的数据就绪之后,内核态的数据将拷贝到用户线程中,并且返回I/O的执行结果到用户线程。这个…

视觉检测中的深度学习应用

引言 视觉检测是计算机视觉的一个重要领域&#xff0c;涉及到对图像或视频流进行分析和理解。随着深度学习技术的迅猛发展&#xff0c;视觉检测领域发生了革命性的变化。深度学习通过使用复杂的神经网络模型&#xff0c;尤其是卷积神经网络&#xff08;CNNs&#xff09;&#…

一些硬件知识(二十一)

高侧开关应该选用P-MOS还是N-MOS呢&#xff1f; 高侧开关就是负载是接地的&#xff0c;开关相对于负载处于高电位&#xff0c;如下图所示。如果将开关和负载的位置互换&#xff0c;就是低侧开关。 P-MOS作为高侧开关的示意图如下图所示。要想P-MOS管导通&#xff0c;则VgsVg-V…

express框架(二)

中间件 什么是中间件 中间件&#xff08;Middleware&#xff09;本质是一个回调函数&#xff0c;中间件函数可以像路由回调一样访问请求对象&#xff08;request&#xff09;&#xff0c;响应对象&#xff08;response&#xff09;。 中间件的作用 使用函数封装公共操作&am…