【C++深入浅出】STL之string用法详解

news2025/1/16 5:33:48


目录

一. 前言

二. STL概要

2.1 什么是STL

2.2 STL的六大组件

2.3 STL的缺陷

三. string类概述

3.1 什么是string类

3.2 为什么要使用string类

四. string类的使用

4.1 包含头文件

4.2 构造函数

4.3 赋值运算符重载

4.4 容量操作

4.5 访问/遍历操作

4.6 查找修改操作

4.7 子串操作

​4.8 非成员函数


一. 前言

        经历了前面漫长且痛苦的学习,相比各位已经体会到了C++的魅力了叭 不要怕,学习完了模板之后,下面我们将进入STL的学习。相信你学完了STL之后,就会感受到使用C++是多么的顺畅,你甚至会不想回到使用C语言的时期,不信?就让我们拭目以待叭

二. STL概要

2.1 什么是STL

        把STL说得那么神,那STL究竟是什么呢?

        STL(standard template libaray - 标准模板库)C++标准库的重要组成部分。其不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。有了STL后,像先前我们写的链表、顺序表、排序算法等等常见的底层数据结构和算法我们就可以不用自己造轮子了,我们可以站在前人的肩膀上,快速的进行开发。

2.2 STL的六大组件

        STL主要由以下六大组件构成:

        在后续的学习中,我们会逐个接触到,到时我们在进行详细讲解。

2.3 STL的缺陷

        尽管STL功能十分强大,但也存在着一些缺陷,下面我们列出了几点:

1. STL库的更新太慢了。上一版靠谱是C++98,中间的C++03基本没有修订,到C++11出来已经相隔了13年,STL才进一步更新。
2. STL目前没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。
3. STL极度的追求效率,导致内部实现比较复杂。比如类型萃取,迭代器萃取。
4. STL的使用会有代码膨胀的问题,比如同时使用vector<int>,vector<double>,vector<string>时会生成多份代码,当然这是由于模板语法本身导致的。

三. string类概述

3.1 什么是string类

        string是C++标准库中用来表示字符序列的类,其中包含了许多关于操作单字节字符串的接口。string在底层实际上是basic_string模板类的别名,如下所示:

typedef basic_string<char, char_traits, allocator> string;

        可以看到,string是basic_string类模板的一个实例,其用char来实例化basic_string类模板,即string中存储的数据类型是char类型。故string只能用于处理单字节的序列,不能操作多字节或者变长字符的序列。

        string类的接口与常规容器的接口基本相同,只是添加了一些专门用来操作字符串的常规操作。

3.2 为什么要使用string类

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

四. string类的使用

4.1 包含头文件

        首先,要使用string类,我们需要包含<string>头文件,并且由于string定义在命名空间std中,我们还需使用命名空间std,如下所示:

#include<string>
using namespace std;

接下来,我们将逐一介绍string的一些常用接口,由于string的接口以及重载版本非常多,详情读者可以参考以下链接:string - C++ Reference (cplusplus.com)icon-default.png?t=N7T8https://legacy.cplusplus.com/reference/string/string/?kw=string

4.2 构造函数

        string也是个类,使用类时我们首先关注的就是它的构造函数,string常见的构造函数如下所示:

        使用方式如下所示: 

void test_constructor()
{
	string str1; //无参构造
	string str2("abcd"); //C字符串构造
	string str3(str2); //拷贝构造
	string str4(str3, 1, 2); //子串构造
	string str5(str2.begin(), str2.begin()+3); //迭代器构造
}

这里有个小问题:在子串构造中,npos的含义又是什么呢?它的定义如下:

static const size_t npos = -1;

由于size_t是无符号整形,而-1在内存中二进制表示为全1,故将-1赋值给npos后npos实际上是2^32-1,是一个非常大的数。

而string规定如果指定的长度len超过字符串的长度则只截取到字符串末尾,故将len的缺省值设置为npos的作用是当用户没有指定子串长度时默认截取到字符串末尾。

4.3 赋值运算符重载

        string重载了赋值运算符以便我们进行两个string对象之间的赋值,函数原型及说明如下所示:

         使用方式如下所示:

