C++入门7——string类详解

目录

1.什么是string类?

2.string类对象的常见构造

2.1 string();

2.2 string (const char* s);

2.3 string (const string& str);

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

2.5 string (const char* s, size_t n);

2.7 验证:

3.string类对象的遍历及访问 

3.1 下标+ [] 访问

3.2 iterator迭代器访问

3.3 at访问 

4. string类对象的容量操作

4.1 size与length

4.2 capacity

4.3 reserve

4.4 resize

4.5 clear

4.6 empty

5.string类对象的修改操作

5.1 增

1. append

2. +=

3.insert 

5.2 删

1. pop_back

2. erase

5.3 查 

1.substr

2.find

5.4 改

1. replace

2. swap 

5.5 查改结合完成替换操作


1.什么是string类?

在官网中,string类有这样的介绍:

Strings are objects that represent sequences of characters.

即:string类表示的对象是字符串类。

1. string是表示字符串的字符串类

2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

3. string在底层实际是:basic_string模板类的别名,typedef basic_string string;

4. 不能操作多字节或者变长字符的序列。

(在使用string类时,必须包含#include头文件以及using namespace std;)

2.string类对象的常见构造

2.1 string();

在官网中,对string();的解释为:

Constructs an empty string, with a length of zero characters.

即:构造一个空字符串,长度为零字符。

int main()
{//string();定义一个空的string类string s1;return 0;
}

2.2 string (const char* s);

在官网中,对于string (const char* s);的解释为:

Copies the null-terminated character sequence (C-string) pointed by s.

即:复制s指向的以空字符结尾的字符串。

int main()
{//string (const char* s);复制s指向的以空字符结尾的字符串string s2("hello world!");return 0;
}

2.3 string (const string& str);

在官网中,对string (const string& str);的解释为:

Constructs a copy of str.

即可以理解为拷贝构造。

int main()
{//拷贝构造s2string s3(s2);string s4 = s2;return 0;
}

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

在官网中,对string (const string& str, size_t pos, size_t len = npos);的解释为:

Copies the portion of str that begins at the character position pos and spans len characters.

即:拷贝str从pos位置到len个字符的一部分。

int main()
{//string (const string& str, size_t pos, size_t len = npos);//拷贝str从pos位置到len个字符的一部分。string s5(s2, 1, 7);return 0;
}

可在官网里括号里还有一句话:  (or until the end of str, if either str is too short or if len is string::npos).

这句话可以理解为:如果str太短或者len太长,那就只拷贝到str的结尾。

2.5 string (const char* s, size_t n);

在官网中,对string (const char* s, size_t n);的解释为:

Copies the first n characters from the array of characters pointed by s.

即:拷贝s指向的字符数组的前n个字符。

int main()
{//string (const char* s, size_t n);//拷贝s指向的字符数组的前n个字符string s6("hello world!", 5);return 0;
}

2.6 string (size_t n, char c);

在官网中,对string (size_t n, char c);的解释为:

Fills the string with n consecutive copies of character c.

即:用n个C语言字符填充。

int main()
{//string (size_t n, char c);//用n个C语言字符填充string s7(10, 'l');
}

2.7 验证:

<<与>>已实现重载,所以可以直接用。

故验证代码如下:

#include<iostream>
#include<string>
using namespace std;
int main()
{//string();定义一个空的string类string s1;//string (const char* s);复制s指向的以空字符结尾的字符串string s2("hello world!");//string (const string& str);拷贝构造s2string s3(s2);string s3_1 = s2;//string (const string& str, size_t pos, size_t len = npos);//拷贝str从pos位置到len个字符的一部分。string s4(s2, 1, 7);//拷贝s2从下标1位置开始到7个字符的一部分//string (const char* s, size_t n);//拷贝s指向的字符数组的前n个字符string s5("hello world!", 5);//拷贝"hello world!"的前5个字符//string (size_t n, char c);//用n个C语言字符填充string s6(10, 'l');//拷贝10个‘l’cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s3_1 << endl;cout << s4 << endl;cout << s5 << endl;cout << s6 << endl;return 0;
}

结果如图:

3.string类对象的遍历及访问 

3.1 下标+ [] 访问

①计算string类的长度或大小

 (size与length意义相同,建议用size)用法如下:

int main()
{string s1("hello world!");cout << s1.size() << endl;cout << s1.length() << endl;return 0;
}

(由结果得知,size与length不包含'\0') 

② 知道了string的长度,我们就可以这样遍历string:

int main()
{string s1("hello world!");for (size_t i = 0; i < s1.size(); i++){cout << s1[i] << endl;//重载了s1.operator[](i)}return 0;
}

 ③实现逆置string

方法一:手搓交换

int main()
{string s1("hello world!");cout << "逆置前s1="<< s1 << endl;size_t begin = 0;//左边界size_t end = s1.size() - 1;//右边界while (begin < end){char tmp = s1[begin];s1[begin] = s1[end];s1[end] = tmp;++begin;--end;}cout << "逆置后s1=" << s1 << endl;return 0;
}

方法二:使用swap

int main()
{string s1("hello world!");cout << "逆置前s1="<< s1 << endl;while (begin < end){swap(s1[begin], s1[end]);++begin;--end;}cout << "逆置后s1=" << s1 << endl;return 0;
}

3.2 iterator迭代器访问

int main()
{string s1("hello world!");string::iterator it = s1.begin();while (it != s1.end()){cout << *it << endl;++it;}return 0;
}

iterator的用法与指针类似:

二者的区别:

 下标+[]只适用于部分容器,底层物理有一定连续,如链式结构、树形、哈希结构,就只能用迭代器。迭代器才是容器访问的主流形式。

3.3 at访问 

at访问与下标+[]访问的功能相同,区别主要体现在越界访问时的报错形式:

如①下标+[]的越界访问:

int main()
{string s1("hello world!");cout << s1[20] << endl;return 0;
}

 ②at的越界访问:

int main()
{string s1("hello world!");cout << s1.at(20) << endl;return 0;
}

(即下标+[]是暴力地终止,at是温柔地终止) 

4. string类对象的容量操作

4.1 size与length

size与length返回字符串有效字符长度

前面已经说过,size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。

代码演示:

int main()
{string s1("hello world!");cout << s1.size() << endl;return 0;
}

4.2 capacity

capacity返回空间总大小

代码如下:

int main()
{string s1("hello world!");cout << s1.capacity() << endl;return 0;
}

设计程序检测string的扩容机制:

int main()
{string s1("hello world!");//检测string的扩容机制size_t old = s1.capacity();    //令old=原本的容量大小cout << old << endl;        for (size_t i = 0; i < 500; i++){s1.push_back('l');         //尾插l的过程中string的容量大小一定会发生变化if (old != s1.capacity())  //当发生扩容时,打印新的string容量大小{cout << s1.capacity() << endl;old = s1.capacity();}}return 0;
}

4.3 reserve

reserve为字符串预留空间(即可以理解为需要多少空间提前开好,不用边用边开)

reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。(在vs2019下reserve只扩容不缩容,在g++下reserve会缩容,但只会缩到现有数据的大小)

用法如下:

int main()
{string s1("hello world!");cout << s1.capacity() << endl;s1.reserve(500);cout << s1.capacity() << endl;return 0;
}

4.4 resize

resize将有效字符的个数改变成n个,多出的空间用字符c填充

resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)用'\0'来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。

①如果要扩容的空间>capacity,则扩容+尾插。验证如下:

int main()
{string s1("hello world!");cout << s1.size() << endl;cout << s1.capacity() << endl;//如果要扩容的空间>capacitys1.resize(100);cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << endl;return 0;
}

int main()
{string s1("hello world!");cout << s1.size() << endl;cout << s1.capacity() << endl;//如果要扩容的空间>capacitys1.resize(100, 'x');cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << endl;return 0;
}

 ②如果size<n<capacity,则只尾插不扩容,验证如下:

int main()
{string s1("hello world!");cout << s1.size() << endl;cout << s1.capacity() << endl;//如果size<n<capacitys1.resize(13,'x');cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << endl;return 0;
}

③如果n<size,只删除、保留前n个,不缩容,验证如下:

int main()
{string s1("hello world!");cout << s1.size() << endl;cout << s1.capacity() << endl;//如果n<capacitys1.resize(6);cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << endl;return 0;
}

(reserve与resize的区别可以概括为一句话:reserve只影响容量,不影响数据,resize既影响容量又影响数据)

4.5 clear

清空有效字符

clear()只是将string中有效字符清空,不改变底层空间大小。

验证如下:

int main()
{string s1("hello world!");cout << s1.size() << endl;cout << s1.capacity() << endl;s1.clear();cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << endl;return 0;
}

4.6 empty

检测字符串释放为空串,是返回true,否则返回false(注意:空为真,不空为假)

验证如下:

int main()
{string s1("hello world!");cout << s1.empty() << endl;string s2;cout << s2.empty() << endl;return 0;
}

5.string类对象的修改操作

修改操作无非就是增删查改,这里只介绍比较常用的操作

5.1 增

1. append

增操作其实已经有了一个我们熟悉的push_back,可是push_back每次只能尾插一个字符,为了方便就有了append:

比如我们二者兼用:

int main()
{string s1("hello");s1.push_back(' ');s1.append("world!");cout << s1 << endl;return 0;
}

append的其他常用用法如下:

①string& append (const char* s);插入常量字符串(上面的用法)

②string& append (const string& str);插入string:

int main()
{string s1("hello");string s2(s1);return 0;
}

③string& append (const string& str, size_t subpos, size_t sublen);插入string从subpos位置起到sublen个字符止的那部分:

int main()
{string s1("hello world!");string s2(s1,1,3);return 0;
}

④string& append (const char* s, size_t n);插入常量字符串的前n个:

int main()
{string s1("hello world!", 3);return 0;
}

⑥string& append (size_t n, char c);插入n个字符c:

int main()
{string s1(4,'x');return 0;
}

⑦string& append (InputIterator first, InputIterator last);插入string的一部分:

插入s1:

int main()
{string s1("hello world!");string s2;s2.append(s1.begin(), s1.end());return 0;
}

 插入去头去尾的s1:

int main()
{string s1("hello world!");string s2;s2.append(++s1.begin(), --s1.end());return 0;
}

2. +=

①string& operator+= (const string& str);插入string:

int main()
{string s1("hello world!");string s2;s2 += s1;return 0;
}

②string& operator+= (const char* s);插入字符串:

int main()
{string s1;s1 += "hello world!";return 0;
}

 ③string& operator+= (char c);插入字符:

int main()
{string s1;s1 += '!';return 0;
}

3.insert 

观察push_back与append,二者都是尾插,那有没有不是尾插的方法呢?当然有!

①string& insert (size_t pos, const string& str);在pos位置插入string:

int main()
{string s1("hello ");string s2("world!");s2.insert(0, s1);return 0;
}

②string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);在pos位置插入string的一部分:

