当前位置: 首页 > news >正文

【C++】String类:标准库介绍

目录

一.预备知识

1.auto关键字

2.范围for

3.迭代器

二.标准库里的string

1.string类的基本介绍

2.构造函数

​编辑

3.访问及遍历操作

3.1 operator []

3.2 基于范围for 

3.3 使用迭代器

4.迭代器

5.容量操作

 5.1 size和length

5.2 capacity

5.3 reserve和resize 

6.修改操作 

6.1 operator+= 和 append

 6.2 insert

6.3 erase

​编辑

7.查找操作

7.1 find

7.2 rfind

7.3 substr


一.预备知识

1.auto关键字

在C++11中,标准委员会赋予了auto全新的含义:作为一个类型指示符来指示编译器在编译时期推导变量的类型。这使得代码更简洁,尤其是在处理复杂的类型时。

用法示例:

        

1.声明普通变量

auto x = 1; // x 的类型被推断为 int
auto y = 1.11; // y 的类型被推断为 double

2.声明指针变量

int i = 10;
auto p = &i; // p 的类型被推断为 int*
auto* q = &i; // q 的类型同样被推断为 int*

3.声明引用类型

int j = 20;
auto& r = j; // r 的类型被推断为 int&

4.在同一行声明多个变量

auto x1 = 1, x2 = 2; // 正确,x1 和 x2 的类型都推断为 int
auto y1 = 1, y2 = 3.14; // 错误,y1 和 y2 的类型不同

5.auto不能直接声明未初始化变量(需要初始值设定)

6.auto不能作为函数的参数

// 错误用法
void func(auto n) 
{// ...
}

7.auto不能直接声明数组

// 错误用法
auto arr[5]; // 错误,无法推断数组类型

auto常在范围for中使用,接下来就介绍范围for 

2.范围for

对于一个有范围的集合而言,由程序员还说明循环的范围是多余的,有时候还容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号:分为两部分,冒号前是用于迭代的变量,冒号后是被迭代的范围,自动迭代,自动取数据,自动判断结束。

范围for可以作用到数组和容器对象(array、string、vector、list...)上进行遍历

int main()
{int array[] = { 1, 2, 3, 4, 5 };//遍历数组每一个值,都乘以2,结果为 2,4,6,8,10//自动识别类型,用引用能改变原值for (auto& e : array)e *= 2;//范围for遍历数组array并打印for (auto e : array)cout << e << ' ';cout << endl;//范围for遍历字符串str并打印string str("hello world");for (auto ch : str){cout << ch << ' ';}cout << endl;return 0;
}

范围for的底层很简单,容器的遍历实际上就是替换为迭代器,接下来就介绍迭代器 

3.迭代器

迭代器是一种数据类型,在C++中,迭代器实际上是一种对象,它被设计用于在容器中进行元素的遍历和访问。迭代器为程序员提供了一种抽象的方式来访问容器的内容,而不用关心容器的底层实现细节。

例如以下用法,目前还没正式讲到,可以看作一个指针来进行理解:其中string::iterator就是string类的迭代器类型,it是迭代器的变量名,将其看作指针,begin就是开头处,end就是结尾处,*it就是解引用该指针指向的内容,it++使得指针指向下一个内容,如此,大概就是迭代器的遍历操作

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

在string类的标准库和模拟实现中,会具体介绍并进行模拟实现,加深印象。

二.标准库里的string

1.string类的基本介绍

在C语言中,字符串是以'\0'结尾的字符数组,需要手动管理内存和处理字符串操作。在头文件string.h中提供了一系列库函数,如strlen、strcpy、strcat等来对字符串进行操作。但这些函数和字符串是分离的,需要手动管理内存,容易出现越界访问等问题。

因此,在C++标准库中,提供了string类,它封装了字符串操作,提供了丰富的成员函数和运算符重载,使得字符串的操作更加方便和安全。

实际上string类是C++标准库的一部分,学习标准库,是一定需要去读文档的,本文依照该string类的文档介绍进行:string - C++ Reference (plusplus.com)

string在底层实际是basic_string这个模板类使用char类型实例化得到的一个具体类,当然我们在使用时直接使用string即可,它本身就是basic_string<char>

2.构造函数

string作为一个类,构造函数是必不可少的,常用的如下几个:

构造函数名称功能说明
string()默认构造函数,构造空的string类对象,即空字符串
string(const string& s)拷贝构造函数
string(const char* s)用C-string(C风格的字符串)来构造
string(size_t n, char c)string类对象中包含n个字符c
#include<iostream>
using namespace std;
int main()
{string s1;string s2("abcdefg");string s3(10, 'a');string s4(s2);cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;return 0;
}

3.访问及遍历操作

3.1 operator []

