<C++>STL->string

string类的由来

这是string的定义:image-20230812120427056

string类是模板实例化后的别名,basic_string是字符串类模板,常见的字符串类型有wchar_t char char16_t
char32_t basic_string类针对的是所有字符串类型设计出来的一个模板,而我们通常使用的字符串类型是char,模板实例化为char的类命名为string

为什么要有string类?

  1. string更符合C++面向对象的设计,将对数据的处理和数据封装在一起
  2. 对字符串进行操作时使用string不需要考虑空间不够的问题,string类会自动扩容
  3. string类成员函数的可读性更强,操作更简便

string类的使用

string类文档

  1. 使用string类需要进入头文件#include <string>,并指定标准命名空间std
    image-20230812121623039

string的成员函数非常多,下面介绍常用的

构造函数

image-20230812145715510
void test_string1()
{string s1;cout << s1 << endl;//空串string s2("hello world");cout << s2 << endl;//hello worldstring s3(s2);cout << s3 << endl;//hello worldstring s4(s3, 6, 5);cout << s4 << endl;//worldstring s5("hello world", 6, 5);cout << s5 << endl;//worldstring s6(s2.begin(), s2.end());//使用迭代器初始化[h,/0)cout << s6 << endl;//hello worldstring s7(4, 'a');cout << s7 << endl;//aaaa
}

复制重载

image-20230818114617803

void test_string2()
{string s1("abcdef");string s2("123456");cout << s2 << endl;	//123456s2 = s1;cout << s2 << endl;	//abcdefs2 = "hello";cout << s2 << endl;	//hellos2 = 'c';	cout << s2 << endl;	//c
}

迭代器

迭代器STL六大组件之一,迭代器(iterator),是确使用户可在容器物件(container,例如链表或数组)上遍访的物件[1][2][3],设计人员使用此接口无需关心容器物件的内存分配的实现细节。

迭代器是一种方便使用者遍历所有容器通用的一个方法。使用者可以通过迭代器遍历所有的容器。

STL所有容器的迭代器都可以分为下面的种类image-20230818120005666

我们主要使用begin,end,rbegin,rend这四个迭代器,它们重载了const成员函数

begin/end

image-20230818131900293

begin/end是正向迭代器,每次结束begin()指向的是容器第一个元素,end指向容器最后一个元素后面一个位置。
string::iterator it++代表it指向容器的下一个数据

string s1("hello world");
const string s2("I am constant");string::iterator it = s1.begin();//it是一个迭代器,是s1对象起始位置的迭代器
while (it != s1.end())	//当it为s1终止位置的迭代器时说明it已经将s1遍历完
{cout << *it << " ";//迭代器的用法类似与指针it++;//迭代器指向下一个数据
}cout << endl;string::const_iterator cit = s2.begin();//调用的是const成员函数begin()
while (cit != s2.end())
{cout << *cit << " ";cit++;
}cout << endl;

rbegin/rendimage-20230818131511032

	string::reverse_iterator rit = s1.rbegin();//rit是一个反向迭代器,指向容器最后一个数据while (rit != s1.rend()) //rit为s1起始位置时说明已经将s1反向遍历完成{cout << *rit << " ";rit++;//反向迭代器++是指向前一个数据}cout << endl;string::const_reverse_iterator crit = s2.rbegin();while (crit != s2.rend()){cout << *crit << " ";crit++;}cout << endl;
}

运行结果:image-20230818132139046

**注意:**cbegin,cend,crbegin,crend是针对const string专门设计的迭代器,但是C++11已经重载了begin等函数的const成员函数,因此可以直接使用begin处理const string

容量相关函数

size:返回字符串长度

image-20230818132555475

length:返回字符串长度

image-20230818133023177

max_size:返回string对象最大长度

image-20230818133303590

capacity:返回字符串容量

image-20230818133426816

void test_string4()
{string s("hello world");cout << s.size() << endl;cout << s.length() << endl;cout << s.max_size() << endl;cout << s.capacity() << endl;
}
image-20230818133728426

resize:调整字符串大小

image-20230818150342424

  1. 如果n比当前对象有效元素长度小,则当前对象只保留前n个字符,删掉其余字符
  2. 如果n比当前对象有效元素长度大,则用指定的字符填充字符串直到字符串的长度等于n,若无指定字符则使用\0填充。
  3. 如果n比当前容量大,则扩容到n个有效空间,并用指定字符填充空间
  4. resize影响容量,也影响内容
