【C++】string进一步介绍
个人主页 : zxctscl
如有转载请先通知
文章目录
- 1. 前言
 - 2. 迭代器
 - 2.1 反向迭代器
 - 2.2 const对象迭代器
 
- 3. Capacity
 - 3.1 size和length
 - 3.2 max_size
 - 3.3 capacity
 - 3.4 clear
 - 3.5 shrink_to_fit (了解即可)
 - 3.6 reserve
 - 3.7 resize
 
- 4. Element access
 - 4.1 operator[]
 - 4.2 at
 
- 5. Modifiers
 - 5.1 push_back
 - 5.2 append
 - 5.3 operator+=
 - 5.4 assign(了解即可)
 - 5.5 insert
 - 5.6 erase
 - 5.7 replace
 - 5.8 swap
 
- 6. String operations
 - 6.1 c_str
 - 6.2 find 和 substr
 - 6.3 rfind
 - 6.4 compare
 
- 7. Non-member function overloads
 - 7.1 operator+
 - 7.2 getline
 
1. 前言
在之前的博客中初步介绍了string一下: 【C++】string类初步介绍,那么这次来看看它的实现。
2. 迭代器
string类对象的访问及遍历操作:
| 函数名称 | 功能说明 | 
|---|---|
| operator[] (重点) | 返回pos位置的字符,const string类对象调用 | 
| begin+ end | begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器 | 
| 范围for | C++11支持更简洁的范围for的新遍历方式 | 
| rbegin + rend | rbegin反向迭代器以反向开始,end将迭代器返回到末尾 | 
2.1 反向迭代器
在前面的一篇中已经提到了前面三个,这次来看看反向迭代器。
 reverse_iterator:将给的字符串反向逆置。
 
void test_string3()
{string s1("hello,world");string::reverse_iterator rit = s1.rbegin();while (rit != s1.rend()){cout << *rit <<" ";rit++;}cout << endl;}
 

 rbegin给rit,rit!=rend,然后加加rit。它本身就是反过来的,所以得用加加。
 
 
2.2 const对象迭代器

 这里还有const对象的迭代器,他们两个有什么区别呢?
 const要用const迭代器(const_iterator),不能修改对象值。

**iterator是可读可写,const_iterator只读。**会根据自己属性去调用。
string::iterator it2 = s1.begin();while (it2 != s1.end()){*it2 += 3;cout << *it2 << " ";it2++;}cout << endl;const string s3("hello world");string::const_iterator it3 = s3.begin();while (it3 != s3.end()){cout << *it3 << " ";it3++;}cout << endl;
 

 
rbegin同样有两种。
 
 
 总共有四种迭代器:正向反向iterator,和正向反向const_iterator。用到最多是正向iterator。
3. Capacity

3.1 size和length
这里的size和length有什么区别呢?
 直接用代码来测试一下:
void test_string4()
{string s1("hello world");cout << s1.size() << endl;cout << s1.length() << endl;
}
 

 很显然,它们没有区别。有两个的原因是:string产生得比较早,没有出数据结构规范,在字符串长度取名字时候取的是length,后来stl出来之后,就增加了一个size。length是一个局限的取名,用size更统一。C++是两种都是兼容的。
3.2 max_size
在x86环境下来看看max_size有多大:

 但是不同平台的max_size可能有所不同。
3.3 capacity

来看看capacity大小:
 发现会比size要大
 
 
 来看看string的扩容机制:
 先取string当前的capacity,然后push_back,如果空间不够可能会引起capacity的变换;每次插入前获取新的capacity和旧的相比较看看相不相等,如果不相等,就把新的capacity赋值给旧的,并输出新的capacity。
    string s;size_t sz = s.capacity();cout << "making s grow:\n";cout << sz << endl;for (int i = 0; i < 100; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}
 
第一次扩容的是原基础的2倍,剩下的都是1.5倍
 
 
与linux的扩容机制是不同的。
 来看看linux的扩容机制:
 
 g++扩容是两倍扩:
 
 STL是一个规范,规定功能,没有规定实现细节。
3.4 clear

clear是指的清数据,空间不一定清理:
string s1("hello world");cout << s1.size() << endl;cout << s1.length() << endl;cout << s1.capacity() << endl;cout << s1 << endl;cout << s1.capacity() << endl;s1.clear();cout << s1 << endl;cout << s1.capacity() << endl;
 
capacity并没有改变。
 
就算将s1多输入字符,它的的capacity在clear后也不会改变;
 
3.5 shrink_to_fit (了解即可)
如果想要缩容用就要用shrink_to_fit :
 