void test_assign()
{
	string str1("abcd");
	string str2 = "ab"; //注意,这里不是赋值重载,这里是定义并初始化str2,故调用的是构造函数
	str2 = str1; //这里才是赋值重载,用string对象赋值
	str2 = "aaaa"; //用一个C字符串赋值
	str2 = 'c'; //用一个字符赋值,此时str2的长度变为1
}

4.4 容量操作

        string类提供了许多与字符串容量相关的接口,如下表所示:

下面有几点注意事项

  1. size()与length()方法底层实现原理完全相同,string出现得比STL早,那时string只有length方法,后面引入size()的原因是为了与其他STL容器的接口保持一致,一般情况下基本都是用size()
  2. clear只是把有效字符的个数清空,不会改变底层空间的大小。
  3. reverse()的作用是为string保留空间,其不改变有效元素个数,当reserve的参数n小于
    string的底层总容量大小时,reserver不会改变容量大小。
  4. 使用reverse()时,有时编译器实际分配的大小会比我们指定的空间,这取决于编译器,不过并不会造成什么影响,我们无需过多关心。

         使用方式如下所示: 

void test_capacity()
{
	string str1 = "hello world";
	cout << "size : " << str1.size() << endl; //输出有效字符长度
	cout << "lenfth : " << str1.size() << endl;
	cout << "capacity : " << str1.capacity() << endl; //输出当前的总容量
	str1.resize(5); //重新指定有效字符的长度
	cout << "size : " << str1.size() << endl;
	str1.reserve(20); //为字符串保留长度为20的空间
	cout << "capacity : " << str1.capacity() << endl;
	cout << "size : " << str1.size() << endl;
	str1.clear(); //清空有效字符
	cout << "empty : " << str1.empty() << endl; //判断字符串是否为空
	cout << "size : " << str1.size() << endl;
}

4.5 访问/遍历操作

        访问操作 

        遍历操作

        通过上面的操作,我们就可以轻松地对一个string对象进行遍历访问了,至于迭代器是什么,目前我们可以把它当做一个原生指针来使用,后面我们再进行详细介绍。元素访问和遍历的演示如下所示:

void  test_access()
{
	string str1("hello world");
	cout << "front : " << str1.front() << endl;
	cout << "back : " << str1.back() << endl;

	cout << "下标遍历:" << endl;
	for (int i = 0; i < str1.size(); i++)
	{
		cout << str1[i];
	}
	cout << endl;

	cout << "正向迭代器遍历:" << endl;
	string::iterator it = str1.begin();      //iterator类型在string的类域中,要加作用域限定符
	//auto it = str1.begin();  //也可以使用auto自动推导类型
	while (it != str1.end())
	{
		cout << *it;  //可以看做原生指针使用
		it++;
	}
	cout << endl;

	cout << "反向迭代器遍历:" << endl;
	string::reverse_iterator rit = str1.rbegin();      //反向迭代器的类型为reverse_iterator
	while (rit != str1.rend())
	{
		cout << *rit;  //可以看做原生指针使用
		rit++;
	}

	cout << "范围for遍历:" << endl; 
	for (auto e : str1)
	{
		cout << e;
	}
}

注意事项:

  1. 由于迭代器类型是在类域内进行重定义的,故我们要使用作用域限定符::指定其类域。
  2. 对于[ ]运算符和at方法,一般更喜欢使用[ ]进行访问,原因方括号更简便且顺手。
  3. 范围for遍历的实现原理实际上就是替换编译器会自动将范围for的代码替换为迭代器进行遍历。我们可以调试并对比二者的汇编验证:

4.6 查找修改操作

         和C语言的常量字符串相比,C++的string对象是可修改的,string类中的字符串是保存在堆空间上的。下面是string类中一些常见的查找和修改接口:

        查找操作

        使用方式如下所示: 

void test_find()
{
	string str1("hello world hello");
	string str2("hello");
	char ch = 'o';
	cout << "从前往后str2第一次出现的下标为:" << str1.find(str2) << endl;
	cout << "从前往后ch第一次出现的下标为:" << str1.find(ch) << endl;
	cout << "从后往前str2第一次出现的下标为:" << str1.rfind(str2) << endl;
	cout << "从后往前ch第一次出现的下标为:" << str1.rfind(ch) << endl;
}

        修改操作

        使用方式如下所示: 

