【C++ STL详解】——string类

目录

前言

一、string类对象的常见构造

二、string类对象的访问及遍历

1.下标+【】(底层operator【】函数)

​编辑

2.迭代器

3.范围for

4.at

5.back和front

三、string类对象的容量操作

1.size 和 length

2.capacity

3.empty

4.clear

5.resize(调整当前字符串的大小)

6.reserve(改变当前容量的大小)

7.shrink_to_fit(缩容)

四、string类对象的修改操作

1.operator+=(尾部追加)

2.append(拼接)

3.push_back(尾插)

4.insert(插入)

5.erase(删除)

6.replace(替换)

7.swap(交换)

五、string的查找

1.find(左闭右开区间,正向查找)

2.rfind(反向查找)

六、string的截取

substr:左闭右开

七、string与字符串的转化

1.字符串转化为string

2.string转为字符串

八、非成员函数重载

1.operator<<和operator>>(输入输出运算符重载)

2.relational operators (string)


前言

好了,老铁们,前面我们对C++的一些基础语法以及一些注意事项都有了一定的了解!那么接下来我们将要进入一个崭新的世界,就是对STL库的学习!对于STL的学习核心有三点:熟用、明理(底层实现)、扩展!下面先来看看string类

  • 通过文档可以看出string是表示字符串的字符串类
  • 底层实际是:basic_string模板类的别名,typedef  basic_string<char, char_traits, allocator>stirng;
  • 使用string类时,必须包含#include头文件以及using namespace std;

如果想要了解更多,关于string类的说明,大家可以参照这个文档:string类

一、string类对象的常见构造

string();   //构造一个空字符串,长度为0(默认构造)

string (const string& str); //拷贝构造

string (const char* s); //复制s所指向的字符序列

string (const char* s, size_t n); //复制所指向的字符序列的前n个字符

string (size_t n, char c);      //复制n个字符C

string (const string& str, size_t pos, size_t len = npos);
//复制str中从字符位置pos开始并跨越len个字符的部分(如果str太短或len为string::npos,则复制到str的末尾)

示例:

	string s0;                         //构造空串
	string s1("is string");            //复制is string
	const char* s = "hello string";
	string s2(s);                      //复制"hello string"
	string s3(s, 3);                   //复制"hello string"前3个字符
	string s4(10, '#');                //复制10个#
	string s5(s1, 0, 5);               //从s1中的位置0开始跨越5个字符的部分,左闭右开区间

	cout << s0 << endl;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;

二、string类对象的访问及遍历

1.下标+【】(底层operator【】函数)

string s1("hello string");
for (int i = 0; i < s1.size(); i++)
{
	cout << s1[i] << ' ';
	//底层写法:cout << s1.operator[](i) << endl;
}

2.迭代器

  • 正向迭代器(begin+end)

begin函数:返回一个指向字符串第一个字符的迭代器

end函数:返回一个指向字符串最后一个字符的下一个位置(即为'\0')的迭代器

这里要注意到,迭代器的函数都会有两个形式一个是非const,一个是const!会根据对象类型的不同去选择不同的函数!

示例:

string s1("hello string");
string::iterator it = s1.begin();
while (it != s1.end())
{
	cout << *it << ' ';
	it++;
}
	const string s2("hello string");
	string::const_iterator it = s2.begin();
	while (it != s2.end())
	{
		cout << *it << ' ';
		it++;
	}

//    const对象返回的是const迭代器,所以不能用普通迭代器去接受

  • 反向迭代器(rbegin+rend)

rbegin函数:返回一个指向字符串最后一个字符的反向迭代器

rend函数:返回一个指向字符串第一个字符前理论元素的反向迭代器(被认为是反向端)

示例:

	string::reverse_iterator it1 = s1.rbegin();
	while (it1 != s1.rend())
	{
		cout << *it1 << ' ';
		it1++;
	}

可以看出,其实就是反向输出!但是要注意它是反向++的

3.范围for

for (auto a : s1)
{
	cout << a << ' ';
}

其实,范围for底层就是个迭代器!!!

4.at

	for (int i = 0; i<s.length(); ++i)
	{
		cout << s.at(i) << " ";
		
	}

注意:这里是at(),不是方括号[],和第一个operator功能类似,但是唯一的不同在于,两者对于越界的处理不同!

