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

c++学习之string实现

字符串 - C++引用 (cplusplus.com)这里给出标准官方的string实现,可以看到设计还是较为复杂的,有成员函数,迭代器,修饰符,容量,元素访问,字符串操作等,将字符尽可能的需求都设计出来,我们这里实现string中比较常用且重要的。

成员变量

private:char* _str;size_t _size;size_t _capacity;
public:const static size_t npos;//声明一个npos 表示返回找不到的下标 或从-1的下一个开始寻找

目录

1.迭代器实现

2.成员函数

空构造

 有参构造

 拷贝构造

析构

 重载=

3.字符串操作

c_str

 find 

 substr

5.修饰符

push_back

 append

 operator+=

insert

 erase

6.容量

reserve

size

capacity

resize 

7.元素访问

重载下标引用操作符

8.运算符重载

重载<

重载==

重载<=

重载>

重载>=

重载!=

重载输入流

重载输出流


1.迭代器实现

这里我们实现了常量迭代器与正常的迭代器,反向迭代器并未实现。对于string这里的迭代器我们可以看到本质上是一个char *类型的指针,在某些地方可能不是指针,且它的用法也是与指针如出一撤。这里对于反向迭代器后面再实现。

    typedef char* iterator;//迭代器const typedef 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;};

在这里, 我们将char*定义为一个新的类型,并且给出它的成员函数,也就是迭代器的各个位置,从而实现。利用迭代器我们可以对他进行遍历:

Mystring::iterator it = str1.begin();while (it != str1.end()){cout << *it ;++it;}//范围forfor (auto tmp : str1){cout << tmp ;}

 同时其实本质上范围for的底层就是利用迭代器实现的,编译器在遇到范围for这样的写法时就会将这一段代码替换成下面迭代器实现的这样的遍历。

2.成员函数

空构造

实际上并不需要实现,我们这里给出它的实现,是了解对于空字符串的构造函数,虽说是空字符串,但不可直接赋值nullptr,否则后面实例化对象调成员函数时就是解引用空指针,空字符串,故这里会报错,实际上实现会给几个字节空间,放\0

Mystring():_str(new char[1]),_capacity(0),_size(0){}

 有参构造

//有参构造Mystring(const char* str="") : _size(strlen(str)), _capacity(_size)//缺省值直接给"",不给"\0",原先就有\0{//注意这里的字符串利用深拷贝,且初始化顺序遵循声明顺序_str = new char[_capacity + 1];//多开一个给\0strcpy(_str, str);}

 拷贝构造

还是老问题,直接的赋值会造成两次析构,故这里需要进行深拷贝。

//拷贝构造//之前讲过,浅拷贝会析构两次,深拷贝解决Mystring(const Mystring& s){_str = new char[s._capacity + 1];memset(_str, 0, s._capacity);strcpy(_str, s._str);this->_size = s._size;this->_capacity = s._capacity;}

析构

释放及初始化

//析构~Mystring(){delete [] _str;_str = nullptr;_capacity = _size = 0;}

 重载=

// 赋值重载Mystring& operator=(const Mystring& s){if (*this != s){char* temp = new char[s._capacity+1];strcpy(temp, s._str);delete []_str;_str = temp;this->_size = s._size;this->_capacity = s._capacity;}return *this;}

 这里的赋值重载区分拷贝构造:

用现有对象初始化定义的对象---------拷贝构造

用现有对象赋值给现有对象------------赋值

3.字符串操作

这里实现几个比较重要的,常用的。

c_str

const char* c_str()const{return _str;}

 find 

这里给出了两种实现,字符寻找与字符串寻找

//寻找某个字符,返回其下标位置size_t find(char ch,size_t pos=0){for (size_t i = pos; i < _size; i++){if (ch == _str[i]){return i;}}return npos;//找不到,返回-1}//寻找某个字符串,返回其相同的个数size_t find(const char* ch, size_t pos = 0){//暴力匹配const char* tmp = strstr(_str+pos, ch);if (tmp!= nullptr){return tmp - _str;//指针相减,找到个数}else{return npos;}}

 substr

//从pos位置处取n个字符,或n到 nposMystring substr(size_t pos, size_t len=npos){assert(pos < _size);Mystring s;size_t end = pos + len;if (len == pos || len + pos >= _size){len = _size - len;end = _size;}s.reserve(len);for (size_t i = pos; i <pos+len; i++){s += _str[i];//这里利用重载后的+=,本质上就是尾插}return s;}

5.修饰符

push_back

//尾插字符void push_back(char ch){//尾插的操作很简单,但是要考虑到扩容的问题if (_size == _capacity){reserve(_capacity=0?4:_capacity * 2);//为了避免空间是0,扩容失败}_str[_size] = ch;++_size;_str[_size] = '\0';}

 append

//尾插字符串void append(const char*ch){size_t num = strlen(ch);if (num + _size > _capacity){reserve(num + _size);}strcpy(_str + _size, ch);_size += num;//注意这里直接运用strcpy拷贝过来,连同\0一起,之后变为新大小}

 operator+=