string s1("hello worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");cout << s1.size() << endl;cout << s1.length() << endl;cout << s1.capacity() << endl;cout << s1 << endl;cout << s1.capacity() << endl;cout << s1.size() << endl;s1.clear();cout << s1 << endl;cout << s1.capacity() << endl;cout << s1.size() << endl;s1.shrink_to_fit();cout << s1 << endl;cout << s1.capacity() << endl;cout << s1.size() << endl;
 
这里缩容到15
 
3.6 reserve
注意区分:
 reserve是保留
 reverse是反转,翻转
reserve是用来扩容的。
 
string s;s.reserve(100);size_t sz = s.capacity();cout << "making s grow:\n";cout << sz << endl;for (int i = 0; i < 100; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}
 

 在linux里面:
 
 
 reserve会不会缩容呢?
 来看看代码:
string s1("hello worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");cout << s1.size() << endl;cout << s1.capacity() << endl;s1.reserve(20);cout << s1.size() << endl;cout << s1.capacity() << endl;
 
reserve是不会缩容的。
 reserve比capacity大才扩容。
 
3.7 resize
resize改变size。
 
resize有三种情况。
resize从三个角度来对它进行分析:
 假设这里size是17,capacity是32
 
- resize给的比size小,会删除
 
string s2("hello worldxxxx");cout << s2.size() << endl;cout << s2.capacity() << endl;s2.resize(10);cout << s2.size() << endl;cout << s2.capacity() << endl;
 

- resize给的在size和capacity之间,插入
 
   string s2("hello worldxxxx");cout << s2.size() << endl;cout << s2.capacity() << endl << endl;/*s2.resize(10);*/s2.resize(20);cout << s2.size() << endl;cout << s2.capacity() << endl;
 
默认插入\0
 
- resize给的比capacity大,扩容+插入
 


 总之:
 
 所以知道要插入多少数据,就提前开好空间,避免了扩容,提高了效率。
4. Element access

4.1 operator[]
在上一篇博客中已经提过了,有需要可以看看【C++】string类初步介绍
 
 在用[]越界是断言错误:
4.2 at

    string s1("hello world");cout << s1[6] << endl;cout << s1.at(6)<< endl;
 

 at与[]的越界报错不一样。
 用at越界时候报的是非法
5. Modifiers
5.1 push_back
尾插一个字符
 
 想尾插一个字符:
void test_string7()
{string s1("hello world");s1.push_back('!');cout << s1 << endl;
}
 

5.2 append
append尾插,可以插入一个字符,也可以插入字符串。
 
    string s1("hello world");/*s1.push_back('!');*/s1.append("!");cout << s1 << endl;s1.append("abcd");cout << s1 << endl;
 


 一般用得最多的就是:
 
5.3 operator+=
+=用起来就比较方便
来看个例子:
   string s1("hello world");s1 += ' ';s1 += "abc";cout << s1 << endl;
 

5.4 assign(了解即可)
assign赋值,字符覆盖
可以把当前字符覆盖:
	string s1("hello world");cout << s1 << endl;s1.assign("xxxxx");cout << s1 << endl;
 

5.5 insert
insert都是在当前位置的前面插入
 
 常用的就是:
 
 举个例子:
string s1("hello world");cout << s1 << endl;s1.insert(0, "abc");cout << s1 << endl;
 

5.6 erase
erase删除
 
 常用:
 
 如果这个内容太短小于npos,就全部删除。
举个例子:
string s1("hello world");cout << s1 << endl;/*s1.insert(0, "abc");*/s1.erase(5,10);cout << s1 << endl;
 

 erase不给值就直接删空了:
 
5.7 replace
replace替换
 
把pos位置,一个字符替换成两个xx:
    string s2("hello world");cout << s2 << endl;s2.replace(6, 1, "xx");cout << s2 << endl;
 

一般结合find()使用:
 

 来看个代码:
string s2("hello world hello abcd");size_t pos = s2.find(' ');while (pos != string::npos){s2.replace(pos, 1, "%20");pos = s2.find(' ');}cout << s2 << endl;
 

 insert erase replace要少用,因为基本上都要挪动数据,效率不高。
像替换这里还可以用范围for:
string s3;for (auto ch : s2){if (ch != ' '){s3 += ch;}else{s3 += "%20";}}cout << s3 << endl;
 

5.8 swap

 来看一个例子:把空格位置换成20%:
void test_string9()
{string s2("hello world hello abcd");string s3;s3.reserve(s2.size());for (auto ch : s2){if (ch != ' '){s3 += ch;}else{s3 += "20%";}}cout << s3 << endl;s2.swap(s3);cout << s2 << endl;
}
 

6. String operations