5.back和front

cout << s.back() << endl;;//访问到最后一个字符
cout << s.front();//访问第一个字符

注意:它访问到的同时,还可以进行修改!

s.back() = 'A';//最后一个元素变为A
s.front() = 'B';//第一个变为B
cout << s.back() << ' ';
cout << s.front();

三、string类对象的容量操作

1.size 和 length

string s1("hello string");
cout << s1.size() << endl;
cout << s1.length() << endl;//返回字符串有效长度

size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。他们得到的结果并不一定等于capacity!

2.capacity

s1.capacity();//返回总空间的大小

3.empty

 s1.empty();//检测字符串是否为空,为空就返回true,否则返回false

4.clear

 s1.clear();//擦除字符串内容,使其变为空字符串,并不改变底层空间的大小

5.resize(调整当前字符串的大小)

会出现以下两种情况:

        ①如果n小于当前字符串的长度,那么他就会将当前长度缩短到n个字符的长度,并将第n个字符以外的其他部分全部删除!

        ②如果n大于当前字符的长度,那么就会将大小扩大到n,扩大的部分如果有字符c,那就拿字符C填充,没有就拿字符'\0'补充!

6.reserve(改变当前容量的大小)

规则如下:

  • 如果n大于当前的容量,那么容量就会扩充到n甚至更大
  • 如果n小于当前容量,那就什么都不做
  • 这个函数不会影响字符串的长度,也不会改变其内容

7.shrink_to_fit(缩容)

规则:调整其capacity以适应它的size

四、string类对象的修改操作

1.operator+=(尾部追加)

如上图,有常见的三种重载形式,功能就是:通过在当前字符串的末尾附加额外字符来扩展字符串

string s("hello string");
s += " ";
s += "!!!!!!";
cout << s << endl;
string s2 = ("  ggggg  ");
s += s2;
cout << s << endl;

2.append(拼接)

这个函数的功能:也是上面的一样,追加,额……但是重载函数有很多,但是常用的就三种:

string& append(const string& str);

string& append(const char*s);

string& append(size_t  n,char c);

	string s("hello string");
	s.append(" ");
	s.append("sjda");
	s.append(10, 'A');
	cout << s << endl;

3.push_back(尾插)

功能:将字符c追加到字符串的末尾,使其长度增加1。

s.push_back('A');

4.insert(插入)

额……还是有点多,其实常用的就一个:在pos位置前插入字符串

string& insert(size_t pos,const char *s);

int main()
{
	string s("hello string");
    s.insert(5, "hhhhhe");//在第五个位置前,插入字符串“hhhhhe”
	cout << s << endl;
	return 0;
}

5.erase(删除)

规则:擦除字符串中从字符位置pos开始并跨越len字符的部分(如果内容太短或len为string::npos,则擦除直到字符串末尾)。

s.erase(0, 5);//删除从第0个位置开始的5个字符
cout << s << endl;

//迭代器
s.erase(s.begin() + 1);
cout << s << endl;//删除第二个位置的值

//删除区间的元素,区间为左闭右开[first,last)
s.erase(s.begin() + 1, s.end() - 1);
cout << s << endl;

6.replace(替换)

其实也有很多个,hh,大家想看完整的可以自己点进链接,下面两种是最常用的

  • String& replace (size_t pos, size_t len, const char* s);
cout << s.size() << endl;
s.replace(0, 4, "AAAAAAAAA");//从0位置开始的4个字符替换成特定字符串,
//但是有一点需要注意,字符串的内容的长度可以任意,随之大小也会改变
							
cout << s << endl;
cout << s.size() << endl;

  • String& replace (size_t pos, size_t len, size_t n, char c);
cout << s.size() << endl;
cout << s.capacity() << endl;

s.replace(0, 4, 100, 'V');//从0位置开始的4个字符替换为100个字符‘V’
cout << s << endl;
cout << s.size() << endl;
cout << s.capacity() << endl;

编译器会按照自己特定的方式进行扩容,在LInux下又是另外的扩容方式!!

需要注意:

上面的尾部追加字符s.append(1,c) / s.push_back(c) /s+='c'其实实现的差不多,但是实际应用中使用+=比较多,它不仅仅可以连接字符,还可以连接字符串