void test_modify()
{
	string str1("hello");
	str1 += "world";
	cout << str1 << endl;
	str1.push_back('!'); //尾插单字符
	cout << str1 << endl;
	str1.append("haha");  //追加字符串
	cout << str1 << endl;

	string str2("hehe");
	str1.swap(str2); //交换
	cout << "str1 = " << str1 << endl;
	cout << "str2 = " << str2 << endl;
}

注意事项:

        一般我们在进行插入时,使用+=运算符会比较多,因为+=不仅可以用来插入字符,也可以用来插入字符串。

4.7 子串操作

        除此之外,string类还有两个较常用的接口,一个用于快速截取子串,一个用来获取C格式的字符串,如下所示:

        使用方式如下所示: 

void test_substr()
{
	string str1 = "hello world";
	string str2 = str1.substr(1, 8);  //截取从下标1处到下标8处的子串  
	cout << str2 << endl;
	cout << str2.c_str() << endl;  //获取C格式的字符串
}

4.8 非成员函数

        最后,除了上面定义在string类内的成员函数,C++还定义了一些全局函数对string对象进行操作,典型的例子就是我们的流提取(>>)流插入(<<)运算符,这两个只能作为全局函数重载。具体的一些接口如下所示:

        使用方式如下所示: 

void test_general()
{
	string str1, str2;
	cout << "请输入一个字符串 :";
	cin >> str1;
	cout << "str1 = " << str1 << endl;
	cin.get();    //这里输入流中会剩下一个'\n',用get方法读取掉,否则getline遇到'\n'会直接停下来
	cout << "请输入一个字符串 :";
	getline(cin, str2);
	cout << "str2 = " << str2 << endl;

	if (str1 > str2)
		cout << "str1 > str2";
	else if(str1 < str2)
		cout << "str1 < str2";
	else 
		cout << "str1 == str2";
}


 以上,就是本期的全部内容啦🌸

制作不易,能否点个赞再走呢🙏

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

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

相关文章

Redis之Java操作Redis的使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Redis实战开发》。&#x1f3af;&#x1f3af; …

07 点积

点积 基本运算几何解释投影运算和基本运算的联系多维空间到一维空间的投影 点积的作用 这是关于3Blue1Brown "线性代数的本质"的学习笔记。 基本运算 两个维数相同的向量 [ 2 , 7 , 1 ] T , [ 8 , 2 , 8 ] T [2, 7, 1]^{T},[8, 2, 8]^{T} [2,7,1]T,[8,2,8]T,求它们…

Spring Boot 整合RabbitMQ

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

【m98】abseil-cpp的cmake构建

m79的代码有些头文件没有,比如#include "absl/numeric/bits.h"使用m98版本里的代码,支持cmake构建cmake版本 WIN32 DEBUG configure Selecting Windows SDK version 10.0.22000.0 to target Windows 10.0.22621. The CXX compiler identification is MSVC 19.37.32…

第七章 Python常用函内置函数

系列文章目录 第一章 Python 基础知识 第二章 python 字符串处理 第三章 python 数据类型 第四章 python 运算符与流程控制 第五章 python 文件操作 第六章 python 函数 第七章 python 常用内建函数 第八章 python 类(面向对象编程) 第九章 python 异常处理 第十章 python 自定…

解决Visual Studio 2010 运行时屏幕一闪而过,无结果显示的问题

安装配置&#xff1a;Visual Studio 2010 软件安装教程&#xff08;附下载链接&#xff09;——计算机二级专用编程软件https://blog.csdn.net/W_Fe5/article/details/134218817?spm1001.2014.3001.5502 1、 我们在运行时会出现窗口一闪而过&#xff0c;这时候我们右键Test_1…

C++初阶-类和对象(中)2

类和对象&#xff08;中&#xff09;2 一、赋值运算符重载运算符重载赋值运算符重载前置和后置重载 二、日期类的实现三、const成员四、取地址及const取地址操作符重载 一、赋值运算符重载 运算符重载 C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是具有特殊…

​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​

软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】 课本里章节里所有蓝色字体的思维导图

c语言练习100(贪吃蛇的实现)

贪吃蛇的实现 先实现主界面&#xff0c;后续将会不断完善。&#xff08;逐渐添加更多的功能&#xff09; test.c #define _CRT_SECURE_NO_WARNINGS #include"snake.h" void Test() {Snake snake { 0 };//创建贪吃蛇//1.游戏开始 - 初始化游戏GameStart(&sn…