int main()
{string s1("hello ");string s2("world!");s2.insert(0, s1, 1, 3);//ellworld!return 0;
}

③string& insert (size_t pos, const char* s);在pos位置插入字符串:

int main()
{string s1("world!");s1.insert(0, "hello ");//hello world!return 0;
}

④string& insert (size_t pos, const char* s, size_t n);在pos位置插入字符串的前n个:

int main()
{string s1("world!");s1.insert(0, "hello ",3);//helworld!return 0;
}

5.2 删

1. pop_back

尾删:

int main()
{string s1("hello world!");s1.pop_back();//hello worldreturn 0;
}

2. erase

①string& erase (size_t pos = 0, size_t len = npos);从第pos个位置删除len个字符:

int main()
{string s1("hello world!");s1.erase(5, 1);//helloworld!return 0;
}

②iterator erase (iterator p);删除string的第p个位置:

int main()
{string s1("hello world!");s1.erase(s1.begin()+1);//hllo world!return 0;
}

5.3 查 

1.substr

string substr (size_t pos = 0, size_t len = npos) const;从pos位置开始,取len个字符:

int main()
{string s1("hello world!");string s2 = s1.substr(6, 5);//worldreturn 0;
}

2.find

关于find的返回值:

The position of the first character of the first match.
If no matches were found, the function returns string::npos.
即:如果找到了就返回找到的第一个的下标,如果没有找到就返回整型的最大值。