②实际上insert/erase/replace,但数据很大时,需要挪动大量的数据,效率太低,能少用就尽量少用!!!

③对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

7.swap(交换)

        对于这个交换函数,其实在STL库里面有两个,一个是作为string类的成员函数,一个是全局的函数,谁都可以用的!

int main()
{
	string s1("hello s1");
	string s2("hello s2");

	//用string里面的交换函数
	s1.swap(s2);
	cout << s1 << endl;
	cout << s2 << endl;
	cout << endl;

	//全局的swap
	swap(s1, s2);
	cout << s1 << endl;

	cout << s2 << endl;
	return 0;
}

五、string类的查找

1.find(左闭右开区间,正向查找)

功能:从字符串pos位置(不写默认是0)开始往后找字符c,返回的是第一个匹配的第一个字符的位置。
如果没有找到匹配项,函数返回string::npos(-1)。(n
pos是一个静态成员常量值,具有size_t类型元素的最大可能值

注意:他们都是const成员函数,就是说可读不可写,仅仅只是查找,遍历访问操作它是可以改变值的,也就是可读可写!

int main()
{
	string s("http://baidu.com/");
	string s2("bai");

	//find(string,pos)返回第一个匹配的位置,也就是b的位置
	size_t pos1= s.find(s2);
	cout << pos1 << endl;

	//find(str,pos)
	size_t pos2 = s.find("com");
	cout << pos2 << endl;

	//find(字符,pos)
	size_t pos3 = s.find('u');
	cout << pos3 << endl;

	return 0;
}

这里没有演示第三个重载函数,因为它其实和第二个重复了,直接用第二个就好了!

2.rfind(反向查找)

功能:从pos位置(默认是npos位置)开始向前查找字符串或者字符,找到就返回它的位置,这个位置是从前先后数的;如果没有找到就返回npos(换个方向理解就是:找到最后一次匹配的第一个字符的位置

注意:这里的第三个重载函数其实和find的情况是一样的,重复了第二个,感觉有点多余(个人吐槽)

六、string类的截取

substr:左闭右开

功能:从pos位置开始,截取n个字符,返回的结果是一个新的字符串对象,这个新对象的内容就是使用截取到子字符串去初始化!

所以这个实际上可以和find去结合使用

七、string类与一些类型的转化

1.字符串转化为string

这个很简单,其实就是第一部分的常见构造的方式!!

string s1("hello string");

char str[] = "hello string";
string s2(str);

2.string转为字符串

这个可以使用string类中的c_str或者date

c_str: const char *c_str() const;

data: const char *data() const;

区别:在C++98中,C_str转化过来的,在末尾会加上"\0",但是data不会!在C++11中,两者都会加!

string s("https://cplusplus.com/reference/string/string/rfind/");

const char* str1 = s.c_str();
const char* str2 = s.data();
cout << str1 << endl;
cout << str2 << endl;

3.内置类型转化为string

double d = 40.25;
string s1 = to_string(d);

还可以是其他的内置类型哦!!!!!

4.string转化为内置类型

string s1("45.630");
double d = stod(s1);

八、非成员函数重载

1.operator<<和operator>>(输入输出运算符重载)

Istream& operator>> (Istream& is, string& str);输入运算符重载

Ostream& operator<< (Ostream& os, const string& str);输出运算符重载

string s;
cin>>s;
cout<<s<<endl;

因为有了这个重载函数,所以可以使用cin和cout输入输出string类!

2.relational operators (string)(大小比较)

这是string类的关系操作符,包括==,!=,<,<=,>,>=。重载的函数,支持string类和string类、string类和字符串之间的比较!

int main()
{
	string s1("hello");
	string s2("hikklkl");
	//string 和string
	cout << (s1 == s2) << endl;
	cout << (s1 != s2) << endl;
	cout << (s1 < s2) << endl;
	cout << (s1 <= s2) << endl;
	cout << (s1 > s2) << endl;
	cout << (s1 >= s2) << endl;
	cout << endl;

	//string和字符串
	const char* s3 = "hella";
	cout << (s1 == s3) << endl;
	cout << (s1 != s3) << endl;
	cout << (s1 < s3) << endl;
	cout << (s1 <= s3) << endl;
	cout << (s1 > s3) << endl;
	cout << (s1 >= s3) << endl;
	return 0;
}

十分的爽!

3.getline(获取一行字符串)

这个函数的存在,其实就是因为cin和scanf的一点小缺陷,看代码

发现了什么,明明输入的A B,可是出来的却是A,其实就是因为cin和scanf在遇到空格时就会停止读取后面的字符,而后面的字符实际上放在缓冲区里!在读取一次看看

此时,A B才能完全输出!有了getline就很方便!

这个函数也是有两个用法的:

如果有界定符,那就读取到界定符为止,后面的字符直接丢弃!

string s;
getline(cin, s,'r');//读到分隔符‘r’为止
cout << s << endl;

②如果没有,那就是默认到‘\0’


好了,感谢大家的阅读!这部分内容有点小多,大家如果想要查看原文档可以点击string文档!

其实实际上用到不多!!题中见分晓!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【校园安全】支小蜜防校园霸凌语音识别系统的好处

在校园安全领域&#xff0c;防校园霸凌语音识别系统的出现&#xff0c;为预防和应对校园霸凌行为提供了新的技术手段。本文将探讨防校园霸凌语音识别系统的好处&#xff0c;并分析其在校园安全建设中的重要作用。 通过安装在校园各个角落的语音识别设备&#xff0c;系统能够捕…

Flink并行度

1、Task flink中每个算子就是一个Task&#xff0c;比如flatMap、map、sum是一个Task。 2、SubTask 算子有几个并行度SubTask的数量就是几&#xff0c;比如 3、算子并行度 算子并行度指的是每个算子的并行度&#xff0c;可用env.setParallelism(1);设置所有算子的并行度&am…

浏览器是如何渲染页面的?

浏览器是如何渲染页面的&#xff1f; 1. 解析 HTML2. 样式计算 Computed Style3. 布局 Layout4. 分层 Layer5. 绘制 Paint6. 分块 Tiling7. 光栅化 Raster8. 画 draw完整过程面试题什么是 reflow&#xff08;回流/重排&#xff09;?什么是 repaint &#xff08;重绘&#xff0…

智慧城市中的数字孪生:构建城市管理的未来框架

目录 一、引言 二、数字孪生技术概述 三、数字孪生技术在智慧城市中的应用 1、实时监测与预警 2、模拟与优化 3、智能化决策 4、协同与共享 四、数字孪生技术构建城市管理的未来框架的价值 1、提高管理效率 2、优化资源配置 3、提升公共服务水平 4、增强应对突发事…

【Linux】Linux——Centos7安装

目录 虚拟机安装【空壳子】安装VMware Workstation新建虚拟机硬件兼容性(直接下一步)稍后安装操作系统客户及操作系统选择Linux&#xff0c;版本Centos764位给虚拟机命名&#xff0c;并选择安装位置处理器配置&#xff08;默认即可&#xff0c;不够用后面可以调&#xff09;虚拟…

JavaWeb - 3 - JavaScript(JS)

JavaScript(JS)官方参考文档&#xff1a;JavaScript 教程 JavaScript&#xff08;简称&#xff1a;JS&#xff09;是一门跨平台、面向对象的脚本语言&#xff0c;是用来控制网页行为的&#xff0c;它能使网页可交互&#xff08;脚本语言就不需要编译&#xff0c;直接通过浏览器…

谷歌广告(google Ads)投放技巧

Google广告投放涉及多个方面&#xff0c;以下是一些常用的技巧&#xff0c;可以帮助提高广告效果&#xff1a; 关键词选择&#xff1a; 选择与你的产品或服务紧密相关的关键词&#xff0c;并确保这些关键词与用户的搜索意图匹配。使用Google关键词规划工具来找到潜在的关键词&a…

python词嵌入

一、词嵌入的概念 自然语言处理的突破在2023年震撼世界&#xff0c;chatgpt3出来&#xff0c;之后chatgpt4、Gemini、Claude3等出来&#xff0c;问答越来越智能&#xff0c;非常厉害&#xff0c;其中有个基础性的概念&#xff0c;计算机要如何理解语言&#xff0c;基础工作就在…

IOS苹果通话记录在线生成网站源代码,直接上传就可使用

一键生成&#xff0c;PHP的上传到网站根目录打开域名访问即可 源码免费下载地址专业知识分享社区-专业知识笔记免费分享 (chaobiji.cn)

个人开发者如何制作实用的微信预约小程序?

随着移动互联网的普及&#xff0c;微信小程序已经成为一种非常流行的应用方式。在本文中&#xff0c;我们将介绍如何通过乔拓云平台制作一个微信预约小程序&#xff0c;从入门到精通&#xff0c;让你轻松完成这个过程。 一、注册登录乔拓云平台 首先&#xff0c;你需要在乔拓云…

为什么说鸿蒙开发就业面广?人才遭“爆抢”的背后说明什么?

鸿蒙开发&#xff0c;作为华为推出的全新操作系统&#xff0c;自其诞生以来就备受关注。而鸿蒙开发就业面广&#xff0c;人才遭“爆抢”的现象&#xff0c;更是引发了业界的广泛讨论。那么&#xff0c;这一现象背后究竟隐藏着怎样的原因和深意呢&#xff1f; 首先&#xff0c;鸿…

Vue.js 进阶技巧:keep-alive 缓存组件解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Java数组常用操作

创建数组 int[] a {1,2,3};int[] a new int[]{1,2,3};int[] a new int[3];ArrayList<Integer> arr new ArrayList<>(); 添加元素 arr.add(99); //将99加入到数组末尾arr.add(3,99); //将99加入到指定索引3处访问元素 int c1 c[1]; int arr1 arr.get(1); …

链表习题-力扣oj (附加思路版)

LCR 140. 训练计划 IIhttps://leetcode.cn/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/ 给定一个头节点为 head 的链表用于记录一系列核心肌群训练项目编号&#xff0c;请查找并返回倒数第 cnt 个训练项目编号。 思路&#xff1a;双指针&#xff0c;快指针先走cnt…

Java中的优先队列PriorityQueue如何排序

目录 一、基本数据类型的排序 &#xff08;1&#xff09;升序 &#xff08;2&#xff09;降序 二、自定义类型如何排序 &#xff08;1&#xff09;升序 &#xff08;2&#xff09;降序 既然大家想要了解优先队列的排序&#xff0c;那么说明已经知道什么事优先队列了&…

ROS 2基础概念#6:服务(Service)| ROS 2学习笔记

服务&#xff08;Service&#xff09;是 ROS 2 计算图中节点通信的另一种方法。 服务基于调用和响应模型&#xff0c;而不是主题的发布者-订阅者模型。 虽然主题允许节点订阅数据流并获取持续更新&#xff0c;但服务仅在客户端专门调用时才提供数据。 ROS 2服务的基本概念 ROS…

浮点数的储存

浮点数的储存 一.浮点数的三段式&#xff08;S,E,M&#xff09;1.如何放入2.如何取出 二.为什么浮点数不能直接比较三.解释第一个问题 我们都知道整形在内存中是按照补码的形式储存的&#xff0c;但是浮点数的储存却和整数的截然不同&#xff0c;浮点数没有所谓是原反补并且浮点…

实现类似 Word 协同编辑--Canvas-Editor

前言 对于word的协同编辑&#xff0c;已经构思很久了&#xff0c;但是没有找到合适的插件。今天推荐基于canvas/svg 的富文本编辑器 canvas-editor&#xff0c;能实现类似word的基础功能&#xff0c;如果后续有更好的&#xff0c;也会及时更新。 Canvas-Editor效果图: 官方文…

重学SpringBoot3-WebMvcAutoConfiguration类

重学SpringBoot3-WebMvcAutoConfiguration类 是什么什么用生效条件作用 自定义配置的三种方式自定义配置举例1. 自定义 DispatcherServlet 配置2. 静态资源配置3. 自定义MVC配置4. 消息转换器5. 异常处理 是什么 org.springframework.boot.autoconfigure.web.servlet.WebMvcAut…

【QT6】打开项目 .pro 一堆报错 但是程序可以运行 打开别人的QT项目后,全是报错

报错环境 我通过在网上拷贝的项目&#xff0c; 然后打开pro文件 build项目 你会发现各种报错 无缘无故的报错 明明环境已经没问题了 解决方案 首先是提示no valid settings file could be found&#xff0c;这个错误很好解决&#xff0c;删除项目目录下的.user文件&#xff…