类锁和实例对象锁你分清了吗?

系列文章目录 文章目录 系列文章目录前言一、什么是锁竞争&#xff1f;二、什么是类锁&#xff1f;什么是实例对象锁&#xff1f;三、给类对象加锁不是锁住了整个类四、总结 前言 java选手们应该都对锁不陌生&#xff0c;加锁了就是为保证操作语句的原子性&#xff0c;如果你是…

二AcW826. 单链表

#include<iostream>using namespace std;const int N100010;//head头结点下标//e[i]值//ne[i]下一个位置的地址//idx当前已经用到了哪个点int head, e[N],ne[N],idx;void init(){head-1;idx0; }void add_to_head(int x)//插到head{e[idx]x;ne[idx]head;//以前head指针是指…

多媒体应用设计师 2023年(含答案回忆版)

以下是小红书上的回忆版 软考考完疯狂回忆&#xff0c;多媒体应用设计师选择题 1.pattern 2.effective 3.merge 4.applications 5.graphic 6.udp 7.rtp 8.rtsp 9.10cm 10.永久 11…97 12.工作技术管理标准 13.管理型元数据 14.premiere 15.wave 16.500km/h 17.3M 18.44000 19.…

11.1~11.2数电实验一些点+11.4~11.5报错复盘

方框写在前面是说这个数有多大&#xff0c;写在后面是说这类数有多少 前面的用于计数&#xff0c;每位无实际意义&#xff1b;后面每位都代表一个同类型的&#xff0c;即数组&#xff0c;每位有实际意义 使用四位格雷码作为深度为8的FIFO的读写指针 将格雷码转换成四位二进制…

Amlogic IR模块Linux驱动分析

目录 一、简介 1、了解IR协议 2、代码结构介绍 二、硬件原理及连接 2、芯片手册解读 三、驱动代码分析 1、设备树介绍 1&#xff09;reg 2&#xff09;protocol 3&#xff09;pinctrl 4&#xff09;map 2、linux驱动介绍 1&#xff09;makefile 2&#xff09;数据…

【C++--string模拟实现】

一、基本思路 新建一个项目&#xff0c;在项目中创建头文件string.h 源文件string.cpp 在头文件中&#xff0c;先定义一个新的命名空间&#xff08;为了防止与库中的string发生冲突&#xff09;&#xff0c;命名空间的名字可以按照自己意愿来命名。 接下来就可以在命名空间中…

高斯过程回归 | 高斯过程回归(GPR)区间预测

对于高斯过程,高斯指的是多元高斯分布,过程指的是随机过程。 我们都知道随机过程就是指函数的分布,那么多元高斯分布实际上应该是指无限元的高斯分布。 协方差函数也称为核函数,是高斯过程回归的重点。核函数的选取方式有很多,包括径向基函数(高斯核函数)、线性核函数、…

C++相关练习及详细讲解

目录 题1&#xff1a;输出数组中第k小的数在数组内找出查找数字在该数组第一次出现的索引 题1&#xff1a;输出数组中第k小的数 题目描述&#xff1a; 给定一个数组arr 输出数组中第k小的数 如果不存在 输出-1 输入格式&#xff1a; 第一行输入一个数字n 代表数组arr大小 第二…

S32K324 UDS Bootloader开发-下位机篇-Bootload软件(1)

文章目录 前言启动过程Bootloader开发链接文件编译文件跳转函数CAN收发相关发送接收初始化及使能CAN周期函数总结前言 上一篇文章介绍了S32K324 -UDS Bootlodaer开发中的需求,本文根据需求开发Bootloader软件。 本文参考NXP官网的S32K324 UBL,其中有一些Bug,也有一些和上位机…

C++ 实现红黑树

红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路 径会比其他路径长出俩倍&#xff0c;因…

SMART PLC开放式以太网通信(UDP通信)

西门子S7-200 SMART PLC不仅支持开放式以太网通信,还支持MODBU-RTU,以及ModbusTcp通信,详细内容请参考下面文章: MODBUS-RTU主站通信 【精选】PLC MODBUS通信优化、提高通信效率避免权限冲突(程序+算法描述)-CSDN博客文章浏览阅读2.5k次,点赞5次,收藏10次。MODBUS通讯…