6.1 c_str
在C语言中有打开文件的操作,在c++里面要打开文件就要用到c_str,让它来兼容C语言。
 
 来个例子:
void test_string10()
{string s1("hello world");string filename("test.cpp");FILE* fout = fopen(filename.c_str(), "r");}
 
6.2 find 和 substr
find查找
 
substr去一个字符串的字串。

 如果想要拿到一个文件的后缀,就用find,但要将后缀拷贝下来就得用到substr。
 来看看简单的实现:
void test_string10()
{string s1("file.cpp");size_t pos1= s1.find('.');if (pos1 != string::npos){string suffix = s1.substr(pos1);cout << suffix << endl;}else{cout << "没有后缀" << endl;}
}
 

 
6.3 rfind
如果查最后一个序列怎么办呢?
 用rfind,从后往前找
 
void test_string10()
{string s1("file.cpp.tar.zip");size_t pos1= s1.rfind('.');if (pos1 != string::npos){string suffix = s1.substr(pos1);cout << suffix << endl;}else{cout << "没有后缀" << endl;}
}
 

 
 如果给的网站很多怎么按协议,域名,网址分开呢?
 
 协议到:,域名从i+3的位置开始,到第一个/就结束。网址就是剩下的部分
void test_string10()
{string url1("https://legacy.cplusplus.com/reference/string/string/substr/");string protocol, domain, uri;//协议,域名,网址size_t i1 = url1.find(':');if (i1 != string::npos){protocol = url1.substr(0, i1 - 0);cout << protocol << endl;}size_t i2 = url1.find('/',i1+3);if (i2 != string::npos){domain = url1.substr(i1+3, i2-(i1+3));cout << domain << endl;uri = url1.substr(i2+1);cout << uri << endl;}
}
 

6.4 compare
compare是按照ascii比较
 
    string str1("green apple");string str2("red apple");cout << (str1 < str2) << endl; 
r的ASCII比g的ASCII小:
 
7. Non-member function overloads

7.1 operator+

 来用代码实现一下:
    string ss1 = "xxx";string ss2 = "yyy";string ret = ss1 + ss2;cout << ret << endl;
 

还支持这样的写法:
   string ret1 = ss1 + "yyy";string ret2 =  "yyy"+ss2;cout << ret1 << endl;cout << ret2 << endl;
 

 
7.2 getline
getline获取一行。
 
 举个例子:获得一个字符串里面最后一个单词的长度
