C++效率掌握之STL库:string函数全解

news/2025/2/26 19:22:35/

文章目录

  • 1.为什么要学习string?什么是string
  • 2.string类对象的常见构造
  • 3.string类对象的容量操作
  • 4.string类对象的迭代器
  • 5.string类对象的元素访问
  • 6.string类对象的元素修改
  • 7.string类对象的查找、提取、对比
  • 8.string类的非成员函数及npos
  • 希望读者们多多三连支持
  • 小编会继续更新
  • 你们的鼓励就是我前进的动力!

从本篇开始将开启C++里的STL库专题,网上有句话说:“不懂STL,不要说你会C++”。STL是C++中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发

stringstring_4">1.为什么要学习string?什么是string

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

因此创建了string类,比STL库还要早出现,所以有一定的缺陷和冗余

在这里插入图片描述

string的主要特征可总结为:

  1. 字符串是表示字符序列的类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
  3. string在底层实际是:basic_string模板类的别名
    typedef basic_string<char, char_traits, allocator> string
  4. 这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作

string_19">2.string类对象的常见构造

在这里插入图片描述

string作为一个类也有构造函数析构函数=运算符重载,我们重点介绍构造函数里的功能

函数名功能说明
string()构造空的string类对象,即空字符串
string (const char* s)C-string来构造string类对象
string (const string& str)拷贝构造函数
string (const char* s, size_t n)s 指向的字符数组中复制前 n 个字符
string (size_t n, char c)string类对象中包含n个字符c
string (const string& str, size_t pos, size_t len = npos)复制从字符位置 pos 开始并跨越 len 字符的 str 部分(或者直到 str 的末尾,如果 str 太短或 lenstring::npos)
string (InputIterator first, InputIterator last)按顺序复制范围 [first,last) 中的字符序列

💻代码测试示例:

#include string"><iostream>
#include string"><string>
using namespace std;int main()
{string s0(string">"Initial string");string s1;string s2(s0);string s3(s0, 8, 3);string s4(string">"Hello");string s5(string">"Best wish!", 4);string s6a(10, 'x');string s6b(10, 42);      // *的ASCII值是42string s7(s0.begin(), s0.begin() + 7);cout << string">"s1: " << s1 << string">"\ns2: " << s2 << string">"\ns3: " << s3;cout << string">"\ns4: " << s4 << string">"\ns5: " << s5 << string">"\ns6a: " << s6a;cout << string">"\ns6b: " << s6b << string">"\ns7: " << s7 << '\n';return 0;
}

⌨️代码输出示例:

在这里插入图片描述

string_66">3.string类对象的容量操作

在这里插入图片描述

通常在C语言阶段,想要知道字符串的长度,或者对其大小容量进行操作,都要自己手撕函数,不仅耗时还费力,所以string提供了现成的函数

函数名功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度(不常用)
max_size返回的是 string 理论上能够容纳的最大字符数
resize将有效字符的个数增加或减少 n 个,多出的空间用字符 c 或空格填充,少的截断字符串
capacity返回空间总大小,即容量
reserve为字符串增加预留空间,即增加预留容量
clear移除 string 对象中存储的所有字符
empty检测字符串释放为空串,是返回 true ,否则返回 false
shrink_to_fit请求 string 对象将其容量缩小到和当前字符串长度相匹配的大小

🔥值得注意的是:

  1. size()length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()
  2. clear() 只是将 string 中有效字符清空,即大小size缩为 0 ,不改变底层空间大小,即容量 capacity 不改变
  3. resize(size_t n)resize(size_t n, char c) 都是将字符串中有效字符个数改变到 n 个,不同的是当字符个数增多时:resize(n) 用空格来填充多出的元素空间,resize(size_t n, char c) 用字符 c 来填充多出的元素空间。注意:resize 在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变
  4. reserve(size_t res_arg=0):为 string 预留空间,不改变有效元素个数,当 reserve 的参数小于 string 的底层空间总大小时,reserver 不会改变容量大小

💻代码测试示例:

#include string"><iostream>
#include string"><string>
using namespace std;int main()
{string str(string">"Hello World!");cout << string">"size:" << str.size() << endl;cout << string">"lenth:" << str.length() << endl;cout << string">"max_size:" << str.max_size() << endl;cout << string">"capacity:" << str.capacity() << endl;str.reserve(100);cout << string">"reserve:" << str.capacity() << endl;str.resize(17, '*');cout << string">"resize:" << str << endl;str.shrink_to_fit();cout << string">"shrink_to_fit:" << str.capacity() << endl;str.clear();cout << string">"clear:" << str << endl;cout << string">"empty:" << str.empty() << endl;return 0;
}

⌨️代码输出示例:

在这里插入图片描述

string_127">4.string类对象的迭代器

在这里插入图片描述

迭代器(Iterator)是一种强大的抽象概念,它提供了一种统一的方式来访问和操作容器(如 stringvector 等)中的元素,简单来说就是提供了另一种遍历修改数据的方法

函数名功能说明
begin + end迭代器:begin 获取开头一个字符 + end 获取最后一个字符下一个位置
rbegin + rend反向迭代器:rbegin 获取最后一个字符 + end 获取开头一个字符上一个位置
cbegin + cendbegin + end 一样,但是常量迭代器只读
crbegin + crendrbegin + rend 一样,但是反向常量迭代器只读

🔥值得注意的是: 定义开头变量前的类型,可以用 auto 代替自动推导,避免了很长的类型,比如后续学习 map 的迭代器类型是这样的 std::map< std::string,std::string >::iterator ,就很有必要用 auto

💻代码测试示例:

#include string"><iostream>
#include string"><string>
using namespace std;int main()
{
string str(string">"Hello World!");string::iterator it1 = str.begin();
while (it1 != str.end())
{
cout << *it1 << ' ';
it1++;
}
cout << endl;string::reverse_iterator it2 = str.rbegin();
while (it2 != str.rend())
{
cout << *it2 << ' ';
it2++;
}
cout << endl;return 0;
}

⌨️代码输出示例:

在这里插入图片描述

string_177">5.string类对象的元素访问

在这里插入图片描述

string 的元素访问提供了能够像数组那样自由访问字符串中的数组的函数,极大的提高了字符修改的效率

🔥值得注意的是: at 用于访问指定位置元素的成员函数。与 operator[ ] 不同的是,at 会进行边界检查,如果传入的索引超出容器的有效范围,会抛出 std::out_of_range 异常

函数名功能说明
operator[ ]像数组一样,使用方括号语法来访问其内部数据
at访问指定位置元素
back返回容器中最后一个元素的引用
front返回容器中第一个元素的引用

💻代码测试示例:

#include string"><iostream>
#include string"><string>
using namespace std;int main()
{
string str(string">"Hello World!");cout << string">"operator[ ]:" << str[11] << endl;
cout << string">"at:" << str.at(10) << endl;
cout << string">"back:" << (str.back() = '~') << ' ' << str << endl;
cout << string">"front:" << (str.front() = 'h') << ' ' << str << endl;return 0;
}

⌨️代码输出示例:

在这里插入图片描述

string_216">6.string类对象的元素修改

在这里插入图片描述

string 还提供了 一系列像修改链表那样能够修改字符串的函数

函数名功能说明
operator+=字符串后追加字符串 str
append字符串后追加字符串 str
push_back字符串后尾插字符 c
assign将新的内容赋值给字符串
insert在容器的指定位置插入元素
erase从容器里移除指定的元素或元素范围
replace在容器或字符串中替换特定元素或子串
swap交换两个 string 对象的内容
pop_back移除 string 中的最后一个元素

🔥值得注意的是:

  1. string 尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c' 三种的实现方式差不多,一般情况下 string 类的 += 操作用的比较多,+= 操作不仅可以连接单个字符,还可以连接字符串
  2. string 操作时,如果能够大概预估到放多少字符,可以先通过 reserve 把空间预留好

💻代码测试示例:

#include string"><iostream>
#include string"><string>
using namespace std;int main()
{string str;cout << string">"operator+=:" << (str += string">"hello") << endl;cout << string">"append:" << str.append(string">" world") << endl;str.push_back('!');cout << string">"push_back:" << str << endl;str.assign(string">"new word");cout << string">"assign:" << str << endl;str.insert(8, string">"!!!");cout << string">"insert:" << str << endl;str.erase(8, 3);cout << string">"erase:" << str << endl;str.replace(0, 3, string">"fashion");cout << string">"replace:" << str << endl;string tmp(string">"happy day!");swap(tmp, str);cout << string">"swap:" << str << endl;str.pop_back();cout << string">"pop_back:" << str << endl;return 0;
}

⌨️代码输出示例:

在这里插入图片描述

string_281">7.string类对象的查找、提取、对比

在这里插入图片描述

string 也提供了一些查找、提取、对比的函数分配器(allocator)是标准库中一个重要的组件,它将内存分配和对象构造分离,使得容器的内存管理更加灵活

函数名功能说明
c_str返回 C 格式字符串
data返回一个指向字符串内部字符数组的指针
get_allocator获取容器当前使用的分配器实例
copy将字符串的一部分复制到一个字符数组中
find在字符串中查找子字符串或字符第一次出现的位置
rfind在字符串中从后往前查找指定的子字符串或字符
find_first_of查找字符串中任意参数在另一个字符串中第一次出现的位置
find_last_of从后往前查找字符串中任意参数在另一个字符串中第一次出现的位置
find_first_not_of在字符串中查找第一个不在指定字符集中的字符
find_last_not_of从后往前在字符串中查找第一个不在指定字符集中的字符
substr从字符串中提取子字符串
compare对两个字符串进行比较

🔥值得注意的是:

  1. c_str() 返回的是一个 const char* 类型的指针,这意味着不能通过该指针修改其所指向的字符串内容
  2. C++11 开始,string::data()string::c_str() 的行为基本一致,都会返回一个以 '\0' 结尾的字符数组指针
  3. 对于 copy,目标字符数组必须有足够的空间来容纳要复制的字符,并且需要手动添加字符串结束符以形成有效的 C 风格字符串
  4. find系列没找到就返回npos
  5. 对于 compare,逐个比较,如果当前字符串小于比较对象,返回一个负整数;如果当前字符串等于比较对象,返回 0 ;如果当前字符串大于比较对象,返回一个正整数

💻代码测试示例:

#include string"><iostream>
#include string"><string>
#include string"><cstdio>
using namespace std;int main()
{string str(string">"Hello World");const char* str1 = str.c_str();printf(string">"c_str:%s\n", str1);const char* str2 = str.data();printf(string">"data:%s\n", str2);char buffer[10];str.copy(buffer, 5, 0);buffer[5] = '\0';cout << string">"copy:" << buffer << endl;string subStr = string">"World";int pos1 = str.find(subStr);cout << string">"find:" << pos1 << endl;int pos2 = str.rfind('h');cout << string">"rfind:" << pos2 << endl;int pos3 = str.find_first_of(subStr);cout << string">"find_first_of:" << pos3 << endl;int pos4 = str.find_last_of(subStr);cout << string">"find_last_of:" << pos4 << endl;int pos5 = str.find_first_not_of(subStr);cout << string">"find_first_not_of:" << pos5 << endl;int pos6 = str.find_last_not_of(subStr);cout << string">"find_last_not_of:" << pos6 << endl;string Substr = str.substr(0, 5);cout << string">"substr:" << Substr << endl;cout << string">"compare:" << str.compare(subStr);return 0;
}

⌨️代码输出示例:

在这里插入图片描述

stringnpos_363">8.string类的非成员函数及npos

在这里插入图片描述

正是有了非成员函数,才能实现大小交换、自定义交换、输出输入等操作,npos 也提供了一种特殊表达方式

函数名功能说明
npos值为-1,表示查找操作失败或者某个位置不存在
operator+将两个字符串拼接
relational operators大小比较
swap交换两个 string 对象的内容
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串

🔥值得注意的是:

  1. npos 值为 -1 ,被定义为 size_t 类型的最大值。-1 原码为 1000 ... 0001 ,补码则为1111 ... 1111 ,但赋给 size_t 时,符号位就用不了了,所以整个补码就为 size_t 能表示的最大值表示查找操作失败或者某个位置不存在
  2. stringoperator+ 尽量少用,因为传值返回,导致效率低
  3. 当使用 >> 读取字符串时,它会在遇到空白字符(如空格、制表符、换行符等)时停止读取;getline 函数会读取输入流中的一行文本,直到遇到换行符为止,也就是遇到空格不会停止

💻代码测试示例:

#include string"><iostream>
#include string"><string>
using namespace std;int main()
{string str1(string">"Hello ");string str2(string">"World");cout << string">"npos:" << str1.npos << endl;cout << string">"operator+:" << (str1 + str2) << endl;cout << string">"relational operators:" << (str1 < str2) << endl;swap(str1, str2);cout << string">"swap:" << str1 << string">" " << str2 << endl;return 0;
}

⌨️代码输出示例:

在这里插入图片描述


希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述


http://www.ppmy.cn/news/1575073.html

相关文章

Python的那些事第三十一篇:快速数据帧处理与可视化的高效工具Vaex

Vaex:快速数据帧处理与可视化的高效工具 摘要 在大数据时代,高效的数据处理和可视化工具对于数据科学家和分析师至关重要。Vaex作为一种开源的Python库,专为处理超大数据集而设计,通过惰性计算、内存映射和并行化技术,显著提升了数据处理的效率和性能。本文详细介绍了Va…

如何使用ArcGIS Pro高效查找小区最近的地铁站

ArcGIS Pro与生活应用 ArcGIS Pro不仅广泛应用于城市规划、环境保护、资源管理等专业领域&#xff0c;其强大的地理信息处理和分析能力同样能为我们的日常生活带来便利。 通过简单的操作&#xff0c;ArcGIS Pro能够迅速为我们揭示地理位置之间的内在联系&#xff0c;如查找最…

Ollama部署本地大模型DeepSeek-R1-Distill-Llama-70B

文章目录 一、下模二、转模1. 下载转换工具2. 安装环境依赖3. llama.cpp1. 转换脚本依赖2. llama.cpp安装依赖包3. llama.cpp编译安装4. 格式转换 三、Ollama部署1. 安装启动Ollama2. 添加模型3. 测试运行 一、下模 #模型下载 from modelscope import snapshot_download model…

在 compare-form.vue 中添加 compareDate 隐藏字段,并在提交时自动填入当前时间

在 compare-form.vue 中添加 compareDate 隐藏字段&#xff0c;并在提交时自动填入当前时间。 提交表单时存入的对象是FakeRegistration&#xff0c;这个对象里面有compareDate字段&#xff0c;刚好表格查询的对象也是FakeRegistration&#xff0c;所以表格展示的时间就是刚才…

显式指定 ChromeDriver 路径

‌1️⃣ 显式指定 ChromeDriver 路径‌ 在代码中直接传递驱动路径&#xff0c;绕过 Selenium Manager 的自动检测&#xff1a; pythonCopy Code from selenium import webdriver from selenium.webdriver.chrome.service import Service# 指定 ChromeDriver 绝对路径&#xf…

源码分享1:批量修改PDF文件名称

批量修改文件名称 运行效果解析 运行效果 执行后 36266郜一凡200304000038内部调拨 修改为 1234一二 200304000038 四个字的 解析 输入需要修改的文件目录 输入完成后 会将文件夹中的目录的 文件名 修改为 保留文件名中间部分 修改前缀和后缀 import os import re import t…

在线疫苗预约小程序(论文源码调试讲解)

第4章 系统设计 用户对着浏览器操作&#xff0c;肯定会出现某些不可预料的问题&#xff0c;但是不代表着系统对于用户在浏览器上的操作不进行处理&#xff0c;所以说&#xff0c;要提前考虑可能会出现的问题。 4.1 系统设计思想 系统设计&#xff0c;肯定要把设计的思想进行统…

微信小程序开发中CSS书写常见问题及最佳实践

在微信小程序中&#xff0c;存在一些CSS选择器的限制和特殊性。如后代选择器&#xff08;如 view button&#xff09;在微信小程序中可能无法按预期工作&#xff0c;我设置width改变按钮的默认宽度效&#xff0c;而更具体的选择器&#xff08;如 view button.btn&#xff09;则…