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

string类模拟实现——C++

一、构造与析构

1.构造函数

构造函数需要尽可能将成员在初始化列表中初始化,string类的成员这里自定义的和顺序表相似,有_str , _size , _capacity , 以及一个静态成员 npos ,构造函数这里实现两种,一种是传参为常量字符串的,一种是不进行传参直接实例化的,这里可以使用缺省参数。

		string(const char* str = ""):_size(strlen(str)){assert(str);_capacity = _size == 0 ? 3 : _size;//一开始时开多几个空间,避免后续一些越界问题_str = new char[_capacity+1];//给多一个位置存放‘\0’strcpy(_str,str);}

2.拷贝构造

拷贝构造得注意参数给的时候,要用引用传参,不然会无限递归

        string(const string& s):_size(s._size),_capacity(s._capacity){_str = new char[_capacity+1];strcpy(_str,s._str);}

3.析构函数

正常用delete释放空间,参数置空即可

		~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}

二、迭代器

1.正向迭代器

这里由于底层是顺序表,因此迭代器的实现可以直接用指针,需要注意的是,在使用迭代器时,有时候需要用到const修饰,因此两种都要实现,构成函数重载

        typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str+_size;}		const_iterator begin()const{return _str;}const_iterator end()const{return _str+_size;}

2.反向迭代器

反向迭代器的实现还没学,暂时先空着...

三、基本参数返回

关于成员变量,我们需要提供一些接口去给用户合理的访问部分参数

		const char* c_str()const{return _str;}size_t size()const{return _size;}size_t capacity()const{return _capacity;}

四、增删查改

1.增加字符

关于增加字符,这里模拟实现几个基本的接口

(1)reserve

在模拟实现增加字符前,要先考虑扩容的问题,可以先实现reserve,后续对其进行复用扩容

		void reserve(size_t n)//扩容{if(n > _capacity){char* tmp = new char[n+1];strcpy(tmp,_str);delete[] _str;_str = tmp;_capacity = n;}}

(2)push_back

		void push_back(char ch){if(_size + 1 > _capacity){reserve(_capacity*2);}_str[_size] = ch;_size++;_str[_size] = '\0';}

(3)append

		void append(const char* s){size_t len = strlen(s);if(_size + len > _capacity){reserve(_size+len);}strcpy(_str+_size,s);_size += len;}

(4)resize

resize改变size的大小,当size改变后比原有的capacity大时,会进行扩容,但不会进行缩容,resize除了改变大小,还会在其余的空间里填上指定字符,要是不给定字符则默认为‘\0’

		void resize(size_t n,char ch = '\0'){if(n > _size){reserve(n);while(_size < n){_str[_size++] = ch;}_str[_size] = '\0';}else{_size = n;_str[_size] = '\0';}}

(5)insert

从指定位置pos插入字符或者字符串,这里需要构成函数重载,思路是用一个end,从后往前的将数据依次往后挪(不要漏掉‘\0’)然后空出来的位置再进行插入,在插入字符串时,挪动数据那一块的判断相对复杂,需要画图去对边界条件进行判断,需要注意的是,end的类型要定义成size_t,为了避免整形提升,还需要注意end<0时,不会变成-1,所以需要避免让end小于0的情况,也就是头插的情况,需要额外加判断或者采用从前面往后搬数据,end指向后面

		void insert(size_t pos,char ch){assert(pos < _size);size_t end = _size+1;if(_size + 1 > _capacity){reserve(_capacity*2);}while(end < pos){_str[end] = _str[end-1];end--;}_str[pos] = ch;_size++;}
		void insert(size_t pos,const char* s){assert(pos < _size);size_t len = strlen(s);if(_size + len > _capacity){reserve(_size+len);}size_t end = _size + len;while(end < pos+len-1){_str[end] = _str[end - len];end--;}strncpy(_str+pos,s,len);_size+=len;}

2.删除字符

(1)erase

npos=-1,但npos是无符号整形,因此是整形的最大值,函数功能是从指定位置往后删指定长度的数据,若是不给长度,则默认全删了,删到‘\0’停下。

		void erase(size_t pos,size_t len = npos){assert(pos < _size);size_t end = pos;size_t count = 0;while(end < _size && len){end++;len--;count++;}while(end <= _size){_str[pos++] = _str[end++];}_size -= count;}

(2)clear

清除所有数据

		void clear(){_size = 0;_str[_size] = '\0';}

3.查找字符

(1)find

查找函数这里模拟实现一个接口,要支持查找字符或者字符串,返回相对应的下标,需要构成函数重载

查找字符

		size_t find(char ch,size_t pos = 0){for(size_t i = pos;i<_size;i++){if(_str[i] == ch){return i;}}return npos;}

查找字符串

		size_t find(const char* s,size_t pos = 0){char* pstr = strstr(_str+pos,s);if(pstr == nullptr){return npos;}return pstr - s;}

4.修改字符