①size_t find (char c, size_t pos = 0) const;从pos位置开始找c,没有给pos默认从头开始找:

int main()
{string s1("hello world!");size_t pos1 = s1.find('l');//2size_t pos2 = s1.find('l', 5);//9size_t pos3 = s1.find('x');//nposreturn 0;
}

 例:取string指定的一部分:

int main()
{//取文件名后缀string s1("test.cpp");size_t pos1 = s1.find('.');if (pos1 != string::npos){/*string s2 = s1.substr(pos1, s1.size() - pos1);*/string s2 = s1.substr(pos1);cout << s2 << endl;}return 0;
}

5.4 改

1. replace

①string& replace (size_t pos, size_t len, const string& str);在pos位置的len个字符替换成str:

int main()
{string s1("hello world!");s1.replace(5, 1, "?");//hello?world!return 0;
}

2. swap 

与另一个string交换:

int main()
{string s1("hello world!");string s2;s2.swap(s1);//hello world!return 0;
}

5.5 查改结合完成替换操作

例:将s1的空格全部替换为?

方法一:

int main()
{string s1("have a good time!");cout << "替换前s1=" << s1 << endl;//have a good time!size_t pos = s1.find(' ', 0);while (pos != string::npos){s1.replace(pos, 1, "?");pos = s1.find(' ', pos + 1);}cout << "替换后s1=" << s1 << endl;//have?a?good?time!return 0;
}

