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

【C++STL】一文掌握 String 核心接口:从基础到实用!

前言:结束了上一阶段的学习,在有了一定的语法基础以后下面我们就要进入C++的STL部分,STL在C++中占有极其重要的地位,下面我们就走进STL的世界,开始STL部分的学习。

在这里插入图片描述

✨ 坚持用 清晰易懂的图解 + 代码语言, 让每个知识点都 简单直观
🚀 个人主页 :MSTcheng · CSDN
🌱 代码仓库 :MSTcheng · Gitee
📌 专栏系列

  • 📖 《C语言》
  • 🧩 《数据结构》
  • 💡 《C++由浅入深》

💬 座右铭“路虽远行则将至,事虽难做则必成!”

文章目录

  • 一,STL简介
    • 1.1 什么是STL?
    • 1.2 STL的六大组件
    • 1.3 如何学习STL
  • 二,第一个STL容器—string
    • 2.1 string的4个默认构造的使用
  • 三,初识迭代器
    • 3.1 使用迭代器遍历string
  • 四、string与容量有关的接口使用
    • 4.1 string成员函数功能说明表
  • 五、元素访问相关的接口
    • 5.1 元素访问函数功能表格
  • 六、修改相关的接口使用
    • 6.1 修改相关的函数说明表格
  • 七,string类非成员函数(全局函数)
    • 7.1 非成员函数功能表格

一,STL简介

1.1 什么是STL?

STL的概念:STL(Standard Template Library)是C++标准库的核心组成部分,提供了一套通用的模板类和函数,用于实现常见的数据结构和算法。

1.2 STL的六大组件

STL的六大组件是它的核心我们在学习STL的时候也是围绕着这六大组件来进行学习,下面看看六大组件都有哪些:

在这里插入图片描述

1.3 如何学习STL

STL提供了一套通用的模板和函数,用于实现常见的数据结构,那么这些函数和数据结构我们首先要学会使用,其实就是了解一下这些数据结构的底层是如何实现的。
所以学习STL的步骤就是1.学会使用 2.了解底层 (后面的STL学习都会按照这两个步骤来学习)

声明:下面各种成员函数和非成员函数的参数返回值,可以去string文档中查询,链接:cpluspuls.com

二,第一个STL容器—string

2.1 string的4个默认构造的使用

函数名称功能说明
string()构造空的string类对象,即空字符串(重点)
string(const char* s)用C风格字符串(C-string)构造string类对象(重点)
string(size_t n, char c)构造包含n个字符cstring类对象
string(const string& s)通过拷贝另一个string类对象构造新对象(重点)

我们先来看看库里面的一些函数重载:

在这里插入图片描述在这里插入图片描述

void TestString1()
{string s1;//创建一个空字符串对象string s2("hello world");//构造string s3(s2);//拷贝构造cout << s3 << endl;string s4(s2, 1, 8);//相当于memcopy//string s4(s1, 1, 60); cout << s4 << endl;string s6(s2, 1);//不写长度那就从1开始拷贝 直到s2被拷贝完cout << s6 << endl;const char* str1 = "hello word"; string s7(str1,5); //使用char* 的字符串构造cout << s7 << endl;string s8(100, '*');//将s8初始化成100个*cout << s8 << endl;//赋值运算符重载 s1.operator=()s1 = s2;s1 = "*******";cout << s1 << endl;
}

还有一个析构函数用于释放string内部的资源,在模拟实现部分会详细说明。

三,初识迭代器

3.1 使用迭代器遍历string

学习一个数据结构就要学会它的遍历,因为在使用数据结构的时候我们常常会修改数据结构内部的值,如果我们要一一进行修改那么就一定会用到遍历。在学习C语言的时候常见的遍历方式是使用for循环,while循环等,借助循环来遍历。而C++搞了一个新的遍历方式叫迭代器,它是所有容器的主流遍历方式,下面我们重点讲解它。