void test_string5()
{string s("hello world");s.resize(5);cout << s << endl;//hellocout << s.size() << endl;//5cout << s.capacity() << endl//15;s.resize(7, 'x');cout << s.size() << endl;cout << s.capacity() << endl;cout << s << endl;
}

运行结果:image-20230818150904932

reserve:请求更改容量

image-20230818151231725

  1. 求将字符串容量调整为计划的大小更改,长度最多为 n 个字符。

  2. 如果 n 大于当前字符串容量,该函数会使容器将其容量增加到 n 个字符(或更大)。

  3. 如果n小于等于当前字符串容量,会被视为不具有约束力的请求,容器可自由实现(VS下不会进行缩容,g++下会缩容,但是它们都不会删除数据)。

  4. 该函数不能改变字符串的长度和内容,只会影响容量.

  5. reserve最大的价值是提前开好空间减少多次扩容的消耗.

clear:清理字符串

image-20230818152103049

  1. clear不会改变字符串的容量
void test_string6()
{string s("hello world");s.reserve(20);cout << s << endl;cout << s.size() << endl;cout << s.capacity() << endl;s.reserve(10);cout << s << endl;cout << s.size() << endl;cout << s.capacity() << endl;s.clear();cout << s << endl;cout << s.size() << endl;cout << s.capacity() << endl;//不改变capacity
}

运行结果:image-20230818152731720

VS下由于内存对齐reserve函数实际申请的空间比需要的空间大

empty:测试字符串是否为空

image-20230818152948256


访问元素类函数

operator[]:获取pos处的字符

image-20230818153945301

  1. pos的值应该属于[0, size()]

  2. 若pos==size(),不应该更改pos处的值,因为此时pos处为\0

  3. 当pos不合法时,operator[]会调用assert终止程序

at:获取pos处的字符

image-20230818154448151

  1. 和operator[]注意点一样,不同的是当pos不合法时,at会抛异常终止程序。

back:获取字符串最后一个字符

image-20230818154725516

front:获取字符串第一个字符

image-20230818154810061

void test_string7()
{string s("hello world");for (size_t i = 0; i < s.size(); i++){cout << s[i] << " ";}cout << endl;for (size_t i = 0; i < s.size(); i++){cout << s.at(i) << " ";}cout << endl;	cout << s.back() << endl;cout << s.front() << endl;
}

运行结果:

image-20230818154911389


修改类函数

operator+=:追加字符串

image-20230818161712258

append:追加字符串

image-20230818162822581

push_back:尾插单个字符

image-20230818162916483

assign:将内容分配给字符串

https://cplusplus.com/reference/string/string//

insert:pos位置前插入字符串

image-20230818163536826

erase:从字符串中删除字符

image-20230818164155691

若不指定删除字符个数,默认删除npos个字符
image-20230818164326012无符号的-1相当于INT32_MAX,因此erase若不指定删除字符个数默认将pos后面所有字符全部删除。

swap:交换字符串值

image-20230818170542713

string中单独实现的swap算法效率比alogrithm里的swap效率高(不涉及深拷贝)

pop_back:删除最后一个字符

image-20230818170622160

void test_string8()
{string s1("hello ");string s2("world");s1 += s2;cout << s1 << endl;s1 += "!!!";s1 += '!';cout << s1 << endl;//hello world!!!!string s3("apple");s3.append(s1, 1, 3);cout << s3 << endl;//appleellconst char* str = " pea";s3.append(str, 4);cout << s3 << endl;//appleell peastring s4;s4.append(s3.begin(), s3.end());cout << s4 << endl;//apple peastring s5;s5.push_back('a');s5.push_back('b');s5.push_back('c');s5.push_back('d');cout << s5 << endl;//abcds5.assign(s3, 9, 3);//覆盖s5的内容cout << s5 << endl;//peastring s6("hello");string s7(" world");s6.insert(1, "abcde", 3);cout << s6 << endl;//habcellos6.assign("hello");s6.insert(s6.size(), s7);cout << s6 << endl; //hello worldstring s8("hello world");s8.erase(5);cout << s8 << endl; //hellostring s9("apple");string s10("pea");s9.swap(s10);		cout << "After swap:s9 = " << s9 << ";s10 = " << s10 << endl;//s9=pea;s10=applestring s11("apple");s11.pop_back();s11.pop_back();cout << s11;
}

