【C++初阶】六、STL---string(总)|为什么学习string类|标准库中的string类|string 类常用接口

news2024/11/20 20:20:37

目录

一、为什么学习string类

1.1 C语言中的字符串

1.2 字符串在OJ面试中

二、标准库中的string类

2.1 string 介绍

2.2 编码格式

三、string 类常用接口

3.1 Member functions(成员函数)

3.1.1 构造函数(Construct)

3.1.2 赋值重载(operator=) ​编辑

3.1.3 string类对象的容量操作(Capacity)

3.1.4 string类对象的访问(Element access) 

3.1.5 string对象的访问及遍历操作(Iterators)  

3.1.6 string类对象的修改(Modifiers) 

3.1.7 string类对象的操作(String operations)

3.2 string类非成员函数(Non-member function overloads) 


一、为什么学习string类

1.1 C语言中的字符串

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

1.2 字符串在OJ面试中

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

注:由于历史原因,string类并不归属到 STL 之中,但是 string类与 STL 很相像,就把 string类归属到 STL 中一起学习

学习 STL 一定要多翻阅 STL的官方文档查看详细解释 C++官网cppreference

但是官网的排布内容不是很好,推荐使用这个非官网的网站:cplusplus ,右上角切换到旧版体验更好

二、标准库中的string类

2.1 string 介绍

string类的文档介绍 

  • 1. 字符串是表示字符序列的类
  • 2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性
  • 3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)
  • 4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)
  • 5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操

总结:

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
  3. string在底层实际是:basic_string 模板类的别名,typedef basic_string<char, char_traits, allocator>string
  4. 不能操作多字节或者变长字符的序列

        在使用string类时,必须包含#include头文件 <string> 以及 using namespace std以及多翻阅参考cplusplus 的标准文档 string

  • 这里为什么是 <string> 而没有 .h呢?
  • 因为 C语言中已经有一个 <string.h>了,为了避免冲突和进行区别,所以使用 <string> 作为头文件

2.2 编码格式

string 是 basic_string 类模板使用字符类型 char 实例化得到的一个类

  

而且还以模板生成几个名字不同 string 类,这些类的主要区别在于编码方式的不同,链接

string 为什么要设计成模板呢? 

因为编码格式的不同,一些字符存储所占用的空间不同

常见的一些编码格式:

(1)ASCII码,是美国设计的;ASCII码表是:计算机当中存的值,和字符的映射,但是只有256个字符的表示,用char表示

(2)Unicode,也叫做万国码。,Unicode是针对全世界的语言而设计的一种编码,常见的有utf-8 utf-16 utf-32

(3)gbk,gbk是叫做国标码,是针对中文创建的一个编码

 编码方式对 basic_string 的影响如下

  • char – 采用单字节编码;
  • char16_t – 采用双字节编码
  • char32_t – 采用四字节编码

这里我们以第一种进行学习,单字节编码格式的 string 

平时使用的 string 本质上是 basic_string<char>, string 内部进行了 typedef

typedef basic_string<char, char_traits, allocator> string

 -------------------我是分割线------------------  

下面介绍string类常用的接口 ,要熟练掌握,其余的用时查阅即可

三、string 类常用接口

3.1 Member functions(成员函数)

3.1.1 构造函数(Construct)

提供了很多构造函数,只需要掌握其中最常用的几个就可以了,其余的如果有需要再查询文档

(constructor)函数名称函数功能
string() (重点)构造空的string类对象,即空字符
string(const char* s) (重点)用字符数组来构造string类对象
string(const string&s) (重点)拷贝构造函数
string(size_t n, char c)用n个c字符来构造string类对象

测试代码

void Test_string()
{
	string s1; // 构造空的string类对象s1
	cout << "s1: " << s1 << endl;
	string s2("hello world"); // 用C格式字符串构造string类对象s2
	cout << "s2: " << s2 << endl;
	string s3(s2); // 拷贝构造s3
	cout << "s3: " << s3 << endl;
}

 运行结果