这里重载的+=是利用了尾插的实现,故也作为字符串修饰

也是两种实现,+=字符或字符串

Mystring& operator+=(const char ch){push_back(ch);return *this;}Mystring& operator+=(const char* ch){append(ch);return *this;}

insert

 也是有两种实现方式

注意注释的提示:若这里想要进行头插,此时end>=0。只有当end--到负数才停止,而size_t 无法去判断正负数,程序崩溃,解决方法,将类型转换为int ,或者修改后移顺序,_str[end] = _str[end-1];去掉条件=。

其次就是对于扩容需要考虑空间为0的情况。

//某个位置插入字符void insert(size_t pos,char ch){assert(pos < _size);if (_size == _capacity){reserve(_capacity = 0 ? 4 : _capacity * 2);//为了避免空间是0,扩容失败}int end = _size;//pos位置处后移while (end>=(int)pos){//后移_str[end + 1] = _str[end];--end;}//插入_str[pos] = ch;}//某个位置插入字符串void insert(size_t pos,char *ch){size_t len = strlen(ch);if (_size +len>_capacity){reserve(_capacity = 0 ? 4 : _capacity * 2);//为了避免空间是0,扩容失败}size_t end = _size;//pos位置处后移while (end >= pos){//后移_str[end + len] = _str[end];--end;}//插入strncpy(_str+pos, ch,len);_size += len;}

 erase

删除pos位置后的npos个字符,这里的npos给的是缺省值,再没参数的情况下为-1,也就是pos后的全部删除。

//删除void erase(size_t pos,size_t len= npos){assert(pos <= _size);if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{size_t begin = pos + len;while (begin <= _size){_str[begin- len] = _str[begin ];++begin;}_size -= len;}}

6.容量

reserve

//扩容void reserve(size_t n){if (n > _size){char* tmp = new char[n + 1];//这里还是留一个\0位置strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}

size

//返回大小
size_t size()const{return _size;}

capacity

//返回容量
size_t capacity()const{return _capacity;}

resize 

//初始化大小为n,且可以赋值之后的void resize(size_t n,char c='\0'){if (n <= _size){//删除_str[n] = '\0';_size = n;}else{//扩容reserve(n);//初始化值while (_size < n){_str[_size] = c;_size++;}//末尾给\0_str[_size] = '\0';}}

7.元素访问

重载下标引用操作符

const char& operator[](int pos)const{assert(pos < _size);return _str[pos];}

8.运算符重载

对于这里的比较运算符,通过实现<与==,再取反实现> ,>=,!=.

重载<

bool operator<(const Mystring &s1){return strcmp(this->_str, s1._str) <0;}

重载==

bool operator==(const Mystring& s){return strcmp(this->_str, s._str) == 0;}

重载<=