修改操作可以通过删除添加实现,实际价值不大,因此没有专门的接口实现,这里实现一个常用的交换操作,比起库里面直接使用的swap,这里省去了拷贝构造的过程,效率上会高很多

(1)swap

		void swap(string& s){std::swap(_str,s._str);std::swap(_size,s._size);std::swap(_capacity,s._capacity);}

五、运算符重载

1.常用运算符

		char& operator[](size_t pos)const{assert(pos < _size);return _str[pos];}string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* s){append(s);return *this;}string& operator=(const string& s){if(this != &s){char* tmp = new char[s._capacity+1];strcpy(tmp,s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;}return *this;}

2.比较运算符

		bool operator>(const string& s)const{return strcmp(_str,s._str) > 0 ;}bool operator==(const string& s)const{return strcmp(_str,s._str) == 0;}bool operator>=(const string& s)const{return *this > s || *this == s;}bool operator<(const string& s)const{return !(*this >= s);}bool operator<=(const string& s)const{return !(*this > s); }bool operator!=(const string& s)const{return !(*this == s);}

3.流重载

(1)输出重载

	ostream& operator<<(ostream& out,const string& s){for(size_t i = 0;i<s.size();i++){out << s[i];}return out;}

(2)输入重载

输入重载需要注意,字符串的截取,如果直接用in截取,则无法截取到空格和回车,因此用借用in的内部接口get(),而且为了避免多次扩容减低效率,可以先开一个字符串数组,将每次在缓存区内获取的字符存到字符串数组中,当字符串满了或者是获取完字符后,再一次性输入到string变量中

	istream& operator>>(istream& in,string& s){s.clear();char ch = in.get();char tmp[100];size_t i = 0;while(ch !=' ' && ch !='\n'){if(i<100){tmp[i++] = ch;ch = in.get();tmp[i] = '\0';}else{s+=tmp;i = 0;}}if(i != 0){s+=tmp;}return in;}

总结:

本篇模拟实现了string的部分常用的基本接口,从原理上去学习了string类的相关知识

相关文章:

string类模拟实现——C++

一、构造与析构 1.构造函数 构造函数需要尽可能将成员在初始化列表中初始化&#xff0c;string类的成员这里自定义的和顺序表相似&#xff0c;有_str , _size , _capacity , 以及一个静态成员 npos &#xff0c;构造函数这里实现两种&#xff0c;一种是传参为常量字符串的&am…...

在 SQL Server 中,可以使用加号运算符(+)来拼接字符串。但是,如果需要拼接多个字符串或表中的字段,就需要使用内置的拼接函数了

以下是 SQL Server 中的一些内置拼接函数&#xff1a; 1. CONCAT&#xff1a;将两个或多个字符串拼接在一起。语法为&#xff1a; CONCAT (string1, string2, ...)示例&#xff1a; SELECT CONCAT(Hello, , World) as combined_string;输出结果为&#xff1a;Hello World&a…...

蓝桥杯每日一题2023.9.25

4406. 积木画 - AcWing题库 题目描述 分析 在完成此问题前可以先引入一个新的问题 291. 蒙德里安的梦想 - AcWing题库 我们发现16的二进制是 10000 15的二进制是1111 故刚好我们可以从0枚举到1 << n(相当于二的n次方的二进制表示&#xff09; 注&#xff1a;奇数个0…...

前端面试的话术集锦第 20 篇博文——高频考点(输入 URL 到页面渲染的整个流程)

这是记录前端面试的话术集锦第二十篇博文——高频考点(输入 URL 到页面渲染的整个流程),我会不断更新该博文。❗❗❗ 借用这道经典面试题,将之前学习到的浏览器以及网络几章节的知识联系起来。 首先是DNS查询,如果这一步做了智能DNS解析的话,会提供访问速度最快的IP地址…...

Android Jetpack Compose之确定重组范围并优化重组

目录 1.概述2.确定Composable重组的范围3.优化重组的性能3.1 Composable 位置索引3.2 通过Key添加索引信息3.3 使用注解Stable优化重组 1.概述 前面的文章提到Compose的重组是智能的&#xff0c;Composable函数在进行重组时会尽可能的跳过不必要的重组&#xff0c;只对需要变化…...

【JDK 8-集合框架进阶】6.1 parallelStream 并行流

一、parallelStream 并行流 1.1 串行 和 并行的区别 > 执行结果 二、问题 2.1 paralleStream 并行是否一定比 Stream 串行快? 2.2 是否可以都用并行&#xff1f; > 报错 三、实战 > 执行结果 四、总结 一、parallelStream 并行流 多线程并发处理&#xff…...

C语言中结构体,枚举,联合相关介绍

本次重点&#xff1a; 1、结构体 &#xff1a; &#xff08;1&#xff09;结构体类型的声明 &#xff08;2&#xff09;结构的自引用 &#xff08;3&#xff09;结构体变量的定义和初始化 &#xff08;4&#xff09;结构体内存对齐 &#xff08;5&#xff09;结构体传参 …...

【干货】GNSS连续运行基准站网

文章目录 01 ​概述02 基准站建设03 数据中心04 数据通信网络 01 ​概述 1. 基准站网的组成 卫星连续运行基准站网&#xff08;Continuously Operating Reference Stations&#xff0c;缩写 CORS&#xff09;是由若干连续运行基准站及数据中心、数据通信网络组成的&#xff0…...

如何使用iPhone15在办公室观看家里电脑上的4k电影,实现公网访问本地群晖!

如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f; 文章目录 如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f;1.使用环境要求&#xff1a;2.下载群晖videostation&#xff1a;3.公网访问本地群晖videostation中的电影&#xff1a;4.公网条件下使用电脑…...

LeetCode之26.删除有序数组中的重复项和80.删除有序数组中的重复项II(C++)

文章目录 0 引言1 删除有序数组中的重复项1.1 解题方法1.2 C代码 2 删除有序数组中的重复项II2.1 解题方法2.2 C代码 0 引言 本文主要记录如何解决LeetCode中数组和字符串类别中的26.删除有序数组中的重复项&#xff08;简单&#xff09;及80.删除有序数组中的重复项II &#…...

linux驱动之input子系统简述

文章目录 一、什么是input子系统二、内核代码三、代码分析 一、什么是input子系统 Input驱动程序是linux输入设备的驱动程序&#xff0c;我们最常见的就按键&#xff0c;触摸&#xff0c;插拔耳机这些。其中事件设备驱动程序是目前通用的驱动程序&#xff0c;可支持键盘、鼠标…...

嵌入式裸机架构的探索与崩塌

为什么会想着探索下嵌入式裸机的架构呢&#xff1f;是因为最近写了一个项目&#xff0c;项目开发接近尾声时&#xff0c;发现了一些问题&#xff1a; 1、项目中&#xff0c;驱动层和应用层掺杂在一起&#xff0c;虽然大部分是应用层调用驱动层&#xff0c;但是也存在驱动层调用…...

MySQL高级语句(第二部分)

MySQL高级语句(第二部分)一、视图表 create view1、视图表概述2、视图表能否修改&#xff1f;&#xff08;面试题&#xff09;3、基本语法3.1 创建3.2 查看3.3 删除 4、通过视图表求无交集值 二、case语句三、空值(null) 和 无值(’ ) 的区别四、正则表达式五、存储过程1、简介…...

HTML计时事件(JavaScript)网页电子钟+网页计时器

setTimeout("函数","未来指定毫秒后调用函数"); clearTimeout(setTimeout("函数","未来指定毫秒后调用函数")); <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title>…...

使用群晖实现Videostation电影的大容量存储及分享教程

文章目录 1.使用环境要求2.制作视频分享链接3.制作永久固定视频分享链接 李哥和他的女朋友是一对甜蜜的情侣&#xff0c;但不幸的是&#xff0c;由于工作原因&#xff0c;他们目前分隔两地&#xff0c;无法常常亲密相伴。 这个距离让李哥特别怀念和女朋友一起在电影院观看电影的…...

后端大厂面试-15道题

1. 说说计算机存储结构 计算机存储结构通常包括这几个层次&#xff1a; 主存储器&#xff08;Main Memory&#xff09;&#xff1a;也称为内存&#xff08;RAM&#xff0c;Random Access Memory&#xff09;&#xff0c;主要用于存储当前正在执行的程序和数据。它是计算机中最…...

C++: 冒泡排序(Bubble Sort)

假设你有一列由数字组成的玻璃珠&#xff0c;这些珠子的重量不同&#xff0c;你希望将它们按照重量从轻到重排列。你会这样做&#xff1a; 从左到右&#xff0c;比较相邻的两颗珠子的重量。如果左边的珠子比右边的珠子重&#xff0c;就交换它们的位置。然后&#xff0c;继续向…...

跨域的解决方案

文章目录 概念一、什么是跨域问题二、为什么会发生跨域问题三、跨域解决方案1、JSONP2、添加响应头3、Spring注解CrossOrigin4、配置文件&#xff08;常用&#xff09;5、nginx跨域 概念 一、什么是跨域问题 前端调用的后端接口不属于同一个域&#xff08;域名或端口不同&…...

如何使用Java语言判断出geek是字符串参数类型,888是整数参数类型,[hello,world]是数组参数类型,2.5是双精度浮点数类型?

如何使用Java语言判断出geek是字符串参数类型&#xff0c;888是整数参数类型&#xff0c;[hello,world]是数组参数类型&#xff0c;2.5是双精度浮点数类型&#xff1f; Java是一种静态类型的编程语言&#xff0c;这意味着我们需要在编译时为变量指定具体的类型。但是&#xff…...

9.20华为机试-后端

1、丢失报文的位置 某通信系统持续向外发送报文&#xff0c;使用数组 nums 保存 n个最近发送的报文&#xff0c;用于在报文未达到对端的情况下重发。报文使用序号 sn 表示&#xff0c;序号 sn 按照报文发送顺序从小到大排序&#xff0c;相邻报文 sn 不完全连续且有可能相同。报…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...