C++【string类的使用】(上)

news2024/11/27 12:52:26

文章目录

  • 1. 为什么要学习string类
  • 2. 标准库的string类
    • 2.1 string的构造函数
      • (1)无参构造(重点)
      • (2)用字符串初始化(重点)
      • (3)用字符串的前n个字符初始化
      • (4)拷贝构造(重点)
      • (5)拷贝str的一部分
      • (6)拷贝n个字符
      • (7)用迭代器初始化
    • 2.2 string的访问及遍历
      • 1. operator[]
      • 2.Iterators(迭代器遍历)
        • 反向迭代器
      • 3. 范围for遍历
        • auto关键字
        • 范围for遍历
    • 2.3 string的容量操作
      • 1.size和length(size是重点)
      • 2. max_size
      • 3. capacity
      • 4. resize(重点)
      • 5. reserve(重点)
        • 补充
      • 6. clear
      • 7. empty
      • 8. shrink_to_fit
  • 结语

1. 为什么要学习string类

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。

2. 标准库的string类

string类的文档介绍
在这里插入图片描述
在使用string类时,必须包含#include头文件以及using namespace std;

2.1 string的构造函数

在这里插入图片描述

(1)无参构造(重点)

C++为了与C语言的<string.h>区分开,是不会加 .h 的(C++的头文件<string>

string();

无参构造的string内是没有元素的。

#include<iostream>
#include<string>

using namespace std;

void test_string_Construct()
{
	string s1;
	cout << s1 << endl;
}

在这里插入图片描述
注意:我们这里是使用的<<是string类实现的全局输出函数(string类还实现了>>输入函数)
在这里插入图片描述

(2)用字符串初始化(重点)

string (const char* s);

文档内容:
Copies the null-terminated character sequence (C-string) pointed by s.

将C字符串拷贝给对象。

string s2("Hello World");

在这里插入图片描述

(3)用字符串的前n个字符初始化

string (const char* s, size_t n);

拷贝C字符串的前n个字符到string类的对象

string s3("Hello World", 5);

在这里插入图片描述

(4)拷贝构造(重点)

string (const string& str);

一个str初始化一个新对象

	string s2("Hello World");
	string s4(s2);

在这里插入图片描述

(5)拷贝str的一部分

string (const string& str, size_t pos, size_t len = npos);

pos为拷贝的开始位置,len为拷贝的字符个数,npos是string的成员常量
在这里插入图片描述
代表如果没给拷贝的字符个数,默认拷贝到str的\0

没有给要拷贝的个数

	string s5(s2, 6);
	cout << s5 << endl;

在这里插入图片描述
给了拷贝的个数

	string s6(s2, 6, 3);
	cout << s6 << endl;

在这里插入图片描述

(6)拷贝n个字符

string (size_t n, char c);

用n个字符拷贝初始化str

	string s7(5, 'x');
	cout << s7 << endl;

在这里插入图片描述

(7)用迭代器初始化

template <class InputIterator>
  string  (InputIterator first, InputIterator last);

按相同顺序复制范围 [first,last] 内的字符序列。

	string s2("Hello World");
	string s8(s2.begin(), s2.end());
	cout << s8 << endl;

在这里插入图片描述

2.2 string的访问及遍历

1. operator[]

在这里插入图片描述
返回string类中第pos位置的引用,也支持const string类调用(但权限是只读)

	string s1("Hello World");
	//下标+[]遍历
	//普通对象
	for (int i = 0; i != s1.size(); i++)
	{
		s1[i] += 2;
		cout << s1[i] << ' ';
	}

	cout << endl;
	
	//const对象
	const string s2("Hello World");
	for (int i = 0; i != s1.size(); i++)
	{
		//s1[i] += 2;
		cout << s1[i] << ' ';
	}

在这里插入图片描述

const对象这样操作会报错(权限只有只读)
在这里插入图片描述

2.Iterators(迭代器遍历)

STL六大组件之一,这里只讲一些迭代器的用法,后期我们会详细讲解。
在这里插入图片描述

在这里插入图片描述
返回一个指向string第一个字符的迭代器

	string s1("Hello World");
	string::iterator sit = s1.begin();

分析下上面的代码,我们先突破了string类域,指定了iterator 定义了变量 sit,然后 sit 接收了来自s1.begin()的返回值,也就是指向第一个字符的位置。
从这里我们可以感觉到这个迭代器的功能特别像指针,但是!迭代器不一定是指针,因为迭代器不仅仅是数组类数据结构有,而是STL的数据结构都有迭代器的功能,像map结构,list结构他们都有迭代器,而且所有迭代器还支持++和解引用,这些迭代器都是重载过的,当然我们也可以把他当作指针用,因为它的用法和指针十分相似。
在这里插入图片描述
返回一个指向最后一个字符的迭代器('\0'
在这里插入图片描述

	//迭代器遍历
	string s1("Hello World");
	string::iterator sit = s1.begin();
	for (; sit != s1.end(); sit++)
	{
		cout << *sit << ' ';
	}
	cout << endl;

在这里插入图片描述
我们也可以使用迭代器对s1进行修改
在这里插入图片描述
如果你只希望迭代器进行“读”的操作,不进行“写”的操作,那就可以使用const迭代器
在这里插入图片描述
在这里插入图片描述
const迭代器,功能和迭代器一样,只是没有了“写”的权限,

	string::const_iterator cit = s1.begin();
	while (cit != s1.end())
	{
		cout << *cit << ' ';
		cit++;
		//(*cit)++;
	}
	cout << endl;

在这里插入图片描述

反向迭代器

顾名思义,迭代器的方向是反方向的,这也就证明了迭代器并不是指针,指针是无法通过++来往后走的。
在这里插入图片描述
在这里插入图片描述

Returns a reverse iterator pointing to the last character of the string (i.e., its reverse beginning).
返回一个反向迭代器,这个迭代器指向string的最后一个字符的前一个位置(最后是'\0'


Reverse iterators iterate backwards: increasing them moves them towards the beginning of the string.
反向迭代器向后迭代:增加迭代器会使其向字符串的开头移动。

在这里插入图片描述

Returns a reverse iterator pointing to the theoretical element preceding the first character of the string (which is considered its reverse end).
返回一个反向迭代器,指向字符串第一个字符(被视为其反向末端)之前的理论元素。


The range between string::rbegin and string::rend contains all the characters of the string (in reverse order).
rbegin和rend之间的顺序是相反的

这里还有最有一种迭代器,const反向迭代器,理解了前面的const迭代器和反向迭代器,就能知道该怎么用了,这里就不赘述了
在这里插入图片描述

补充:const迭代器都是C++11加入进来的。

3. 范围for遍历

C++11支持更简洁的范围for的新遍历方式

auto关键字

在这里补充2个C++11的小语法,方便我们后面的学习。

  • 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。(也就是自动推导类型)

就拿迭代器来说,我们如果要写一个反向迭代器,我们需要写
string::reverse_iterator rit = s1.rbegin();
但是如果我们用了auto,那就不用写那么长的代码
auto resit = s1.rbegin();

  • 用auto声明指针类型时,用auto和auto*没有任何区别但用auto声明引用类型时则必须加&
  • 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
  • auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
  • auto不能直接用来声明数组
范围for遍历

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。

范围for可以作用到数组和容器对象上进行遍历

范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

在这里插入图片描述

我们也可以不通过汇编来看(错误使用范围for的e)
在这里插入图片描述

2.3 string的容量操作

在这里插入图片描述

1.size和length(size是重点)

在这里插入图片描述
size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。

	string s1("hello worldxxxxxxx");

	//求元素个数
	cout << "size:" << s1.size() << endl;
	cout << "length:" << s1.length() << endl;

在这里插入图片描述

2. max_size

在这里插入图片描述

Returns the maximum length the string can reach.
返回string能到达的最大长度

	string s1("hello worldxxxxxxx");
	//返回string的最大长度
	cout << "max_size:" << s1.max_size() << endl;

32位环境下是21亿多
在这里插入图片描述
64位就更长的(达到了九十多亿万亿)
在这里插入图片描述

3. capacity

在这里插入图片描述

Returns the size of the storage space currently allocated for the string, expressed in terms of bytes.
返回当前空间所分配的大小(以字节为单位)

这个我们就很熟悉,也就不多讲解了

	string s1("hello worldxxxxxxx");
	//求容量大小
	cout << "capacity:" << s1.capacity() << endl;

在这里插入图片描述

4. resize(重点)

在这里插入图片描述

Resizes the string to a length of n characters.
将size修改到n


If n is smaller than the current string length, the current value is shortened to its first n character, removing the characters beyond the nth.
如果你给的n比原来的size小,那么会将当前值缩短为前 n 个字符,并删除 n 个字符之后的字符。


If n is greater than the current string length, the current content is extended by inserting at the end as many characters as needed to reach a size of n. If c is specified, the new elements are initialized as copies of c, otherwise, they are value-initialized characters (null characters).
如果你给的n比原来的size大且指定了字符c,新元素将被初始化为 c 的副本,否则,它们将是值初始化字符(空字符)。

	string s1("hello worldxxxxxxx");
	cout << endl << "改变内容个数:" << endl;
	//改变内容个数
	s1.resize(s1.size() - 5);	   //小于原本的size会删除string内部的元素(从后往前删)
	cout << s1 << endl;
	cout << "size:" << s1.size() << endl;
	cout << "capacity:" << s1.capacity() << endl << endl;//减少了size并不会减少capacity

	s1.resize(s1.size() + 5);	   //大于原本的size,会在多余的地方加入'/0'
	cout << s1 << endl;
	cout << "size:" << s1.size() << endl << endl;
	s1.resize(s1.size() + 2, '#'); //大于原本的size且指定了字符,会在尾部插入n个指定字符
	cout << s1 << endl;
	cout << "size:" << s1.size() << endl << endl;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5. reserve(重点)

reserve改变的是capacity。
在这里插入图片描述

Requests that the string capacity be adapted to a planned change in size to a length of up to n characters.
要求将字符串容量调整为不小于size的长度,以适应计划中的大小变化。


If n is greater than the current string capacity, the function causes the container to increase its capacity to n characters (or greater).
如果 n 大于当前字符串容量,该函数会使容器的容量增加到 n 个字符(或更多)。


In all other cases, it is taken as a non-binding request to shrink the string capacity: the container implementation is free to optimize otherwise and leave the string with a capacity greater than n.
在如果给的数字在size与capacity之间,那么缩减字符串容量的请求就不一定会执行:容器实现可以自由地进行其他优化,使字符串容量大于 n。


This function has no effect on the string length and cannot alter its content.
这个函数无法影响string的size和修改string的内容

	string s1("hello");
	//改变容量
	s1.reserve(4);//容量比size小
	cout << "capacity:" << s1.capacity() << endl; //不会缩容(这里不管vs还是g++都不会缩容)

	s1.reserve(10);//改变的值在capacity与size之间
	cout << "capacity:" << s1.capacity() << endl; //在vs平台下不会缩容(但是在g++里会缩容)

	s1.reserve(20);//改变的值比capacity大
	cout << "capacity:" << s1.capacity() << endl; //会扩容

在这里插入图片描述

补充

补充一个小知识点,从上面的代码我们得知,只有5个元素的string竟然开了16个空间(多出来个是给'\0'

这是因为vs在设计string类时,设计了两个存储空间,当capacity小于16个时存储在有16个字节大小的_Buf数组里面当capacit大于16时再存储到堆上开辟的动态内存

在这里插入图片描述
当我们把size或者capacity修改到大于16时,数据就会存储到_Ptr里面。

6. clear

清空有效字符
在这里插入图片描述

Erases the contents of the string, which becomes an empty string (with a length of 0 characters).
清空string的内容,并将string的size置为0

	string s1("hello worldxxxxxx");
	//清除string的元素
	s1.clear();
	cout << "size:" << s1.size() << endl;          //归零
	cout << "capacity:" << s1.capacity() << endl;  //不变

在这里插入图片描述
clear()只是将string中有效字符清空,不改变底层空间大小。

7. empty

在这里插入图片描述
这个就是判断string是否为空

	string s1("hello worldxxxxxx");
	//判断string是否为空
	s1.clear();
	cout << s1.empty() << endl;
	s1 += 'a';
	cout << s1.empty() << endl;

在这里插入图片描述
判断的是string类的size是否为0

8. shrink_to_fit

这是C++11新加入的函数
在这里插入图片描述

Requests the string to reduce its capacity to fit its size.
要求string的capacity减少到size的大小


The request is non-binding, and the container implementation is free to optimize otherwise and leave the string with a capacity greater than its size.
该请求是非约束性的,容器实现可以自由地进行其他优化,使字符串的容量大于其大小。(但vs会执行)


This function has no effect on the string length and cannot alter its content.
这个函数无法影响string的size,也无法改变string的内容

	string s1("hello worldxxxxxx");
	cout << "capacity:" << s1.capacity() << endl;
	//将capacity缩减到size
	s1.resize(10);
	s1.shrink_to_fit();
	cout << "capacity:" << s1.capacity() << endl; //缩小了

在这里插入图片描述

结语

如果全部讲解就会篇幅过长,所有剩下的部分会放在下半部的博客
那么这次的分享就到这里结束了~
最后感谢您能阅读完此片文章~
如果您认为这篇文章对你有帮助的话,可以用你们的手点一个免费的赞并收藏起来哟~
如果有任何建议或纠正欢迎在评论区留言~
也可以前往我的主页看更多好文哦(点击此处跳转到主页)。

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

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

相关文章

常见ElasticSearch 面试题解析(上)

前言 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java语言开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是一种流行的企业级搜索引擎。ElasticSearch…

直播间“饕餮盛宴”的背后,是“他经济”正在冒头

最近&#xff0c;一个有意思的现象逐渐露出了苗头。 今年“双11”第一轮尾款开启支付的当晚&#xff0c;罗永浩的直播间上演了一出别样的“饕餮盛宴”。直播开场后&#xff0c;iphone16系列、可口可乐&#xff08;含糖、无糖300ml&#xff09;10秒售罄&#xff0c;索尼PS5、沃…

hive on tez 指定队列后任务一直处于running状态

如上图所示一直处于running状态&#xff0c;查看日志发现一直重复弹出同一个info&#xff1a; 2024-10-18 16:57:32,739 [INFO] [AMRM Callback Handler Thread] |rm.YarnTaskSchedulerService|: Allocated: <memory:0, vCores:0> 释义: 当前应用程序没有分配到任何内存…

wordcloud 字体报错

wordcloud 字体报错 词云库报错&#xff1a;Only supported for TrueType fonts字体文件问题pillow版本的问题wordcloud版本问题&#xff08;我的最终解决方案&#xff09; 词云库报错&#xff1a;Only supported for TrueType fonts 字体文件问题 解决方法 写绝对路径 &…

教程分享!超简单的低功耗4G模组LCD应用示例!看过来~

低功耗4G模组LCD应用是物联网技术中的一部分知识&#xff0c;在未来的学习和实践中&#xff0c;我们还将接触到更多前沿的技术和理念。让我们一起努力&#xff0c;探索科技的无限可能&#xff0c;为我们的生活带来更多便利与惊喜&#xff01;希望本文能为您提供一些帮助&#x…

Cisco WLC 9800 - HA SSO with Ether-channel

本文将记录如何配置HA SSO以及Ethernet Channel。 1.拓扑情况 本文的内容基于如下的Topo进行。 2.准备工作 两台WLC的型号必须一样&#xff1b;两台WLC必须使用一样的软件版本&#xff1b;需要准备好使用的IP地址&#xff1a;两个用于WLC的管理地址&#xff08;WMI&#xff…

串口通讯编程示例之串口编写程序

使用open()函数打开串口设备 首先使用open()函数打开串口设备/dev/ttymxc6&#xff0c;设备使用了O_RDWR | O_NOCTTY | O_NDELAY标志&#xff0c;分别代表以读写方式打开、不让设备成为控制终端且设置非阻塞模式&#xff0c;也就是当无法打开设备时&#xff0c;不会在原地等待&…

【博客节选】Unity角色异常抖动问题排查

本文截取自本人文章 &#xff1a;【Unity实战笔记】第二一 基于状态模式的角色控制——以UnityChan为例 发现出现角色抖动问题 尝试解决方法&#xff1a; 跳跃的loop time不要勾选&#xff1b; 相机aim添加垂直阻尼 还是不行&#xff0c;仔细查看是位移时震颤。 UnityCha…

HCIP-HarmonyOS Application Developer 习题(十三)

&#xff08;多选&#xff09;1、在设计应用框架的过程中&#xff0c;我们常用的界面应用框架有哪些? A、启动页 B、详情页 C、列表视图 D、网格视图 答案&#xff1a;ABCD 分析&#xff1a; &#xff08;多选&#xff09;2、触摸屏以触控的方式进行输入。它可以支持以下哪些…

OpenIPC开源FPV之Ardupilot配置

OpenIPC开源FPV之Ardupilot配置 1. 源由2. 问题3. 分析3.1 MAVLINK_MSG_ID_RAW_IMU3.2 MAVLINK_MSG_ID_SYS_STATUS3.3 MAVLINK_MSG_ID_BATTERY_STATUS3.4 MAVLINK_MSG_ID_RC_CHANNELS_RAW3.5 MAVLINK_MSG_ID_GPS_RAW_INT3.6 MAVLINK_MSG_ID_VFR_HUD3.7 MAVLINK_MSG_ID_GLOBAL_P…

千万不要小看SD3.5!最强模型全家桶来了!

一、SD3.5 的登场 Stability AI 推出的 SD3.5 引起了广泛关注。它直接开源了三个模型&#xff0c;包括 Large 和 Large Turbo&#xff0c;Medium 将于 29 号发布&#xff0c;并且这三个型号都可以商用。 &#xff08;一&#xff09;模型版本介绍 模型版本参数量特点分辨率范围S…

《A complete telomere-to-telomere assembly of the maize genome》方法总结

研究背景 完整的T2T基因组组装一直是基因组研究的长期追求。 研究方法 通过生成高深度覆盖的超长 Oxford Nanopore Technology (ONT) 和 PacBio HiFi 测序数据&#xff0c;报道了玉米的完整基因组组装。 每条染色体均以单一contig的形式完整覆盖。 结果概述 基因组特征&am…

vue3中mitt和pinia的区别和主要用途,是否有可重合的部分?

在 Vue 中&#xff0c;Mitt 和 Pinia 是两个不同的工具&#xff0c;它们的主要用途和功能有所不同&#xff0c;但在某些方面也存在重合的部分。 区别 Mitt&#xff1a; Mitt 是一个简单而强大的事件总线库&#xff0c;用于在组件之间进行事件的发布和订阅。 它提供了一种简洁…

【Linux】实现一个简易的shell命令行

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:Linux ⚙️操作环境:Xshell (操作系统:Ubuntu 22.04 server 64bit) 目录 一.项目简介 二.分析项目实现 三.逐步实现项目功能 1.获取命令行 2.解析命令行 3.指令的判断 4.普通命令的执行 四.完整项目代码 结语 一.项目简介…

计算生物学与生物信息学漫谈-1-测序一路走来

最近工作中&#xff0c;反思自己计算生物学基础非常薄弱&#xff0c;然而作为一门非常新兴的交叉学科&#xff0c;涉及计算机、物理、生物、数学等多多学科&#xff0c;国内并没有这样完善的教程&#xff0c;因此想要自己做一个教程&#xff0c;使用费曼学习法学习&#xff0c;…

【亚马逊云】基于 Amazon EKS 搭建开源向量数据库 Milvus

文章目录 一、先决条件1.1 安装AWS CLI ✅1.2 安装 EKS 相关工具✅1.3 创建 Amazon S3 存储桶✅1.4 创建 Amazon MSK 实例✅ 二、创建EKS集群三、创建 ebs-sc StorageClass四、安装 AWS Load Balancer Controller五、部署 Milvus 数据库5.1 添加 Milvus Helm 仓库5.2 配置 S3 作…

Vue2、Element中实现Enter模拟Tab,实现切换下一个框的效果

目录 &#x1f4c3;前序 &#x1f449;开发历程 &#x1f4bb;实际代码 &#x1f4fd;实现效果图 前序 在几乎所有的浏览器中&#xff0c;都具备通过 Tab 键来切换焦点的功能。然而&#xff0c;有些用户提出了强烈要求&#xff0c;希望能够增加通过 Enter 键…

进程间通信(二)消息队列、共享内存、信号量

文章目录 进程间通信System V IPC概述System V IPC 对象的访问消息队列示例--使用消息队列实现进程间的通信 共享内存示例--使用共享内存实现父子进程间的通信&#xff08;进程同步&#xff09;示例--使用进程实现之前的ATM案例&#xff08;进程互斥&#xff09; 信号量示例--利…

上传Gitee仓库流程图

推荐一个流程图工具 登录 | ProcessOnProcessOn是一个在线协作绘图平台&#xff0c;为用户提供强大、易用的作图工具&#xff01;支持在线创作流程图、思维导图、组织结构图、网络拓扑图、BPMN、UML图、UI界面原型设计、iOS界面原型设计等。同时依托于互联网实现了人与人之间的…

大厂常问iOS面试题–Runloop篇

大厂常问iOS面试题–Runloop篇 一.RunLoop概念 RunLoop顾名思义就是可以一直循环(loop)运行(run)的机制。这种机制通常称为“消息循环机制” NSRunLoop和CFRunLoopRef就是实现“消息循环机制”的对象。其实NSRunLoop本质是由CFRunLoopRef封装的&#xff0c;提供了面向对象的AP…