3.1.2 赋值重载(operator=) 

测试代码

void TestString()
{
	string s1("hello");
	string s2, s3, s4;
	s2 = s1;
	s3 = "world";
	s4 = s2 + s3;

	cout << "s2: " << s2 << endl;
	cout << "s3: " << s3 << endl;
	cout << "s4: " << s4 << endl;
}

运行结果​至于析构函数(destructor)则简单了解即可,因为程序结束自动调用析构函数 

3.1.3 string类对象的容量操作(Capacity

​掌握最常用的几个就可以了,其余的如果有需要再查询文档

函数名称功能说明
size(重点)返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty(重点)检测字符串释放为空串,是返回true,否则返回false
clear(重点)清空有效字符
reserve(重点)为字符串预留空间**
resize(重点)将有效字符的个数该成n个,多出的空间用字符c填充

(1)size && length

        size 和 length 的功能完全相同,这是早期 string 设计遗留的问题

测试代码

void TestString()
{
	string s1("hello");
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.length: " << s1.length() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl;
 
	string s2("aaaaa");
	cout << "s2: " << s2 << endl;
	cout << "s2.empty: " << s2.empty() << endl;
	s2.clear();//清空有效字符串
	cout << "s2.clear后: " << s2 << endl;
}

运行结果

(2)resize

        resize 函数用来调整字符串大小,它一共分为三种情况: 

  1. n 小于原字符串的 size,此时 resize 函数会将原字符串的 size 改为 n,但不会改变 capacity
  2. 大于原字符串的 size,但小于其 capacity,此时 resize 函数会将 size 后面的空间全部设置为字符 c 或默认的‘\0’
  3. 大于原字符串的 capacity,此时 resize 函数会将原字符串扩容,然后将size 后面的空间全部设置为字符 c 默认的‘\0’  

测试代码

void TestString()
{
	string s1("hello world!");
	cout << "s1: " << s1 << endl;
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl;
	s1.resize(20);
	cout << "s1: " << s1 << endl;
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl;
	s1.resize(15);
	cout << "s1: " << s1 << endl;
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl;
	s1.resize(5);
	cout << "s1: " << s1 << endl;
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl;
}

运行结果

(3) reserve

        reserve 用来扩容与预留空间,相当于C语言中的 realloc 函数,它分两种情况:

  • n 大于原字符串的 capacity,此时 reserve 函数会将 capacity 扩容到 n
  • n 小于等于原字符串的 capacity,capacity 容量不变 (不缩容)

注意区分 reserve 和 reverse 

测试代码

void TestString()
{
	string s1("hello world!");
	cout << "s1: " << s1 << endl;
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl << endl;
	
	s1.reserve(5);
	s1.reserve(15);
	cout << "s1: " << s1 << endl;
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl << endl;

	s1.reserve(30);
	cout << "s1: " << s1 << endl;
	cout << "s1.size: " << s1.size() << endl;
	cout << "s1.capacity: " << s1.capacity() << endl;
}

 运行结果

3.1.4 string类对象的访问(Element access) 

掌握 operator[] 使用即可,其它也是使用到了再查询文档

测试代码

void TestString()
{
	string s1 = "hello world!";

	for (size_t i = 0; i < s1.size(); ++i)
	{
		cout << s1[i] << endl;
	}

}

 运行结果

3.1.5 string对象的访问及遍历操作(Iterators)  

        Iterators 是 C++中的迭代器,可以把它当成指针来理解(string 和 vector),不是所有迭代器都是指针

也是老样子,掌握常用的几个即可,其它使用到再查询文档

函数名称函数功能
begin()返回一个指向字符串中第一个字符的迭代器
end()返回一个指向字符串最后一个字符下一个位置(‘\0’)的迭代器
rbegin()反向迭代器,返回一个指向字符串最后一个字符下一个位置(‘\0’)的迭代器
rend()反向迭代器,返回一个指向字符串中第一个字符的迭代器

测试代码

void TestString()
{
	string s1 = "12345";
	string::iterator it = s1.begin();
	while (it < s1.end())
	{
		(*it)++;
		cout << *it;
		++it;
	}
}

 运行结果

        反向迭代器就是正向迭代器反过来使用,不再演示。实际上,范围 for 的底层就是使用迭代器实现的

3.1.6 string类对象的修改(Modifiers) 

也是老样子,掌握常用的几个即可,其它使用到再查询文档

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+=(重点)在字符串后追加字符串str

(1) operator+=

        operator+= 是运算符重载,用于向字符串尾插数据,支持尾插一个字符串以及尾插一个字符

测试代码

void TestString()
{
	string s1 = "hello";
	string s2 = "world";

	s1 += s2;
	cout << s1 << endl;
}

 运行结果

(2)push_back 、append

push_back 是在字符串后尾插字符c,append 是在字符串后追加一个字符串,这些都与 += 类似,设计有些多余,不演示了

(3)insert 和 erase

        insert 函数用于向在字符串的 pos 处插入数据,erase 用来从 pos 位置开始向后删除 len 个字符,因为时间复杂度的问题,很少使用,有需要直接看文档,不演示了

3.1.7 string类对象的操作(String operations

老规矩,掌握常用的几个即可,其它使用到再查询文档

函数名称功能说明
c_str(重点)返回C格式字符串
find(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

(1)c_str

        在某些场景中只支持对C形式的字符串,即字符数组进行操作,比如网络传输、fopen,而不支持对C++中的 string 对象进行操作,所以 string 提供了 c_str,用于返回C形式的字符串,即以 ‘\0’ 结尾的字符串

测试代码

void TestString()
{
	string s1 = "hello world";
	const char* str = s1.c_str();

	cout << str << endl;
}

 运行结果

(2)find

        find 用于返回 一个字符或一个字符数组或一个string对象 在 string 中首次出现的位置,如果找不到就返回 npos: 

说明一下 npos,npos 是一个无符号数,npos = -1 即代表无符号的最大取值

测试代码

void TestString()
{
	string s1 = "hello world";

	cout << s1.find('o') << endl;
	cout << s1.find("or") << endl;
	cout << s1.find("a") << endl;
}

运行结果

(3)rfind

        rfind 是从末尾开始找指定内容,与 find 查找方向相反,不演示了

(4)substr

        substr 返回一个新构造的字符串对象,从字符位置 pos 开始,跨越 len 个字符或直到字符串结尾

测试代码

void TestString()
{
	string s1 = "hello world!!";

	cout << s1.substr(0, 5) << endl;
	cout << s1.substr(6, 6) << endl;
}

 运行结果

3.2 string类非成员函数(Non-member function overloads) 

掌握常用的几个即可,其它使用到再查询文档

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>>(重点)输入运算符重载
operator<<(重点)输出运算符重载
getline(重点)获取一行字符串
relational operators(重点)大小比较

 

(1) relational operators

两个 string 对象之间的大小关系函数重载,直接使用就好了,不演示了

(2) operator>> 和 operator<<

流插入与流提取运算符重载,这两个重载的作用就是为了让 string 对象支持直接输出和输入

(3)getline

         C语言中的 scanf 函数和 C++ 中的 cin 都是以空格、换行等作为不同数据之间的分割标志的,即当它们遇到这些符号时就会停止读。C语言提供了 gets 函数来读取一行字符,C++ 则是提供了 getline 函数来读取一行字符,并且我们还可以自己指定结束标志符,不演示了  

----------------我是分割线---------------

文章到这里就结束了,下一篇即将更新

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

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

相关文章

C++11 并发指南七(C++11 内存模型一:介绍)

C11 并发指南七(C11 内存模型一&#xff1a;介绍) 文章目录C11 并发指南七(C11 内存模型一&#xff1a;介绍)第六章主要介绍了 C11 中的原子类型及其相关的API&#xff0c;原子类型的大多数 API 都需要程序员提供一个 std::memory_order&#xff08;可译为内存序&#xff0c;访…

面试第一次被问到SDK测试,当时就懵了

01、是什么 客户端SDK是为第三方开发者提供的软件开发工具包&#xff0c;包括SDK接口、开发文档和Demo示例等。SDK和应用之间是什么关系呢&#xff1f;以云信即时消息服务为例&#xff0c;如下图所示&#xff0c;应用客户端通过调用云信SDK接口&#xff0c;进行消息等数据查询…

[前端笔记——CSS] 14.图像、媒体和表单元素

[前端笔记——CSS] 14.图像、媒体和表单元素1.CSS调整大小2.图片、媒体和表单元素2.1替换元素2.2 form元素2.3 举个实例1.CSS调整大小 一个空的<div>是没有尺寸的。如果在 HTML 文件中添加一个空<div> 并给予其边框&#xff0c;则会在页面上看到一条线。 <div…

【软件安装】ubuntu安装nvidia驱动,解决闪屏问题

Official Drivers | NVIDIA nvidia驱动下载官网&#xff0c;登陆速度是有点慢的&#xff0c;需要耐心等待 我的电脑是笔记本&#xff0c;ubuntu18.04.6&#xff0c;NVIDIA GeForce RTX 3050 Laptop GPU 天时地利人和的情况下&#xff0c;按照下面这篇博文就可以顺利安装nvidi…

【存储】etcd的存储是如何实现的(2)

在上一篇中&#xff0c;介绍了etcd底层存储的内容&#xff0c;包括wal、raft.MemoryStorage以及backend。在介绍backend时提到了backend只是etcd kv存储的一部分&#xff0c;负责持久化存储&#xff0c;backend加内存化treeIndex才构成etcd完整的支持mvcc的kv存储。所以这篇就来…

红队大量资产指纹探测工具和摄像头漏-洞渗-透和利用工具

红队大量资产指纹探测工具和摄像头漏-洞渗-透和利用工具。 Finger定位于一款红队在大量的资产中存活探测与重点攻-击系统指纹探测工具。在面临大量资产时候Finger可以快速从中查找出重点攻-击系统协助我们快速展开渗-透。 实际效果 URL批量扫描效果如下: 调用api进行资产收集效…

第九层(6):STL之queue

文章目录前情回顾queue概念queue容器需要注意的地方queue类内的构造函数queue类内的赋值操作queue类内的插入操作queue类内的删除操作queue类内的访问queue类内的大小操作下一座石碑&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一的智能制造专业学生&…

设计模式第4式:观察者模式Spring事件监听机制

前言 观察者模式是一种非常重要的设计模式&#xff0c;在JDK和Spring源码中使用非常广泛&#xff0c;而且消息队列软件如kafka、rocketmq等也应用了观察者模式。那么我们就很有必要学习一下观察者模式了。 随后我们来看看大名鼎鼎的事件监听机制&#xff0c;它是基于观察者模…

直波导与微环的耦合——Lumerical仿真1

微环与直波导的耦合的Lumerical仿真的一个记录&#xff0c;包括仿真步骤和一些问题的探究&#xff0c;参考自https://www.bilibili.com/video/BV1tF411z714。 &#x1f381;附Lumerical仿真文件 Lumerical第一个仿真一、建立结构1、放置微环结构2、修改结构二、光源1、放置光源…

React是不是MVVM架构?

首先说结论&#xff1a;不是 一、MVVM Model-View-ViewModel&#xff1a;一句话概括MVVM&#xff0c;操作数据&#xff0c;就是操作视图&#xff0c;就是操作DOM。开发者只需要完成包含申明绑定的视图模板&#xff0c;编写ViewModel中业务数据变更逻辑&#xff0c;View层则完…

MySQL(六):redo日志——保证事务的持久性

目录一、redo日志的基本介绍1.1 什么是redo日志1.2 redo日志的格式1.3 redo日志的类型1.4 Mini-Transaction二、redo日志的写入过程2.1 redo log block2.2 redo日志缓冲区2.3 将redo日志写入log buffer2.3 redo日志刷新到磁盘2.5 redo日志文件组2.6 redo日志文件格式2.7 log se…

【MySQL进阶】MySQL触发器详解

序号系列文章7【MySQL基础】运算符及相关函数详解8【MySQL基础】MySQL多表操作详解9【MySQL进阶】MySQL事务详解10【MySQL进阶】MySQL视图详解文章目录前言1&#xff0c;触发器1.1&#xff0c;触发器概述1.2&#xff0c;触发器使用环境2&#xff0c;触发器基本操作2.1&#xff…

CentOS7 安装单机 Kafka

一、单机安装 1、上传压缩文件到服务器、解压 tar -zxvf kafka_2.13-3.3.2.tgz -C /usr/local #解压到 usr/local目录下 进入解压目录下 更名kafka mv kafka_2.13-3.3.2/ kafka-3.3.2 2、配置环境变量 vim /etc/profile export KAFKA_HOME/usr/local/kafka-3.3.2export PATH$PA…

MySQL学习记录(9)InnoDB存储引擎

文章目录6、InnoDB存储引擎6.1、逻辑存储结构6.2、架构6.2.1、概述6.2.2、内存结构6.2.3、磁盘结构6.2.4、后台线程6.3、事务原理6.3.1、事务基础6.3.2、redo log日志6.3.3、undo log日志6.4、MVCC6.4.1、基本概念6.4.2、记录中隐藏字段6.4.3、undo log日志6.4.4、readview6.4.…

【Pytorch项目实战】之图像分类与识别:手写数字识别(MNIST)、普适物体识别(CIFAR-10)

文章目录图像分类与识别&#xff08;一&#xff09;实战&#xff1a;基于CNN的手写数字识别&#xff08;数据集&#xff1a;MNIST&#xff09;&#xff08;二&#xff09;实战&#xff1a;基于CNN的图像分类&#xff08;数据集&#xff1a;CIFAR-10&#xff09;图像分类与识别 …

Lua 函数 - 可变参数

Lua 函数 - 可变参数 参考至菜鸟教程。 Lua函数可以接收可变数目的参数&#xff0c;和C语言类似&#xff0c;在函数参数列表中使用三点...表示函数有可变的参数。 function add(...) local s 0 for i, v in ipairs{...} do --> {...} 表示一个由所有变长参数构成的数…

模拟实现C库函数(2)

"烦恼无影踪,丢宇宙~"上一篇的模拟实现了好几个库函数,strlen\strcpy\memcpy\memmove,那么这一篇又会增加几个常用C库函数的模拟实现 memset\itoa\atoi。一、memsetmemset - fill memory with a constant byte#include <string.h>void *memset(void *s, int c,…

机器自动翻译古文拼音 - 十大宋词 - 江城子·乙卯正月二十日夜记梦 苏轼

江城子乙卯正月二十日夜记梦 宋苏轼 十年生死两茫茫&#xff0c;不思量&#xff0c;自难忘。 千里孤坟&#xff0c;无处话凄凉。 纵使相逢应不识&#xff0c;尘满面&#xff0c;鬓如霜。 夜来幽梦忽还乡&#xff0c;小轩窗&#xff0c;正梳妆。 相顾无言&#xff0c;惟有泪千…

uniapp使用及踩坑项目记录

环境准备 下载 HBuilderX 使用命令行创建项目&#xff1a; 一些常识准备 响应式单位rpx 当设计稿宽度为750px的时&#xff0c;1rpx1px。 uniapp中vue文件style不用添加scoped 打包成h5端的时候自动添加上去&#xff0c;打包成 微信小程序端 不需要添加 scoped。 图片的…

SpringDataJpa set()方法自动保存失效

问题描述&#xff1a;springdatajpa支持直接操作对象设置属性进行更新数据库记录的方式&#xff0c;正常情况下&#xff0c;get()得到的对象直接进行set后&#xff0c;即使不进行save操作&#xff0c;也将自动更新数据记录&#xff0c;将改动持久化到数据库中&#xff0c;但这里…