实际中replace效率太低,因此尽量少用replace

方法二:

int main()
{string s1("have a good time!");cout << "替换前" << s1 << endl;//have a good time!string s2;for (auto ch : s1){if (ch == ' '){s2 += "?";}else{s2 += ch;}}s1.swap(s2);cout << "替换后" << s1 << endl;//have?a?good?time!return 0;
}

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

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

相关文章

【机器学习】基于线性回归的医疗费用预测模型

文章目录 一、线性回归定义和工作原理假设表示 二、导入库和数据集矩阵表示可视化 三、成本函数向量的内积 四、正态方程五、探索性数据分析描述性统计检查缺失值数据分布图相关性热图保险费用分布保险费用与性别和吸烟情况的关系保险费用与子女数量的关系保险费用与地区和性别…

GDP播放器 驱动视频播放器 PHP 系统源码 v4.4.3

最重要的是我们自己开发了源代码&#xff0c;因此无论您在使用此工具时遇到什么问题&#xff0c;我们都会快速解决。这个版本演示 分别支持PHP7.4/8.1/8.2三个版本 演示地址

轻松驾驭开发之旅:Maven配置阿里云CodeUp远程私有仓库全攻略

文章目录 引言一、为什么选择阿里云CodeUp作为远程私有仓库&#xff1f;二、Maven配置阿里云CodeUp远程私有仓库的步骤准备工作配置Maven的settings.xml文件配置项目的pom.xml文件验证配置是否成功 三、使用阿里云CodeUp远程私有仓库的注意事项 引言 在软件开发的世界里&#…

CosyVoice - 阿里最新开源语音克隆、文本转语音项目 支持情感控制及粤语 本地一键整合包下载

近日&#xff0c;阿里通义实验室发布开源语音大模型项目FunAudioLLM&#xff0c;而且一次包含两个模型&#xff1a;SenseVoice和CosyVoice。 CosyVoice专注自然语音生成&#xff0c;支持多语言、音色和情感控制&#xff0c;支持中英日粤韩5种语言的生成&#xff0c;效果显著优于…

分子AI预测赛Task4笔记(结束)

话不多说&#xff0c;直接上官方链接&#xff1a;‌​​​‍&#xfeff;​⁠​‌​‍​​&#xfeff;​‌​⁠‬​&#xfeff;‬​​‌​​​​‬‬​​​​‍⁠‍‌​&#xfeff;⁠Task3&#xff1a;进阶baseline详解 - 飞书云文档 (feishu.cn)Task4&#xff1a;持续尝试&…

C++左值右值

在C中&#xff0c;左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09;是表达式分类的关键概念&#xff0c;它们主要影响表达式的赋值、函数调用以及操作符的使用方式。这些概念在C11及以后的版本中变得更加重要&#xff0c;因为引入了移动语义和右值引用…

妈妈带女儿美在心里

在这个充满温情与惊喜的午后&#xff0c;阳光温柔地洒落在每一个角落&#xff0c;仿佛连空气弥漫着幸福的味道。就在这样一个平凡的时刻&#xff0c;一段关于爱与成长的温馨画面&#xff0c;悄然在网络上绽放&#xff0c;引爆了无数人的心弦——#奚梦瑶2岁女儿身高#&#xff0c…

【Linux进程】命令行参数 环境变量(详解)

目录 前言 1. 命令行参数 什么是命令行参数? 2. 环境变量 常见的环境变量 如何修改环境变量? 获取环境变量 环境变量的组织方式 拓展问题 导入环境变量 3. 本地变量* 总结 前言 在使用Linux指令的时候, 都是指令后边根命令行参数, 每个指令本质都是一个一个的可执行程…

【UE5.1 角色练习】13-枪械射击——拿出与收起武器

目录 效果 步骤 一、安装射击武器 二、拿武器和收武器 效果 步骤 一、安装射击武器 1. 在虚幻商城中将“FPS Weapon Bundle”添加到工程中&#xff0c;由于我们使用的是5.1版本&#xff0c;我们可以先将该资产放入UE4工程中&#xff0c;然后迁移到5.1版本的工程 2. 打开角…