重载下标操作符[ ],使得可以像访问数组一样使用下标来访问字符串中的某个字符,同时返回值是char&,这意味着我们还可以对该下标的字符进行修改等操作。

int main()
{string s1 = "abcde";//进行遍历,遍历方式类似于数组for (int i = 0; i < s1.size(); ++i){cout << s1[i] << " ";}cout << endl;//对下标为0的字符(即第一个字符)进行更改s1[0] = '0';cout << s1;return 0;
}

3.2 基于范围for 

int main()
{string s1 = "abcde";//只能遍历for (auto e: s1){cout << e << " ";}cout << endl;//若要进行更改,加&引用for (auto& e : s1){e = 'a';cout << e << " ";}cout << endl;return 0;
}

3.3 使用迭代器

在遍历的实现中,更推荐使用迭代器,因为迭代器是大多数数据结构都拥有的,而[ ]不是都有的,使用[ ] 要求物理底层是连续的,如数组等。

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

4.迭代器

迭代器是一种数据结构,在C++中,迭代器是一种对象,它被设计用于在容器中进行元素的遍历和访问。迭代器为程序员提供了一种抽象的方式来访问容器中的元素,而不用关心容器的底层实现细节。

 在string类中就有这四个比较重要的迭代器:

迭代器名称功能说明
begin()返回一个指向字符串中第一个字符的迭代器
end()返回一个指向字符串中最后一个字符的下一个位置的迭代器
rbegin()反向,返回一个指向字符串中最后一个字符的迭代器
rend()反向,返回一个指向字符串中第一个字符的前一个位置的迭代器

string类提供了很多类型的迭代器,包括正向迭代器(iterator)、常量正向迭代器(const_iterator)、反向迭代器(reverse_iterator)、常量反向迭代器(const_reverse_iterator)

  1.  正向迭代器(iterator):用于遍历可修改字符串的迭代器,可以通过begin()、end()方法来获取范围
  2. 常量正向迭代器(const_iterator):用于遍历不可修改的常量对象的迭代器,也可以通过begin()、end()方法获取范围
  3. 反向迭代器(reverse_iterator):用于反向遍历可修改的字符串的迭代器,可以通过rbegin()、rend()方法来获取范围
  4. 反向常量正向迭代器(const_reverse_iterator):用于反向遍历不可修改的常量对象的迭代器,也可以通过rbegin()、rend()方法获取范围

根据begin()的定义,可以发现这其实是一个重载,一个适用于非常量对象,一个适用于常量对象,返回的迭代器也因此不同,例如可以这样使用:

int main()
{string s = "abcde";const string cs = "abc";//会取寻找最合适的,此时非常量对象两者都可以,不过使用普通迭代器最合适string::iterator it = s.begin();//但是权限不能放大,只能缩小//不能使用普通迭代器去接收常量字符串的迭代器//因此用string::iterator cit = cs.begin()会报错//应该使用常量迭代器string::const_iterator cit = cs.begin();return 0;
}

其他的end();rbegin();rend()都是同理,此处不再赘述。

5.容量操作

函数名称功能说明
size()返回字符串有效字符长度(容器通用)
length()返回字符串有效字符长度(字符串专属)
capacity()返回当前分配给字符串的总空间大小
empty()检测字符串是否为空字符串
clear()清空字符串有效内容
reserve()为字符串预留空间
resize()将有效字符的个数改为n个,多出的空间用字符c填充

 5.1 size和length

两者的作用完全相同:都是返回字符串的有效长度,但是length是只适用于字符串string类的,而size是通用于容器的。

5.2 capacity

capacity()用于返回当前字符串对象分配的储存空间大小(即容量),字符串是存在容量的,这个容量就是指在不重新分配内存的情况下,字符串可以存储的最大字符数。

值得注意的是,capacity()返回的是字符串分配的总空间大小,而不是当前字符串的实际长度,也就是说,capacity()的返回值会大于size()的返回值,因为容量是一定大于等于实际储存的字符长度的,例如:

5.3 reserve和resize 

reserve有保留,预定的意思,功能就是为字符串预留至少n个字符的储存空间,也就是提前分配指定大小空间,好处是节约扩容成本。改变的是容量的大小,而不是实际有效字符的大小。

  • 当n大于当前容量时,reserve就会重新分配内存(可能扩容到n但也可能按其他方式进行扩容到比n大的数目)
  • 若n小于容量,有可能进行缩容也有可能不做处理,这取决于编译器和环境

但有一点是无可置疑的:reserve不会影响到字符串的实际大小与内容,size()的值一定不会变化

resize功能是调整字符串的实际大小为n。根据需要插入或删除字符,使得字符串的实际大小等于n

  • 若n小于当前字符串的实际大小,那么多余的字符将被删除,只剩下前n个字符
  • 若n大于当前字符串的实际大小,那么将用指定的字符c(不指定默认是'\0')来填充新增的部分