函数/语法功能说明
begin + endbegin获取字符串第一个字符的迭代器,end获取最后一个字符下一个位置的迭代器
rbegin + rendrbegin获取字符串最后一个字符的逆向迭代器,rend获取第一个字符前一个位置的逆向迭代器
范围for (C++11)支持更简洁的范围遍历方式,无需显式使用迭代器或下标

1、传统遍历方式

void TestString2()
{string s1("hello word!");const string s2("hello bite");//s1[0]++ -> s1.operator[](0)++  使用重载的方括号//第一种遍历方式 使用循环
//循环遍历字符串 并修改字符串  s1.size()是string类里的成员函数 返回的是字符串的大小for (size_t i = 0;i < s1.size();i++){s1[i]++;}cout << s1 << endl;
}

2、使用迭代器

void TestString3()
{string::iterator it1 = s1.begin();										
while (it1 != s1.end())
{
//it就是像指针一样的东西(*it1)++;//*it就可以拿到对应位置的数据 进行修改//(*it1)--;
}
cout << s1 << endl;//将迭代器使用在顺序表(vector)
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);//这里的vector模板有显示限定 int
vector<int>::iterator it2 = v.begin();
while (it2 != v.end())
{cout << *it2 << " ";++it2;
}
cout << endl;

在这里插入图片描述

const迭代器与普通迭代器

在这里插入图片描述

正向迭代器和反向迭代器

在这里插入图片描述

3、auto关键字

还有另外一种遍历方式就是使用范围for。但在介绍范围for之前我们先来介绍一下auto关键字

void auto_test()
{
//auto是C++11支持的一种能够自动识别类型的关键字 auto x = 10;auto y = 10.1;cout << x << endl;//自动推出类型为int类型cout << y << endl;//自动推出类型为double类型//auto声明引用类型时必须要使用&int& z = x;auto m = z;//这一步是赋值 如果想要m++ z和x也跟着++ 就要加上&即auto& m = z;m++;//用auto声明指针类型时,用auto和auto*没有任何区别auto p1 = &x;// 只能是指针auto* p2 = &x;
}

在这里插入图片描述

auto的注意事项:

  1. 当使用auto在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错。因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
  2. auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
  3. auto不能直接用来声明数组

4、范围for