运行结果:

image-20230818170713181


其他操作

c_str:获取C风格字符串

image-20230818170948514

find:在字符串中查找内容

image-20230818193454909

  1. 字符串第一个字符被视为匹配的起始位置

  2. pos若比len大 ,则不会查找

  3. 如果找到对应的字符串,返回第一个匹配的第一个字符的位置

  4. 如果没有找到对应的字符串,返回npos

rfind:找到字符串中最后一次出现的内容

image-20230818194326625

  1. 字符串最后一个字符将被视为匹配的起始位置
  2. 任何一个比length大的pos值意味着完整的字符串将被搜索
  3. 若查找到,则返回最后一次匹配的第一个字符的位置
  4. 若没有查找到,则返回npos.

find_first_of:在string中查找字符

image-20230818195832204

  1. 在字符串中搜索与其参数中指定的任何字符相匹配的第一个字符。
  2. string对象第一个字符被视为匹配的起始位置
  3. pos比length大则不会查找
  4. 在string中寻找匹配s或str任何字符
  5. 若搜索到则返回第一个匹配字符的位置
  6. 若没有搜索到返回npos

find_last_of:在string中从后往前查找字符

image-20230818201106341

  1. 在字符串中搜索与其参数中指定的任何字符相匹配的最后一个字符。
  2. string中最后一个字符被视为匹配的起始位置
  3. 任何一个比length大的值意味着完整的string将被搜索
  4. 若搜索到返回最后一个匹配字符的位置
  5. 为搜索到返回npos

substr:获取子串

image-20230818202803949

  1. 如果pos等于对象长度,返回一个空串
  2. 如果pos大于对象长度,抛异常
void test_string10()
{string s("https://cplusplus.com/reference/string/string/find/");size_t pos = s.find("/");//返回"cplus"第一次出现的位置if (pos != string::npos){cout << pos << endl;}size_t rpos = s.rfind("/");if (rpos != string::npos){cout << rpos << endl;//50}size_t apos = s.find_first_of("abcdef");if (apos != string::npos){cout << apos << endl;//8}string s1("I like eating apples!");size_t find = s1.find_first_of("aeiou");while (find != string::npos){s1[find] = '*';find = s1.find_first_of("aeiou", find + 1);}cout << s1 << endl;string s2("user/bin/man");cout << "Splitting:" << s2 << endl;size_t found = s2.find_last_of("/\\");if (found != string::npos){cout << "Path:" << s2.substr(0, found) << endl;cout << "File:" << s2.substr(found + 1) << endl;}s = "https://cplusplus.com/reference/string/string/find/";size_t pos1 = s.find(":");string protocols = s.substr(0, pos1);cout << protocols << endl;size_t pos2 = s.find("/", pos1 + 3);string domain = s.substr(pos1 + 3, pos2 - pos1 - 3);cout << domain << endl;string source = s.substr(pos2 + 1);cout << source << endl;
}

运行结果:
image-20230819112601764


非成员函数

operator+:拼接字符串

image-20230819113105875