6.修改操作 

函数名称功能说明
operator +=在字符串后追加字符串
push_back在字符串后插入字符
append在字符串后追加字符串
insert插入字符(字符串)
erase删除字符

6.1 operator+= 和 append

将+=进行重载,用于将当前字符串与另外一个字符串进行连接,方便快捷,当然append也能做到该功能。

 6.2 insert

常用的两个, 1号是在pos这个下标位置前插入str字符串,2号是在pos下标前插入n个字符c

由于插入需要挪动数据,因此insert的效率其实并不高

6.3 erase

删除从下标pos出开始算起的len的字符,注意这里len的默认值是npos,需要补充说明一下npos

 

npos是C++中的一个静态成员变量,表示无效或不存在的位置。通常用于标识字符串查找等操作未找到匹配项的情况。npos的类型是size_t,值为-1,其补码就是全1,也就是最大的意思。 

7.查找操作

函数名称功能说明
find在字符串中查找指定的字符或子串
rfind在字符串中从右往左查找指定的字符或子串
find_first_of在字符串中从左往右查找指定集合中的任意字符
find_last_of在字符串中从右往左查找指定集合中的任意字符
find_first_not_of在字符串中从左往右查找不在指定集合中的最后一个字符
find_last_not_of在字符串中从右往左查找不在指定集合中的最后一个字符
substr从字符串中提取子串

7.1 find

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

7.2 rfind

整体和find类似。不过是从后往前找,找到一个字符或一个字符数组或一个string对象最后一次出现的位置,如果找不到就返回 npos

7.3 substr

从pos位置处开始截取len长度(默认截取到最后),下面以得到文件后缀为例:

int main()
{string s1("test.c");//得到文件后缀//从前往后找到第一个.的位置size_t pos1 = s1.find('.');//如果找到了就截取if (pos1 != string::npos){string ret1 = s1.substr(pos1);cout << ret1 << endl;}//如果文件名含有.怎么办string s2("te.st.c");//使用rfind从后往前查找倒数第一个.size_t pos2 = s2.rfind('.');if (pos2 != string::npos){string ret2 = s2.substr(pos2);cout << ret2 << endl;}return 0;
}

由于string类函数是很丰富的,这里不可能全部一一讲解,更多的需要在使用时去查阅相应的文档即可:<string> - C++ Reference (cplusplus.com)

在下一篇文章中将会具体自己模拟实现string类来加深理解,欢迎持续关注,感谢观看

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • HarmonyOS Next原生应用开发-从TS到ArkTS的适配规则(十六)
  • 使用Nexus3为containerd和docker配置镜像代理
  • 前端怎么用 EventSource并配置请求头及加参数(流式数据)
  • Hyperf 安装,使用,
  • 单一责任原则
  • CentOS7上安装RabbitMQ
  • 正则表达式入门:Python ‘ re ‘ 模块详解
  • C++内存泄漏--**关于“异常0xc0000005 读取的位置 0xDDDDDDDD时发生冲突”
  • Flask详细教程
  • <STC32G12K128入门第十步>USB HID键盘
  • 5年前端面试之路
  • 【LeetCode Cookbook(C++ 描述)】一刷二叉树综合(下)
  • “AI+Security”系列第2期(三):面向LLM(大语言模型)的漏洞挖掘与对齐防御研究
  • 橙色简洁大气体育直播自适应模板赛事直播门户自适应网站源码
  • YOLOv10:实时端到端目标检测
  • (三)从jvm层面了解线程的启动和停止
  • [nginx文档翻译系列] 控制nginx
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • Bytom交易说明(账户管理模式)
  • ECMAScript入门(七)--Module语法
  • HTTP请求重发
  • Java 内存分配及垃圾回收机制初探
  • js 实现textarea输入字数提示
  • Laravel 菜鸟晋级之路
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Linux各目录及每个目录的详细介绍
  • MobX
  • oschina
  • python3 使用 asyncio 代替线程
  • React的组件模式
  • Vue学习第二天
  • windows下mongoDB的环境配置
  • 翻译--Thinking in React
  • 浮现式设计
  • 高性能JavaScript阅读简记(三)
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 听说你叫Java(二)–Servlet请求
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 我的面试准备过程--容器(更新中)
  • 用Visual Studio开发以太坊智能合约
  • 阿里云ACE认证之理解CDN技术
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​Spring Boot 分片上传文件
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • #Linux(Source Insight安装及工程建立)
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • #图像处理
  • (42)STM32——LCD显示屏实验笔记
  • (C语言)fread与fwrite详解
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (动态规划)5. 最长回文子串 java解决
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (南京观海微电子)——示波器使用介绍