#include<iostream>
#include<string>
using namespace std;
int main()
{string line;// 不要使用cin>>line,因为会它遇到空格就结束了// while(cin>>line)while (getline(cin, line)){size_t pos = line.rfind(' ');cout << line.size() - pos - 1 << endl;}return 0;
} 
有问题请指出,大家一起进步!!!
相关文章:
【C++】string进一步介绍
个人主页 : zxctscl 如有转载请先通知 文章目录 1. 前言2. 迭代器2.1 反向迭代器2.2 const对象迭代器 3. Capacity3.1 size和length3.2 max_size3.3 capacity3.4 clear3.5 shrink_to_fit (了解即可)3.6 reserve3.7 resize 4. Element access4…...
思科设备下面主机访问公网经常时好时坏延迟大丢包不稳定
环境: 思科防火墙ASA5555 Cisco Adaptive Security Appliance Software Version 9.4(2)6 Device Manager Version 7.5(2)153 内外为DMZ区域 思科交换机(C3560E-UNIVERSALK9-M), Version 12.2(55)SE5 主机 centos 7 问题描述: 思科设备下面主机访问公网经常时好时坏不稳定…...
nuxtjs 如何通过ecosystem.config.js配置pm2?
在 Nuxt.js 项目中,您可以通过 ecosystem.config.js 文件来配置 PM2,以便使用 PM2 来管理 Nuxt.js 应用的进程。ecosystem.config.js 是一个特殊的配置文件,它允许您定义应用的各种属性,如脚本路径、环境变量、日志设置等。 下面…...
个人博客系列-后端项目-用户注册功能(7)
介绍 用户注册API的主要流程:1.前端用户提交用户名,密码 2. 序列化器校验用户名,密码是否合法。3.存入数据库。4.签发token 创建序列化器 from rest_framework import serializers from rest_framework_simplejwt.serializers import Toke…...
vue项目因内存溢出启动报错
前端能正常启动,但只要一改动就报错启动出错。 解决办法: 安装依赖 npm install cross-env increase-memory-limit 然后再做两件事:在node 在package.json 里的 script 里进行配置 LIMIT是你想分配的内存大小,这里的8192单位…...
UI 学习 二 可访问性 模式
教程:Accessibility – Material Design 3 一 颜色对比 颜色和对比度可以用来帮助用户看到和理解应用程序的内容,与正确的元素交互,并理解操作。 颜色可以帮助传达情绪、语气和关键信息。可以选择主色、辅助色和强调色来支持可用性。元素之…...
Spring学习
Maven 的配置文件是一个强约定的XML格式文件,它的文件名一定是pom.xml。 1、POM (Project Object Model) 一个 Java 项目所有的配置都放置在 POM 文件中,大概有如下的行为: 定义项目的类型、名字管理依赖关系定制插件的 1.maven坐标 <…...
鸿蒙开发-UI-动画-组件内转场动画
鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 鸿蒙开发-UI-图形-图片 鸿蒙开发-UI-图形-绘制几何图形 鸿蒙开发-UI-图形-绘制自定义图形 鸿蒙开发-UI-图形-页面内动画 文章目录 前言 一、基本概…...
Leet code 179 最大数
解题思路 贪心算法 贪心算法就是走一步看一步 每一步都取当前位置的最优解 这题我们该如何贪呢? 我们先把int数组转换为string数组 以示例2为例 3 30 34 5 9 排序哪个在前哪个在后? 3 30 (330)> 30 3 (30…...
swagger踩坑之请求类不显示具体字段
swagger踩坑之请求类不显示具体字段 省流:枚举字段需要加上ApiModelProperty注解 过程复现: TestEnum 枚举不加注解,swagger的UI类不显示详细字段 Data Accessors(chain true) ApiModel(value "test对象", description &quo…...
案例分析篇14:信息系统安全设计考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)
专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…...
前端之用HTML弄一个古诗词
将进酒 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>将进酒</title><h1><big>将进酒</big> 君不见黄河之水天上来</h1><table><tr><td ><img…...
Linux 安装使用 Docker
目录 一、前提卸载命令:执行情况: 二、安装 Docker1. 通过仓库进行安装(在线方式)1.1 设置存储库1.2 查看可安装版本1.3 安装 Docker1.4 启动 Docker1.5 验证是否成功 2. 通过 RMP 包安装(离线方式)2.2 安装…...
Doris部署学习(一)
目录 前言 一、Docker容器支持 二、Doris编译步骤 1.拉取镜像 2.构建Docker编译容器 3.下载源码并编译 前言 本文档主要介绍如何通过源码在Docker编译 Doris,以及部署。 一、Docker容器支持 Docker教程:Docker & Docker-Compose 安装教程 - 知…...
QT下跨平台库实现及移植经验分享
最近在移植公司一个QT桌面软件到android上,有一些公司自定义的库,用了很多windows的api,移植过程很是曲折,在此有一些感悟分享一下~ 一.自编写跨平台库 1.有时候为了程序给第三方用需要编译一些qt封装库,并可能跨平台…...
8:00面试,8:06就出来了,问的问题有点变态。。。
从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到9月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…...
Rust 利用 Trait 实现多态性
在Rust中,Trait(特性)是一种强大的抽象机制,类似于其他编程语言中的接口或类型类。它们允许你定义一组方法,这些方法可以在任何实现该Trait的类型上调用。这使得Rust能够以一种非常灵活的方式支持多态性。 下面是一个…...
Java毕业设计-基于springboot开发的“智慧食堂”设计与实现-毕业论文+答辩PPT(附源代码+演示视频)
文章目录 前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1.开发说明2.需求分析3、系统功能结构 三、系统实现展示1、系统登录2、系统功能模块3、管理员功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基于springboot开发的“智慧食堂”设计与…...
一瓶5.86万,听花酒什么来头?
听花酒,到底什么来头? 宣称有提升免疫力、改善睡眠、保障男性功能、调节生理紊乱、抗衰老等功效的听花酒,被315晚会曝光了。 相关话题词随即冲上了热搜。之后,售价最高达58600元的听花酒被京东、拼多多、淘宝等电商平台火速下架…...
代码随想录 二叉树—填充每个节点的下一个右侧结点指针
今天没精力看了 题解c: class Solution { public:Node* connect(Node* root) {if (root NULL) return NULL; // 基本情况queue<Node*> q;q.push(root);while (!q.empty()) {int size q.size();Node* prev NULL;for (int i 0; i < size; i) {Node* no…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
拟合问题处理
在机器学习中,核心任务通常围绕模型训练和性能提升展开,但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正: 一、机器学习的核心任务框架 机…...
FOPLP vs CoWoS
以下是 FOPLP(Fan-out panel-level packaging 扇出型面板级封装)与 CoWoS(Chip on Wafer on Substrate)两种先进封装技术的详细对比分析,涵盖技术原理、性能、成本、应用场景及市场趋势等维度: 一、技术原…...