[ralational operators](https://cplusplus.com/reference/string/string/ralational operators/):对字符串的比较操作

image-20230819113314884

operaotr>>:从流中提取字符串

image-20230819113826909

  1. 遇见空白符结束流提取
  2. 想要提取空白符需要使用getline

operator<<:将字符串打印到流中

image-20230819113856892

getline:从流中提取一行到string中

image-20230819115641700

  1. 从 is 中提取字符并将其存储到 str 中,直到找到分隔符 delim(或换行符“\n”,对于 (2))

  2. 如果到达文件结尾或输入操作期间发生其他错误,提取也会停止。

  3. 如果找到分隔符,它将被提取并丢弃


不同编译器下的string结构

vs下string

下述结构是在32位平台下进行验证,32位平台下的指针为4字节

vs下string的结构总共占28字节,其中由以下几部分组成:

  • 联合体_Bx
  • 指针_Myproxy记录其他信息
  • 记录字符串有效长度变量_Mysize
  • 记录当前字符串容量变量_Myres

联合体_Bx中存放的是字符串的内容

  • 当字符串有效长度小于16时存放在_Bx中的buf数组中
  • 当字符串长度大于等于16时存放在_Bx中的_Ptr指针所指向的堆空间中。image-20230831220148643

故string的大小为 16 + 4 + 4 + 4 = 28 16+4+4+4=28 16+4+4+4=28

image-20230831215707027

g++下string

g++下的string结构通过一个指针实现,指针指向一个结构,结构包含:

  • 空间总大小
  • 字符串有效长度
  • 引用计数
  • 指向堆空间的字符串,用来存放字符串内容

string的模拟实现

请移步string模拟实现

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

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

相关文章

Elasticsearch基础篇(八):常用查询以及使用Java Api Client进行检索

ES常用查询以及使用Java Api Client进行检索 1. 检索需求 参照豆瓣阅读的列表页面 需求&#xff1a; 检索词需要在数据库中的题名、作者和摘要字段进行检索并进行高亮标红返回的检索结果需要根据综合、热度最高、最近更新、销量最高、好评最多进行排序分页数量为10&#xf…

flutter设置windows是否显示标题栏和状态栏和全屏显示

想要让桌面软件实现全屏和不显示状态栏或者自定义状态栏&#xff0c;就可以使用window_manager这个依赖库&#xff0c;使用起来还是非常方便的&#xff0c;可以自定义显示窗口大小和位置&#xff0c;还有设置标题栏是否展示等内容&#xff0c;也可以设置可拖动区域。官方仓库地…

OpenHarmony当前进展和未来趋势

操作系统自20世纪50年代诞生&#xff0c;经历了从专用操作系统到通用操作系统的转变。整体可以将操作系统的发展历史分为3个阶段&#xff1a;PC时代、移动互联网时代、万物互联时代。 PC时代主要以计算机为主&#xff0c;用户规模从1970年的10亿增长到1990年的30亿。这一时代诞…

鸿蒙原生应用/元服务实战-DevEco Studio 模拟器资源经常不足

DevEco Studio 模拟器资源经常不足&#xff0c;模拟器是最方便和最广泛的开发者可以快速体验应用元服务效果的途径&#xff0c;还是要加强。 除了Wearable,其他都用不了。 只能用预览器看效果&#xff0c;或者使用远程真机或者本地真机了。 在API9&#xff0c;比如分享等&…

leetcode第 381 场周赛最后一题 差分,对称的处理

第 381 场周赛 - 力扣&#xff08;LeetCode&#xff09;最后一题3017. 按距离统计房屋对数目 II - 力扣&#xff08;LeetCode&#xff09; dijkstra超时了&#xff0c;看了灵神的解题方法力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台&#xff0c;其…

二.用户与权限管理(二)

用户与权限管理 5.角色管理5.1角色的理解5.2创建角色5.3给角色赋予权限5.4查看角色的权限5.5回收角色的权限5.6删除角色5.7给用户赋予角色5.8激活角色5.9撤销用户角色5.10设置强制角色(mandatory role) 6.配置文件的使用6.1配置文件格式6.2 启动命令与选项组6.3 特定MySQL版本的…

java数组ArrayList(存对象)

1、dade文件 package model;public class dade {private int id;private String name;public dade() {}public dade(int id, String name) {this.id id;this.name name;}public int getId() {return id;}public void setId(int id) {this.id id;}public String getName() {…

推荐IDEA一个小插件,实用性很高!!

插件&#xff1a; Convert YAML and Properties File 由于每个人的开发习惯不同&#xff0c;在开发过程中会遇到各种小细节的问题。今天给大家介绍一个小插件&#xff0c;作用不大&#xff0c;细节很足。 就是properties类型文件和yml文件互相自由转换 解决&#xff1a;…

【webrtc】neteq测试工程

设置git代理 $ git config --global http.https://github.com.proxy socks5://127.0.0.1:7890 git config --global https.https://github.com.proxy socks5://127.0.0.1:7890导入cmake直接构建 win32 debug v143 编译opus Build started...

云原生全栈监控解决方案(全面详解)

【作者】JasonXu 前言 当前全球企业云化、数字化进程持续加速&#xff0c;容器、微服务等云原生技术在软件架构中快速渗透&#xff0c;IT 架构云化、复杂化持续驱动性能监控市场。企业云化、数字化持续转型&#xff0c;以及为了考虑系统的弹性、效率&#xff0c;企业软件开发中…

【linux】 查看 Linux 重启历史记录(reboot)

了解 Linux 重启日志 /var/log 目录隐藏着 Linux 日志机制的核心信息&#xff0c;它是记录系统活动的宝贵仓库。然而&#xff0c;仅仅有日志还不够&#xff0c;真正的难题在于&#xff0c;如何从大量数据中提炼出与系统重启相关的关键信息。 在 /var/log 目录中&#xff0c;可…

简单但全面了解一下webSocket

文章目录 webSocket是一种协议&#xff0c;设计用于提供低延迟、双全工和长期运行的连接什么是实时通信&#xff1f; webSocket之前的世界webSocket的优势为什么需要心跳机制&#xff1f;webSocket的限制 webSocket是一种协议&#xff0c;设计用于提供低延迟、双全工和长期运行…

CRM系统的痛点,如何解决?

在当今竞争激烈的商业世界中&#xff0c;客户关系管理&#xff08;CRM&#xff09;数字化转型已经成为大企业成功的重要秘诀。大型跨国公司如亚马逊、苹果和微软等已经在CRM数字化方面走在了前列&#xff0c;实现了高度个性化的客户体验&#xff0c;加强了客户忠诚度。 然而&a…

Conda python管理环境environments 四 从入门到精通

Conda系列&#xff1a; 翻译: Anaconda 与 miniconda的区别Miniconda介绍以及安装Conda python运行的包和环境管理 入门Conda python管理环境environments 一 从入门到精通Conda python管理环境environments 二 从入门到精通Conda python管理环境environments 三 从入门到精通…

【Linux】解决能访问github但克隆不了的问题

文章目录 1.查看你的代理的地址&#xff1a;2.git设置3.尝试clone 1.查看你的代理的地址&#xff1a; 2.git设置 先看看当前的git设置 $ git config --list然后git中要设置好对应的地址 git config --global http.proxy 127.0.0.1:78903.尝试clone $ git clone https://git…

服务器感染了.wis[[Rast@airmail.cc]].wis勒索病毒,如何确保数据文件完整恢复?

导言&#xff1a; 在当今数字化的时代&#xff0c;恶意软件攻击已经变得越来越复杂和狡猾&#xff0c;[[MyFilewaifu.club]].wis [[backupwaifu.club]].wis[[Rastairmail.cc]].wis勒索病毒是其中的一种新威胁。本文91数据恢复将深入介绍[[MyFilewaifu.club]].wis [[backupwaif…

机器学习实验报告-集成学习

目录 一、集成学习介绍 1.1集成学习的引入 1.2集成学习发展史 1.3集成学习的学习组织方式 1.3.1并联组织关系 1.3.2串联组织关系 1.4集成学习及其实现方法概述 二、集成学习实现方法 2.1Boosting 2.1.1基本过程 2.1.2注意点 2.2bagging 2.2.1基本过程 2.2.2注意点…

QT实现USB通讯

一.概述 QT实现USB通讯这里主要介绍两种方法&#xff0c;一种是通过libusb库来实现usb通讯&#xff0c;一种是通过hidapi库实现通信。 1.介绍libusb库 libusb 是一个 C 库&#xff0c;提供对 USB 设备的通用访问。 可移植的&#xff1a;使用单个跨平台API&#xff0c;它可以…

一、防御保护---信息安全概述

一、网络安全防御---信息安全概述 1.信息安全现状及挑战1.1 网络空间安全市场在中国&#xff0c;潜力无穷1.2 数字化时代威胁升级1.3 传统安全防护逐步失效1.4 安全风险能见度不足1.5 缺乏自动化防御手段1.6 网络安全监管标准愈发严苛 2.信息安全概述2.1 简介2.2 常见的网络安全…

Java 设计者模式以及与Spring关系(四) 代理模式

目录 简介: 23设计者模式以及重点模式 代理模式&#xff08;Proxy Pattern&#xff09; 静态代理示例 spring中应用 动态代理 1.基于JDK的动态代理 target.getClass().getInterfaces()作用 内名内部类写法(更简洁&#xff0c;但不推荐) 2.基于CGLIB实现 spring中应用 …