C++之spring

C++之spring

在这里插入图片描述

string类对象的访问及遍历操作

operator[]

返回pos位置的字符,const string类对象调用

在这里插入图片描述

这是一个既可以写也可以读的库函数,const修饰的内容是不可以更改的,所以是读

C++类与对象里要想普通对象和const修饰的对象同时重载

第二种访问及遍历操作就是:下标+[]

代码如下:

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1("hello world");for (size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";}cout << endl;
}

还有种写法:

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1("hello world");for (size_t i = 0; i < s1.size(); i++){s1[i]++;}}

这种写法使自定义类型像数组一样访问及遍历,也能得到相同的结果:

在这里插入图片描述

接下来再来引入一个概念:迭代器

可以理解为像指针一样的东西,它在堆上面开辟空间,因为可以动态调整大小

代码示例如下:

    //迭代器string::iterator it1 = s1.begin();//这么写是因为定义在string的类域里面while (it1 != s1.end()){cout << *it1 << " ";++it1;}cout << endl;
}

这里需要特别强调的是:end是最后一个数据的下一个位置,不是最后一个数据

运行结果如下:

在这里插入图片描述

可能string这里会显得迭代器有点繁琐,但是它是适用于所有容器通用的方法,下标+[]只适用于string,vector这样的底层是连续的物理结构,但是像链表就不太适合,运算符重载的效率就会大大降低,因为链表的地址没有大小关系

顺便说一句,begin和end相当于数学里面左闭右开的逻辑关系

可能会觉得while(it1!=s1.end())是否可以变成<,不建议这样,<只适合地址有大小关系的情况,!=更通用些

迭代器使用的例子:

#include <iostream>
#include <list>
using namespace std;
list <int> lt;//尾插lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);//迭代器的使用list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";//用法类似于指针的解引用//但是并不是指针,底层是运算符重载}cout << endl;

迭代器的逆置访问

例子如下:

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1("hello world");
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{cout << *rit << " ";++rit;
}
cout << endl;
}

打印结果:

在这里插入图片描述

反向,因为方向也是相反的,所以不是–而是++

const迭代器

const string s2(s1);//string::const_iterator it1 = s2.begin();  加上const,因为这是不能被修改的auto it1 = s2.begin();//换成auto关键字,提高效率,毕竟是块语法糖while (it1 != s2.end()){//*it1 += 1;    常量不能被修改cout << *it1 << " ";++it1;}cout << endl;
//反向//string::const_reverse_iterator rit1 = s2.rbegin();auto rit1 = s2.rbegin();while (rit1 != s2.rend()){cout << *rit1 << " ";++rit1;}cout << endl;

auto关键字

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个 不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型 指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期 推导而得

**用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加& **

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际 只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

**auto不能作为函数的参数,可以做返回值,但是建议谨慎使用 **

auto不能直接用来声明数组

示例如下:

int i=0;
int j=i;
//自动推导类型
auto z=i;
auto x=1.1;//double
auto p=&i;//int*
int &r1=i;
auto r2=r1;//int
auto &r3=r1;//int&

应用场景:

以后会学到map:它的底层涉及到红黑树,代码非常地长

std::map<std::string, std::string> dict;
std::map<std::string, std::string>::iterator dit = dict.begin();auto dit = dict.begin();
//会简便非常多

这是一种语法糖,可以简化代码,是懒人的福音

auto能否做函数的形参?

C++20才支持

auto能否作返回值?

可以,但是不是特别好,因为万一嵌套不写注释,就会很麻烦:

.....
auto func3()
{auto y=func4();
}
auto func2()
{auto x=func3();
}

范围for

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

范围for可以作用到数组和容器对象上进行遍历

范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。

例子1:

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1("hello world");
//范围forfor (char ch : s1){cout << ch << " ";}cout << endl;
}

运行结果:
在这里插入图片描述

但其实日常中我们会更喜欢前面的类型是auto,会更加地方便,让编译器在编译的时期进行推导

和引用结合的情况:

1)修改内容:

#include <iostream>
#include <string>
using namespace std;
int main()
{string s1("hello world");
//范围forfor (auto& ch : s1){ch++;cout << ch << " ";}cout << endl;
}

运行结果:
在这里插入图片描述

不加上引用,就不会有影响,因为这是赋值拷贝,并没有改变内容本身

2)容器比较大的情况

例如上面提到的map容器

并不是所有情况都适合使用范围for

因为它的底层是迭代器,迭代器只支持容器,范围for有个例外,支持数组

例子如下:

int a[] = { 1,2,3,4,5,6 };
for (size_t i = 0; i < sizeof(a) / sizeof(int); i++)
{cout << a[i] << " ";
}
cout << endl;
for (auto e : a)
{cout << e << " ";
}
cout << endl;

运行结果:

在这里插入图片描述

也就是说范围for适用于容器和数组

string类对象的容量操作

size和length

功能都是返回字符串有效字符长度

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接 口保持一致,一般情况下基本都是用size()

capacity

主要作用是扩容

样例代码如下:

 string s1;size_t old = s1.capacity();cout << "capacity:" << old << endl;for (size_t i = 0; i < 100; i++){s1 += 'x';if (s1.capacity() != old){cout << "capacity:" << s1.capacity() << endl;old = s1.capacity();}}

运行结果:

在这里插入图片描述

可以发现,除了第一次是两倍大小的关系,其他情况下都是1.5倍左右,因为VS会预留个buffer,大小为16个字节大小,如果刚开始的string字符串大小小于16个字节,放到buffer里面,大于16个就浪费这个buffer,加上这个buffer是为了防止频繁地调用堆里面的存储

具体来说,原因如下:

vs和g++下string结构的说明

注意:

下述结构是在32位平台下进行验证,32位平台下指针占4个字节。

  • **vs下string的结构 **

string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义 string中字符串的存储空间

**当字符串长度小于16时,使用内部固定的字符数组来存放 **

当字符串长度大于等于16时,从堆上开辟空间

union _Bxty
{ // storage for small buffer or pointer to larger one
value_type _Buf[_BUF_SIZE];
pointer _Ptr;
char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建 好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。

其次:还有**一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的 容量 **

最后:还有一个指针做一些其他事情。

故总共占16+4+4+4=28个字节。

  • g++下string的结构

G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个 指针,该指针将来指向一块堆空间,内部包含了如下字段:

空间总大小

字符串有效长度

引用计数

struct _Rep_base
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
};

指向堆空间的指针,用来存储字符串。

reserve

功能:为字符串预留空间

在VS中,reserve预留空间会比实际的要大

代码如下:

string s1;
s1.reserve(200);
size_t old = s1.capacity();
cout << "capacity:" << old << endl;
for (size_t i = 0; i < 100; i++)
{s1 += 'x';if (s1.capacity() != old){cout << "capacity:" << s1.capacity() << endl;old = s1.capacity();}
}

运行结果如下:

在这里插入图片描述

reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参 数小于string的底层空间总大小时,reserver不会改变容量大小。

string类对象的修改操作

push_back

在字符串后尾插字符

append

在字符串后追加一个字符串

operator+=(重点,比上面两个库函数好)

在字符串后追加字符串str

int main()
{string s1("hello");s1.push_back(',');s1.push_back('w');cout << s1 << endl;s1.append("orld");cout << s1 << endl;s1.append(10, '!');cout << s1 << endl;string s2("hello smile hello world");s1.append(s2.begin()+6, s2.end());cout << s1 << endl;string s3("hello");s3 += ',';s3 += "world";cout << s3 << endl;return 0;
}

运行结果:

在这里插入图片描述

一道OJ题:仅仅反转字母

给你一个字符串 s ,根据下述规则反转字符串:

  • 所有非英文字母保留在原有位置。
  • 所有英文字母(小写或大写)位置反转。

返回反转后的 s

示例 1:

输入:s = "ab-cd"
输出:"dc-ba"

示例 2:

输入:s = "a-bC-dEf-ghIj"
输出:"j-Ih-gfE-dCba"

示例 3:

输入:s = "Test1ng-Leet=code-Q!"
输出:"Qedo1ct-eeLg=ntse-T!"

提示

  • 1 <= s.length <= 100
  • s 仅由 ASCII 值在范围 [33, 122] 的字符组成
  • s 不含 '\"''\\'

代码:

class Solution {
public:string reverseOnlyLetters(string s) {int n = s.size();int left = 0, right = n - 1;while (true) {while (left < right && !isalpha(s[left])) { // 判断左边是否扫描到字母left++;}while (right > left && !isalpha(s[right])) { // 判断右边是否扫描到字母right--;}if (left >= right) {break;}swap(s[left], s[right]);left++;right--;}return s;}
};

双指针法,看下标

一道OJ题:字符串相加

给定两个字符串形式的非负整数 num1num2 ,计算它们的和并同样以字符串形式返回。

你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。

示例 1:

输入:num1 = "11", num2 = "123"
输出:"134"

示例 2:

输入:num1 = "456", num2 = "77"
输出:"533"

示例 3:

输入:num1 = "0", num2 = "0"
输出:"0"

提示:

  • 1 <= num1.length, num2.length <= 104
  • num1num2 都只包含数字 0-9
  • num1num2 都不包含任何前导零

代码如下:

class Solution {
public:string addStrings(string num1, string num2) {//这是我们需要返回的字符串,要接受的对象string str;//因为扩容会浪费一定的空间,会导致效率降低,所以用了库函数里面的函数,更加合理地使用空间//+1是为了防止越界str.reserve(max(num1.size(),num2.size())+1);//end是有效字符串最后一位的下一位,所以要-1防止越界int end1=num1.size()-1,end2=num2.size()-1;//进位int next=0;//循环的条件是要继续下去,平常可能会想着结束的条件不一样,是反的while(end1>=0||end2>=0||next){//这里是字符串接收,end计算完了还要记得--,字符串‘0’是拿ASCLL码表,0是48int x1=end1>=0?num1[end1--]-'0':0;int x2=end2>=0?num2[end2--]-'0':0;//ret是要接收的数int ret=x1+x2+next;//进位将数取整next=ret/10;//这个是个位,例如9+4,要余3ret=ret%10;//库函数,头插,尾插会错误,如11,231,会变成242str.insert(0,1,'0'+ret);}//这是为了处理1+9,没有进位的情况if(next==1){str+='1';//这里引入了一个库函数,进行逆置,是为了降低时间复杂度,使其为O(N)reverse(str.begin(),str.end());//str.insert(str.begin(),'1');,时间复杂度为O(N^2)}return str;}
};
       int x1=end1>=0?num1[end1--]-'0':0;int x2=end2>=0?num2[end2--]-'0':0;//ret是要接收的数int ret=x1+x2+next;//进位将数取整next=ret/10;//这个是个位,例如9+4,要余3ret=ret%10;//库函数,头插,尾插会错误,如11,231,会变成242str.insert(0,1,'0'+ret);}//这是为了处理1+9,没有进位的情况if(next==1){str+='1';//这里引入了一个库函数,进行逆置,是为了降低时间复杂度,使其为O(N)reverse(str.begin(),str.end());//str.insert(str.begin(),'1');,时间复杂度为O(N^2)}return str;
}

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

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

相关文章

2024华为杯研究生数学建模,代码思路和参考文章

F题X射线脉冲星光子到达时间建模&#xff0c; E题高速公路应急车道紧急启用模型&#xff0c; D题大数据驱动的地理综合问題&#xff0c; C题数据驱动下磁性元件的磁芯损耗建模&#xff0c; B题W LAN 组网中网络吞吐量建模&#xff0c; A题风电场有功功率优化分配&#xff…

Python画笔案例-057 绘制蜘蛛网

1、绘制蜘蛛网 通过 python 的turtle 库绘制 蜘蛛网&#xff0c;如下图&#xff1a; 2、实现代码 绘制蜘蛛网&#xff0c;以下为实现代码&#xff1a; """蜘蛛网.py """ import turtledef draw_circle(pos,r):"""pos:圆的中心点…

力扣最热一百题——搜索二维矩阵

目录 题目链接&#xff1a;240. 搜索二维矩阵 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法一&#xff1a;暴力不解释 Java写法&#xff1a; 运行时间 C写法&#xff1a; 运行时间 时间复杂度以及空间复杂度 解法二&#xff1a;利用自带的大小关系进行Z型走…

电商ISV 电商SaaS 是什么

Independent Software Vendors的英文缩写&#xff0c;意为“独立软件开发商” 软件即服务(SaaS) 指一种基于云技术的软件交付模式 订阅收费 这些公司叫做ISV软件供应商&#xff0c;通过SaaS服务交付收费 为什么会有电商ISV 从商家角度划分&#xff1a;有独立品牌商家、大商…

叉车限速器外接LED屏,监督厂区安全,让速度慢下来!

叉车限速器外接LED屏&#xff0c;可实时显示当前叉车行驶中的速度&#xff0c;单/双面电子显示屏供用户选择&#xff0c;方便企业人员监控司机当前行驶速度&#xff0c;当速度超过指定值时&#xff0c;叉车速度报警系统发出声光警示&#xff0c;提醒行人、司机&#xff0c;超速…

最新适用:关于夫妻共同债务的裁判规则+司法观点

✦ 重点条文 ✦ 《民法典》第一千零六十四条 夫妻双方共同签名或者夫妻一方事后追认等共同意思表示所负的债务&#xff0c;以及夫妻一方在婚姻关系存续期间以个人名义为家庭日常生活需要所负的债务&#xff0c;属于夫妻共同债务。 夫妻一方在婚姻关系存续期间以个人名义超…

新手入门:小程序架构快速上手

目录 新建项目和配置 项目基本结构 新建小程序页面 修改项目首页 全局配置 窗口 tabBar 页面配置 小程序基本语法 wxml 数据绑定 条件渲染 列表渲染 wxss wxss 对比 css rpx import 全局样式和局部样式 js wxs 数据请求 get和post请求 小程序和跨域 小程…

特征工程与交叉验证在机器学习中的应用

数据入口&#xff1a;学生考试表现影响因素数据集 - Heywhale.com 本数据集提供了关于影响学生考试成绩的多种因素的全面概述。数据集包含了有关学习习惯、出勤率、家长参与、资源获取等方面的信息。 数据说明 字段名说明Hours_Studied每周学习的小时数Attendance出勤率&…

30个GPT提示词天花板,一小时从大纲到终稿

PROMPT 1 中文&#xff1a;构建研究背景与意义&#xff0c;阐述研究问题的紧迫性和重要性。 English: Establish the research background and significance, elucidating the urgency and importance of the research question. 中文&#xff1a;设计研究目的与目标&#xff…

深入解析:HTTP 和 HTTPS 的区别

网络安全问题正变得日益重要&#xff0c;而 HTTP 与 HTTPS 对用户数据的保护十分关键。本文将深入探讨这两种协议的特点、工作原理&#xff0c;以及保证数据安全的 HTTPS 为何变得至关重要。 认识 HTTP 与 HTTPS HTTP 的工作原理 HTTP&#xff0c;全称超文本传输协议&#xf…

go 安装依赖超时

一、配置代理 go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.io,direct go get github.com/unidoc/unioffice

对象关系映射ORM

目录 ORM【重要】 1、 什么是ORM 2、 实体类 3、 ORM改造登录案例 ORM【重要】 1、 什么是ORM 目前使用JDBC完成了CRUD,但是现在是进行CRUD,增删改方法要设计很多参数,查询的方法需要设计集合才能返回. 在实际开发中,我们需要将零散的数据封装到对象处理. ORM (Object Rela…

十九、石英晶体振荡电路

石英晶体振荡电路 1、石英晶体的特点、等效电路、特性曲线; 2、石英晶体振动器的特点&#xff0c; 3、石英晶体振动器的振荡频率

软考(中级-软件设计师)计算机系统篇(0921)

六、计算机系统组成&#xff08;五大部件&#xff09; &#xff08;冯.诺依曼) 冯.诺依曼计算机的特点&#xff1a; 计算机有五大部件组成&#xff1a;输入设别&#xff0c;输出设备&#xff0c;控制器&#xff0c;运算器&#xff0c;存储器;指令和疏忽都以同等地位存于存储器…

为什么年轻人都热衷找搭子,而不是找对象?

在繁华的都市中&#xff0c;有一个名叫晓悦的年轻人。晓悦每天穿梭于忙碌的工作和快节奏的生活之间&#xff0c;渐渐地&#xff0c;她发现身边的朋友们都开始找起了 “搭子”。 有一天&#xff0c;晓悦结束了一天疲惫的工作&#xff0c;坐在咖啡店里&#xff0c;看着窗外匆匆而…

为写论文头疼?推荐4款ai写毕业论文初稿的软件

写论文对于许多学生来说是一项既重要又具挑战性的任务。为了帮助大家更高效地完成这一过程&#xff0c;我将推荐四款优秀的AI写毕业论文初稿的软件&#xff0c;并详细介绍它们的功能和优势。 传送门&#xff1a;https://www.aipaperpass.com?piclLGw 千笔-AIPassPaper是一款功…

面向对象例题之例题的特性

答案&#xff1a;C 解析&#xff1a;对象里面的方法和属性数量是不确定的&#xff0c;可以不断扩展写多个属性和方法 清洗的边界是对象必备的&#xff0c;哪些是这个类的&#xff0c;哪些是其他类的都有体现。 良好的定义行为一般指定义良好的属性和方法 可扩展性指的是子类…

【问题随记】在使用 AuthenticationManager 的时候,出现循环依赖问题 —— `java.lang.StackOverflowError`

问题随记 在使用 AuthenticationManager 的时候&#xff0c;出现循环依赖问题 —— java.lang.StackOverflowError&#xff0c;查资料查了两天半&#xff0c;终于找到原因。 2024-06-16T17:54:19.48708:00 ERROR 20672 --- [nio-8789-exec-1] o.a.c.c.C.[.[.[/].[dispatcherS…

波分技术基础 -- FEC

信号在传输过程中&#xff0c;不可避免的会出现劣化、误码&#xff0c;FEC (Forward error correction) 技术确保通信系统在噪声和其他损伤的影响下&#xff0c;依然能够实现无错误传输。 应用场景&#xff1a;长途密集波分系统&#xff08;DWDM&#xff09;实现方式&#xff…

LED显示屏迎来革新:GOB封装技术引领行业新风尚

在我们日常生活中&#xff0c;LED显示屏无处不在&#xff0c;从繁华的街头广告牌到家庭娱乐中心的大屏幕电视&#xff0c;它们都以鲜明的色彩和清晰的画质吸引着我们的目光。然而&#xff0c;在LED显示屏技术日新月异的今天&#xff0c;一种名为GOB&#xff08;Glue On Board&a…