bool operator<=(const Mystring& s){return *this < s || *this == s;//由于<与=已实现,直接用}

重载>

bool operator>(const Mystring& s){return !( *this <=s) ;//取反}

重载>=

bool operator>=(const Mystring& s){return !(*this < s);//取反}

重载!=

bool operator!=(const Mystring& s){return!(*this==s);}

重载输入流

//流插入
istream& operator>>(istream& in, Mystring& s)
{char ch;ch = in.get();//一个个拿字符,包括空格与\nwhile (ch != ' ' && ch != '\n'){s += ch;ch = in.get();}return in;
}

重载输出流

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

相关文章:

c++学习之string实现

字符串 - C引用 (cplusplus.com)这里给出标准官方的string实现&#xff0c;可以看到设计还是较为复杂的&#xff0c;有成员函数&#xff0c;迭代器&#xff0c;修饰符&#xff0c;容量&#xff0c;元素访问&#xff0c;字符串操作等&#xff0c;将字符尽可能的需求都设计出来&a…...

kubevirt虚机创建svc通过NodePort的方式暴露端口

背景 存在kubevit存在的三个虚机&#xff1a; ubuntu-4tlg7 7d22h Running True ubuntu-7kgrk 7d22h Running True ubuntu-94kg2 7d22h Running True 网络没有做透传&#xff0c;pod也不是underlay网络想要通过NodePort方式暴露虚机22端口进行远程登录。 …...

Elasticsearch终端命令行用法大全

API作用使用场景curl localhost:9200/_cluster/health?pretty查看ES健康状态curl localhost:9200/_cluster/settings?pretty查看ES集群的设置其中persistent为永久设置&#xff0c;重启仍然有效&#xff1b;trainsient为临时设置&#xff0c;重启失效curl localhost:9200/_ca…...

nacos版本升级注意事项

背景&#xff1a;nacos版本升级&#xff0c;1.0.1升级到2.1.2&#xff0c;nacos主要用作配置中心 1 从官网下载新版本nacos压缩包 2 由于1.x到2.x版本数据结构发生变化&#xff0c;无法沿用旧的数据库&#xff0c;所以新建一个数据库实例&#xff0c;来保存具体的nacos配置信息…...

JavaScript作用域与作用域链

JavaScript作用域与作用域链 JavaScript的作用域和作用域链是理解这门语言的关键概念之一。作用域指的是变量和函数在程序中可被访问的范围。作用域链是由函数的嵌套关系决定的变量对象的链式结构。 静态作用域与动态作用域 JavaScript使用静态作用域&#xff0c;也称为词法…...

MQTT异常掉线原因

一、业务场景 我们在使用MQTT协议的时候&#xff0c;有些伙伴可能会遇到MQTT客户端频繁掉线、上线问题 二、原因分析及异常处理 1.原因&#xff1a;使用相同的clientID 方案&#xff1a;全局使用的clientID保证唯一性&#xff0c;可以采用UUID等方式 2.原因: 当前用户没有Top…...

重新理解百度智能云:写在大模型开放后的24小时

在这些回答背后共同折射出的一个现实是——大模型不再是一个单选题&#xff0c;而更是一个综合题。在这个新的时代帆船上&#xff0c;产品、服务、安全、开放等全部都需要成为必需品&#xff0c;甚至是从企业的落地层面来看&#xff0c;这些更是刚需品。 作者| 皮爷 出品|产…...

Stable Diffusion 提示词技巧

文章目录 背景介绍如何写好提示词提示词的语法正向提示词负向提示词 随着AI技术的不断发展&#xff0c;越来越多的新算法涌现出来&#xff0c;例如Stable Diffusion、Midjourney、Dall-E等。相较于传统算法如GAN和VAE&#xff0c;这些新算法在生成高分辨率、高质量的图片方面表…...

VS2019编译curl库

下载&#xff1a; curl-7.61.0.tar.gz 编译&#xff1a; 解压到一个文件下&#xff0c;然后右键以管理员权限运行buildconf.bat 编译x64的库使用的是x64 Native Tools Command Prompt for VS 2019 本机工具命令提示&#xff0c;如果想编译x86的库&#xff0c;可以选择x86 Nat…...

yolov5自定义模型训练三

经过11个小时cpu训练完如下 在runs/train/expx里存放训练的结果&#xff0c; 测试是否可以检测ok 网上找的这张识别效果不是很好&#xff0c;通过加大训练次数和数据集的话精度可以提升。 训练后的权重也可以用视频源来识别&#xff0c; python detect.py --source 0 # webca…...

服务器中了mkp勒索病毒该怎么办?勒索病毒解密,数据恢复

mkp勒索病毒算的上是一种比较常见的勒索病毒类型了。它的感染数量上也常年排在前几名的位置。所以接下来就由云天数据恢复中心的技术工程师来对mkp勒索病毒做一个分析&#xff0c;以及中招以后应该怎么办。 一&#xff0c;中了mkp勒索病毒的表现 桌面以及多个文件夹当中都有一封…...

Docker环境搭建Prometheus实验环境

环境&#xff1a; OS&#xff1a;Centos7 Docker: 20.10.9 - Community Centos部署Docker 【Kubernetes】Centos中安装Docker和Minikube_云服务器安装docker和minikube_DivingKitten的博客-CSDN博客 一、拉取Prometheus镜像 ## 拉取镜像 docker pull prom/prometheus ## 启动p…...

Python Qt学习(七)Listview

源代码&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file qt_listview.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not…...

哈希表HashMap(基于vector和list)

C数据结构与算法实现&#xff08;目录&#xff09; 1 什么是HashMap&#xff1f; 我们这里要实现的HashMap接口不会超过标准库的版本&#xff08;是一个子集&#xff09;。 HashMap是一种键值对容器&#xff08;关联容器&#xff09;&#xff0c;又叫字典。 和其他容易一样…...

go中的函数

demo1:函数的几种定义方式 package mainimport ("errors""fmt" )/* 函数的用法 跟其他语言的区别&#xff1a;支持多个返回值*///函数定义方法1 func add(a, b int) int {return a b }//函数定义方法2 func add2(a, b int) (sun int) {sun a breturn s…...

小试 InsCode AI 创作助手

个人理解&#xff1a; 自ChatGPT新版现世&#xff0c;一直被视面替代人工工作的世大挑战&#xff0c;各类人工智能语言生成工目层出不穷&#xff0c;也在不断影响着我们日常的工作和生活 小试CSDN的InsCode AI&#xff1a; - 基本概念查询方便&#xff0c;与个人了解&…...

粉丝经验分享:13:00 开始的面试,13:06 就结束了,问题真是变态

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

SASS的@规则

1&#xff0c;import sass扩展了import导入&#xff0c;对于css&#xff0c;import导入在页面加载的时候去下载导入的外部文件&#xff0c;而sass的导入&#xff0c;在编译成css文件的时候就将外部的sass文件导入合并编译成一个css文件。 他支持同时导入多个文件&#xff1b;…...

【C++初阶】模拟实现优先级队列priority_queue

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…...

如何为你的公司选择正确的AIGC解决方案?

如何为你的公司选择正确的AIGC解决方案&#xff1f; 摘要引言词汇解释&#xff08;详细版本&#xff09;详细介绍1. 确定需求2. 考虑技术能力3. 评估可行性4. 比较不同供应商 代码快及其注释注意事项知识总结 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客&…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...