一.2.(4)放大电路静态工作点的稳定;(未完待续)

1.Rb对Q点及Au的影响 输入特性曲线&#xff1a;Rb减少&#xff0c;IBQ&#xff0c;UBEQ增大 输出特性曲线&#xff1a;ICQ增大&#xff0c;UCEQ减少 AUUO/Ui分子减少&#xff0c;分母增大&#xff0c;但由于分子带负号&#xff0c;所以|Au|减少 2.Rc对Q点及Au的影响 输入特性曲…

【JavaSE复习】数据结构、集合

JavaSE 复习 1.数据结构1.1 查找1.1.1 基本查找1.1.2 二分查找1.1.3 插值查找1.1.4 斐波那契查找1.1.5 分块查找1.1.6 分块查找的扩展&#xff08;无规律数据&#xff09; 1.2 排序1.2.1 冒泡排序1.2.2 选择排序1.2.3 插入排序1.2.4 快速排序 2. 集合2.1 基础集合2.1.1 集合和数…

爱了!8款超好用的PC端办公软件!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 你电脑中用的最久的软件是哪些&#xff1f;以下是否有你曾经使用过的软件呢&#xff1f;工欲善其事&#xff0c;必先利其器&#xff0c;今天继续…

无人机便携式侦测干扰设备(定全向)技术详解

无人机便携式侦测干扰设备&#xff08;定全向&#xff09;是一种专门针对无人机进行侦测和干扰的设备。它具备定向和全向两种工作模式&#xff0c;能够覆盖较宽的频率范围&#xff0c;有效侦测并干扰无人机与遥控器之间的通信信号&#xff0c;从而达到控制或驱离无人机的目的。…

验证回文串-string题目

用双指针&#xff0c;left right从两头往中间对比&#xff0c;不是字母的都略过&#xff0c;比的时候化成小写字母 125. 验证回文串 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool isPalindrome(string s) {if(s.size() < 1)return true;int left …

论文复现-基于决策树算法构建银行贷款审批预测模型(金融风控场景)

作者Toby&#xff0c;来源公众号&#xff1a;Python风控模型&#xff0c;基于决策树算法构建银行贷款审批预测模型 目录 1.金融风控论文复现 2.项目背景介绍 3.决策树介绍 4.数据集介绍 5.合规风险提醒 6.技术工具 7.实验过程 7.1导入数据 7.2数据预处理 7.3数据可…

SpringBoot3+Vue3开发园区管理系统

介绍 在当今快速发展的城市化进程中&#xff0c;高效、智能的园区管理成为了提升居民生活品质、优化企业运营环境的关键。为此&#xff0c;我们精心打造了全方位、一体化的园区综合管理系统&#xff0c;该系统深度融合了园区管理、楼栋管理、楼层管理、房间管理以及车位管理等…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【明文导入密钥(ArkTS)】

明文导入密钥(ArkTS) 分别以导入AES256与RSA2048密钥为例&#xff0c;具体的场景介绍及支持的算法规格 开发步骤 指定密钥别名keyAlias。 密钥别名的最大长度为64字节。 封装密钥属性集和密钥材料。 密钥属性集同样与密钥生成中指定的密钥属性一致&#xff0c;须包含[HuksKe…

昇思MindSpore学习总结十——ResNet50迁移学习

1、迁移学习 &#xff08;抄自CS231n Convolutional Neural Networks for Visual Recognition&#xff09; 在实践中&#xff0c;很少有人从头开始训练整个卷积网络&#xff08;使用随机初始化&#xff09;&#xff0c;因为拥有足够大小的数据集相对罕见。相反&#xff0c;通常…

【机器学习】机器学习与时间序列分析的融合应用与性能优化新探索

文章目录 引言第一章&#xff1a;机器学习在时间序列分析中的应用1.1 数据预处理1.1.1 数据清洗1.1.2 数据归一化1.1.3 数据增强 1.2 模型选择1.2.1 自回归模型1.2.2 移动平均模型1.2.3 长短期记忆网络1.2.4 卷积神经网络 1.3 模型训练1.3.1 梯度下降1.3.2 随机梯度下降1.3.3 A…

SpringCloud学习Day7:Seata

概念 Seata是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务 工作流程 TC以Seata服务器形式独立部署&#xff0c;TM和RM则是以Seata Client的形式集成在微服务中运行