void TestString4()
{string s1("hello world");for(auto e:s1){//范围for内部可以修改s1//e--;cout<<e<<endl;}//遍历vectorvector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);for (auto e : v){cout << e << " ";}cout << endl;
}

在这里插入图片描述

范围for的注意事项:

  1. 范围for的三个自动:自动迭代、自动取数据、自动判断结束。这一点相比于上面的迭代器又更加的方便了,原因在于它是自动的。
  2. 范围for可以作用到数组和其他的容器对象上进行遍历。
  3. 范围for的底层其实就是替换为了迭代器,这也是它为什么能够支持遍历其他容器的原因。

总结—迭代器的意义:
1: 统一类似的方式遍历修改容器
2: 算法脱离具体底层结构,和底层结构解耦
3: 算法独立模板实现针对多个容器处理

四、string与容量有关的接口使用

4.1 string成员函数功能说明表

函数名称功能说明
size(重点)返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回字符串分配的空间总大小
empty (重点)检测字符串是否为空串,是则返回 true,否则返回 false
clear (重点)清空字符串中的有效字符
reserve (重点)为字符串预留空间
resize (重点)将有效字符的个数调整为 n 个,多出的空间用字符 c 填充
void stringTest1()
{string s1("123456");//无论是s.size() 还是s.capacity()都是不包括\0的cout << s1.size() << endl;cout << s1.capacity() << endl; //capacity可能大于或等于字符串的长度 大于因为capacity底层会扩容cout << s1.length() << endl;//如果非空就打印if (!s1.empty()){cout << s1 << endl;}s1.clear();//清空字符串就是将size(有效数据个数)改成0cout << s1.size() << endl;string s2;size_t old = s2.capacity();cout << endl;cout << "s2.capacity:" << old << endl;//string的底层实际上就是一个顺序表,所以不断的往里面插入数据就会引发扩容逻辑for (size_t i = 0;i < 100;i++){s2.push_back('x');if (s2.capacity() != old){cout << "capacity:" << s2.capacity() << endl;old = s2.capacity();}}
//使用reserve 知道要开多少空间提前开好 避免多次扩容,提升效率s2.reserve(100);//扩容可以cout <<s2.capacity()<< endl;s2.reserve(5);//缩容不行cout <<s2.capacity()<< endl;//resize 插入数据 让size达到我们定义的n 个
// n > capacity > size;
string s2("123456");
cout << endl;
s2.resize(20, '#');//这里n给20 那么size就从原来的6变成20,第二个参数不给默认用空格填充
cout << "size:" << s2.size() << endl;
cout << "capacity:" << s2.capacity() << endl;
}

上面的接口在使用中有几点需要注意:

  1. resize接口是修改有效数据个数的接口,在改变元素个数时,如果是将元素个数增多,那么可能会影响capacity导致扩容,如果是将元素减少则底层总空间大小不变。
  2. reserve接口是修改string总空间的接口,它不会影响有效数据个数。在改变空间大小时,如果比原来空间大那么久扩容到指定的这个空间,如果比原来的空间小并不会将空间缩小!!!
  3. clear接口单纯修改有效数据个数,不改变底层的空间大小!

五、元素访问相关的接口

5.1 元素访问函数功能表格

函数名称功能说明区别
operator[] (重点)返回 pos 位置的字符,const string 类对象可调用若越界访问,行为未定义(可能崩溃或返回垃圾值)
at返回 pos 位置的字符,提供边界检查若越界访问,抛出 std::out_of_range 异常,安全性更高

:表格对比了两种访问字符串字符的方法,核心差异在于越界处理机制。

void stringTest3()
{//方括号操作符 本质是函数重载string s1("hello word!");s1[0]++;	cout << s1 << endl;//at用于返回该下标处的内容//cout << s1.at(2) << endl;s1.at(0)--;cout << s1 <<endl;//访问的下标越界 不属于当前空间 抛异常//s1.at(15);
}

六、修改相关的接口使用

6.1 修改相关的函数说明表格

函数名称功能说明
push_back在字符串末尾插入字符c
append在字符串后追加一个字符串
operator+= (重点)在字符串后追加字符串str
c_str (重点)返回C格式的字符数组
find + npos(重点)从字符串pos位置开始向后查找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始向前查找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符并返回
void test2()
{string s1("abcdefg");//string底层就是一个字符数组 对于string的操作就相当于对数组的操作s1.push_back('h');//push_back就是尾插往size位置处插入数据s1.push_back('i');s1.append("hello!JJJJ");//append就是往s1后面追加一个字符串cout << s1<< endl;//c_str()用于当使用C语言想要打开C++的文件时,test.cpp就是一个string类型
//但是C语言又没有string这种东西 但是可以使用c_str返回C语言底层的那个字符数组这样就可以打开文件了string filename("test.cpp");FILE* fout = fopen(filename.c_str(), "r");if (fout == nullptr){cout << "fopen error" << endl;return;}string s2("hello   world")size_t ret=s1.find(0," ");//find函数,从起始位置开始查找指定的字符,找到了返回该字符所在位置的下标//size_t ret2=s1.rfind(0," ")//refind接口就是从尾部开始倒着查找while (pos != string::npos)//npos 是string类里面定义的一个数据 它的类型是size_t 值为-1相当于是整型的最大值   所以npos就代表字符串能存储的最大长度pos!=npos就是说该位置如果不等于最大字符串长度 就说明找到了 否则就说明没找到 {s2[pos] = '#';//s2.replace(pos, 2,"##"); //replace接口 替换指定位置的字符pos = s2.find(' ',pos+2);}cout << s2 << endl;string s3=s2.substr(0, 5);//从s2中截取5个字符给s3cout << s3 << endl;
}

七,string类非成员函数(全局函数)

7.1 非成员函数功能表格

运算符/函数功能说明注意事项
operator+字符串拼接,返回新字符串对象传值返回导致深拷贝,频繁调用可能影响性能,建议少用
operator>> (重点)输入运算符重载,从输入流提取内容到字符串,遇空格终止需配合istream使用,注意处理缓冲区及错误状态
operator<< (重点)输出运算符重载,将字符串内容插入到输出流常用于日志打印或控制台输出,无格式限制
getline (重点)从输入流读取一行字符串(包括空格),可指定分隔符需清除换行符残留,避免与operator>>混用时出错
relational operators (重点)比较字符串大小(如==, !=, <, >等),按字典序逐字符对比区分大小写,比较前需确保字符串非空或已初始化
void stringTest8()
{
string s1("hello"), s2("hello");
cout << s1 << " " << s2 << endl;
string s3 = s1 + s2;//operator+用于字符串拼接
cout << s3 << endl;//流插入重载bool a = s1 == s2;//判断大小关系 有== >= <= < > !=
cout << a << endl;
//cin >> s1 >> s2;//流提取重载
//cout << s1 <<" "<< s2 << endl;string line;
//cin >> line;//流插入重载getline(cin, line);//获取一行字符串 区别与scanf scanf识别到空格就结束 
//而getline不同 getline是识别到换行才结束
cout << line << endl;
}

注意:这里的函数之所以搞成全局函数而不搞成string内部的函数是因为,如果搞成string内部函数那么第一个参数就定死了是string类型。因为成员函数中第一个参数要传给this指针,this指针的类型就是该类的类型。这些函数如果重载成成员函数就无法实现const char* 的类型作为参数了!

以上就是本篇文章的所有内容了,感谢各位大佬观看,制作不易还望各位大佬点赞支持一下!有什么问题可以加我私信交流!
http://www.dtcms.com/a/452786.html

相关文章:

  • 长沙宁乡建设网站网站本地环境搭建
  • 从以太网到多个 CAN 网络的网关
  • 网站做弹窗怀化职院网站
  • ros2 功能包 package.xml 结构详细解释
  • ros2 功能包 CMakeLists.txt 结构详细解释
  • 【Python】小练习-考察变量作用域问题
  • YOLO算法原理详解系列 第007期-YOLOv7 算法原理详解
  • 【C++贪心】P8087 『JROI-5』Interval|普及+
  • C++知识点总结用于打算法
  • 【算法】二分查找(一)朴素二分
  • 干货>肉夹馍词嵌入方案(embedding方案),适合资源受限、要求可解释、领域边界清晰的应用场景
  • PDML 不能和rebuild partition index同时运行
  • 网站目录管理模板做一个网站一般要多少钱
  • 对于力扣2025,10,7的每日的一点反思(非递归并查集写法)
  • Elasticsearch、OpenSearch 与 Easysearch:三代搜索引擎的演化与抉择
  • 以人为本视角下定制开发开源AI智能名片S2B2C商城小程序的营销价值与实践路径
  • AI智能体(Agent)大模型入门【5】--本地AI模型连接到PyCharm或者编译软件使用
  • INT305 Machine Learning 机器学习 Pt.3二元分类和多类分类
  • 拨付网站建设经费的请示防查水表 wordpress 评论
  • 从零开始学Flink:实时流处理实战
  • mysql全量+增量备份脚本及计划任务配置
  • 做微信商城网站哪家好权威网站建设公司
  • 湛江市微信网站建设企业药品行业做网站
  • 2024- Chrome 插件开发指南和实践
  • Apache Iceberg介绍、原理与性能优化
  • winlogon!StateMachineRun函数会用到核心数据结构winlogon中的重要全局状态机状态数组
  • 手机网站开发专业什么网站做二手货车
  • 做音乐网站代码wordpress app 读者
  • 高端品牌网站建设费用网站建设的建议和意见
  • 电子商务网站的建设 论文wordpress导入大小.h