C++第十九弹---string模拟实现(下)

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

目录

1、修改操作

2、迭代器操作

3、字符串操作 

4、非成员函数重载操作

总结


1、修改操作

1、string& operator+= (const char* s);

//尾部插入字符串s
2、string& operator+= (char c);

//尾部插入字符c
3、void push_back (char c);

//尾部插入字符c
4、string& append (const char* s);

//尾部插入(追加)字符串s
5、void insert(size_t pos, char ch);

//在pos位置插入字符c
6、void insert(size_t pos, const char* str);

//在pos位置插入字符串str
7、void erase(size_t pos, size_t len = npos);

//从pos位置删除n个字符
8、void swap(string& s);

//把字符串数据进行交换

void push_back(char c)
{// 扩容 容量为0则固定为4 其他则*2if (_size == _capacity){reserve(_capacity == 0 ? 4 : 2 * _capacity);}_str[_size] = c;//_size下标插入字符c++_size;//将大小+1_str[_size] = '\0';//字符串最后位置给标志结束的\0
}
void append(const char* s)
{//追加字符串首先得判断空间是否足够size_t len = strlen(s);if (len > _capacity - _size)//空间不够则扩容{reserve(_size + len);//大小为原大小+插入字符串长度}strcpy(_str + _size, s);//将要追加的数据拷贝到原数据尾_size += len;//更新字符串大小
}
string& operator+=(char c)
{push_back(c);//调用尾插字符函数return *this;
}
string& operator+=(const char* str)
{append(str);return *this;
}
void insert(size_t pos, char ch)
{assert(pos <= _size);//断言,小于字符串大小才能进行插入操作// 扩容if (_size == _capacity){reserve(_capacity == 0 ? 4 : 2 * _capacity);}// end=_size会有无符号与有符号比较问题,因为pos恒大于等于0,end回到-1// 无符号与有符号比较 会提升至无符号比较 即end = -1 还会大于possize_t end = _size + 1;while (end > pos)//end==pos则循环停止{_str[end] = _str[end - 1];//将前面的元素往后面一个位置移动--end;}_str[pos] = ch;//pos位置赋值字符ch++_size;//更新大小
}void insert(size_t pos, const char* str)
{assert(pos <= _size);//pos小于字符串大小才能进行插入操作size_t len = strlen(str);if (len > _capacity - _size)//容量不够则扩容{reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];//将原数据向后移动len位置--end;}strncpy(_str + pos, str, len);//不需要拷贝\0因此使用strncpy拷贝len长度到原串_size += len;//更新大小
}
void erase(size_t pos, size_t len = npos)
{assert(pos < _size);if (len == npos || len >= _size - pos)//长度为npos或者大于等于字符串大小-pos即删除整个字符串{_str[pos] = '\0';//直接在pos位置给\0即可_size = pos;//pos为\0下标,刚还为字符串大小}else//将pos+len位置后的数据拷贝到pos为止{strcpy(_str + pos, _str + pos + len);_size -= len;//更新长度}
}
void swap(string& s)//交换类的成员变量即可,
{std::swap(_str, s._str);//调用库函数的swap模板函数std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}

2、迭代器操作

注意:暂时我们理解的迭代器实质为指针,但不完全是指针,此处就通过指针来模拟实现。

typedef char* iterator;//将迭代器定义成char*类型
typedef const char* const_iterator;将迭代器定义成const char*类型


1、const char* begin() const;

//获取指向首元素的const迭代器
2、const char* end() const;

//获取指向尾元素的const迭代器
3、char* begin();

//获取指向首元素的迭代器
4、char* end();

//获取指向尾元素的迭代器

typedef char* iterator;
typedef const char* const_iterator;const char* begin() const
{return (const char*)_str;//返回首元素地址,const修饰因此强转类型
}
const char* end() const
{return (const char*)_str + _size;//尾元素下一个位置地址,即\0位置地址
}
char* begin()
{return _str;
}
char* end()
{return _str + _size;
}

3、字符串操作 

1、const char* c_str() const;

//获取C字符串首元素地址

2、size_t find(char ch, size_t pos = 0) const;

//从pos位置(默认从0位置)找字符ch,找到则返回下标,否则返回npos
3、size_t find(const char* sub, size_t pos = 0) const;

//从字符串sub的pos位置找是否有匹配的字符串,找到则返回第一个元素下标,否则返回npos
4、string substr(size_t pos = 0, size_t len = npos);

//从pos位置截取len长度(默认截取整个字符串)的子串

const char* c_str() const
{return _str;//返回首地址
}
size_t find(char ch, size_t pos = 0) const
{assert(pos < _size);//小于字符串大小才能进行查找for (size_t i = 0; i < _size; i++)//遍历字符串{if (_str[i] == ch)return i;//找到字符则返回下标}return npos;
}
size_t find(const char* sub, size_t pos = 0) const
{assert(pos < _size);const char* p = strstr(sub + pos, _str);//从sub+pos位置找,调用C语言库的找子串函数,找到则返回该值的地址,否则返回NULLif (p)//不为空则返回下标,指针相减即为相差个数,即下标{return p - _str;}else//为空返回npos{return npos;}
}
string substr(size_t pos = 0, size_t len = npos)
{assert(pos < _size);string sub;if (len >= _size - pos)//长度大于_size-pos即将整个字符串截取,也包括len==npos{for (size_t i = pos; i < _size; i++){sub += _str[i];//追加给sub}}else//否则截取len长度{for (size_t i = pos; i < len + pos; i++){sub += _str[i];}}return sub;
}

4、非成员函数重载操作

1、void swap(string& s1, string& s2);

//将类s1数据与类s2数据交换
2、bool operator==(const string& s1, const string& s2);

//比较s1与s2是否相等
3、bool operator<(const string& s1, const string& s2);

//比较s1是否小于s2
4、ostream& operator<<(ostream& out, const string& s);

//流插入,即打印字符串s
5、istream& operator>>(istream& in, string& s);

//流提取,即将输入的内容给s
6、istream& getline(istream& in, string& s);

//获取一行信息,即将输入中回车之前的信息给s

void swap(string& s1, string& s2)
{s1.swap(s2);//调用类成员交换函数,跟库函数中交换函数重载,先调用类成员函数
}
bool operator==(const string& s1, const string& s2)
{int ret = strcmp(s1.c_str(), s2.c_str());//调用C语言比较字符串函数,等于0则相等return ret == 0;
}
bool operator<(const string& s1, const string& s2)
{int ret = strcmp(s1.c_str(), s2.c_str());return ret < 0;
}ostream& operator<<(ostream& out, const string& s)
{for (auto ch : s){out << ch;//用范围for变量类}return out;
}istream& operator>>(istream& in, string& s)
{s.clear();//清空串schar ch = in.get();//C++库中输入函数,读取一个字符给chchar buff[128];//先开辟一个128字节空间,减少频繁扩容size_t i = 0;while (ch != '\n' && ch != ' ')//流提取不识别空格回车{buff[i++] = ch;//将字符赋值给buff数组if (i == 127)//字符串满了则追加给串s{buff[127] = '\0';//末尾追加标志符\0s += buff;i = 0;//再重新赋值字符给buff数组}ch = in.get();}if (i > 0)//i>0则再追加数据给s{buff[i] = '\0';s += buff;}return in;
}
istream& getline(istream& in, string& s)
{s.clear();char ch = in.get();char buff[128];size_t i = 0;while (ch != '\n')//不识别回车,其他原理同流插入{buff[i++] = ch;if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;
}

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Text2SQL 论文】SeaD:使用 Schema-aware 去噪训练的 end2end 的 Text2SQL

论文&#xff1a;SeaD: End-to-end Text-to-SQL Generation with Schema-aware Denoising ⭐⭐ NAACL 2022, arXiv:2105.07911 本论文提出 SeaD 模型&#xff0c;使用 schema-aware 的去噪方法来训练一个 end2end、seq2seq 的 Transformer 模型来实现 Text2SQL。 一、论文速读…

C++系列-static成员

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 概念 声明为static的类成员称为类的静态成员&#xff0c;用static修饰的成员变量&#xff0c;称之为静态成员变量&#xff0c;用static修饰的成员函数&#xff0c;称之为静态成…

stm32学习-流水灯

接线 注意&#xff1a;LED灯长一点的引脚是正极。 配置GPIO 1.使用RCC开启GPIO时钟 void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); void RCC_APB1Perip…

【Qt 学习笔记】Qt窗口 | 菜单栏 | QMenuBar的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt窗口 | 菜单栏 | QMenuBar的使用及说明 文章编号&#xff1a;Qt 学习…

第20届文博会:“特别呈现”—周瑛瑾雷米·艾融双个展,著名美术评论家,批评家彭德教授对周瑛瑾作品进行评论

周瑛瑾不是学院派艺术家&#xff0c;但在彩墨画领域的天赋超出中国八大美院的同类型画家。相比具有批判意识的当代艺术&#xff0c;他的彩墨艺术如同我们这个苦难世界的创可贴和安慰剂。当我面对他的彩墨画&#xff0c;首先是惊艳&#xff0c;随之想到屈原的离骚&#xff0c;还…

[CISCN 2024] Crypto部分复现

文章目录 OvOez_rsacheckin浅记一下 迟来的文章 OvO 题目描述&#xff1a; from Crypto.Util.number import * from secret import flagnbits 512 p getPrime(nbits) q getPrime(nbits) n p * q phi (p-1) * (q-1) while True:kk getPrime(128)rr kk 2e 65537 kk …

【三维修复、分割与编辑】InFusion、Bootstrap 3D、GaussianGrouping、GaussianEditor等(论文总结)

提示&#xff1a; 文章目录 前言一、InFusion&#xff1a;扩散模型助力&#xff0c;效率提高20倍&#xff01;(2024)1. 摘要2. 算法3. 效果 二、2D Gaussian Splatting三、Bootstrap 3D:从扩散模型引导三维重建1.摘要2.相关工作3.方法1.Boostrapping by Diffusion 通过扩散模型…

学习存储协议的利器,聊聊tcpdump和Wireshark

数据存储技术分为多个方面,包括数据持久化、数据映射、数据压缩和通信协议等等。其中通信协议是数据存储技术中非常重要的一部分,正是通信协议使得计算节点可以访问存储设备。同时,也正是不同的协议让存储系统呈现不同的形态。 如下图所示,通过iSCSI协议,可以将存储端的存…

【JVM实践与应用】

JVM实践与应用 1.类加载器(加载、连接、初始化)1.1 类加载要完成的功能1.2 加载类的方式1.3 类加载器1.4 双亲委派模型1.5自定义ClassLoader1.6 破坏双亲委派模型2.1 类连接主要验证内容2.2 类连接中的解析2.3 类的初始化3.1 类的初始化时机3.2 类的初始化机制和顺序3.2 类的卸…

C从零开始实现贪吃蛇大作战

个人主页&#xff1a;星纭-CSDN博客 系列文章专栏 : C语言 踏上取经路&#xff0c;比抵达灵山更重要&#xff01;一起努力一起进步&#xff01; 有关Win32API的知识点在上一篇文章&#xff1a; 目录 一.地图 1.控制台基本介绍 2.宽字符 1.本地化 2.类项 3.setlocale函…

【深度学习】第1章

概论: 机器学习是对研究问题进行模型假设,利用计算机从训练数据中学习得到模型参数,并最终对数据进行预测和分析,其基础主要是归纳和统计。 深度学习是一种实现机器学习的技术,是机器学习重要的分支。其源于人工神经网络的研究。深度学习的模型结构是一种含多隐层的神经…

关于C的\r回车在不同平台的问题

首先我们需要搞明白\r和\n是两回事 \r是回车&#xff0c;前者使光标到行首&#xff0c;&#xff08;carriage return&#xff09; \n是换行&#xff0c;后者使光标下移一格&#xff0c;&#xff08;line feed&#xff09; Linux平台下 #include <stdio.h> int main()…

神经网络不确定性综述(Part I)——A survey of uncertainty in deep neural networks

相关链接&#xff1a; 神经网络不确定性综述(Part I)——A survey of uncertainty in deep neural networks-CSDN博客 神经网络不确定性综述(Part II)——Uncertainty estimation_Single deterministic methods-CSDN博客 神经网络不确定性综述(Part III)——Uncertainty est…

Python实现xml解析并输出到Excel上

1.编写xml文件 2.使用Python的ElementTree模块来解析XML import xml.etree.ElementTree as ET from openpyxl import Workbook # 解析XML函数 def parse_xml(xml_file):tree ET.parse(xml_file)root tree.getroot() --打开根节点data []for user in root.findall(Users/Us…

1.手动LogisticRegression模型的训练和预测

通过这个示例&#xff0c;可以了解逻辑回归模型的基本原理和训练过程&#xff0c;同时可以通过修改和优化代码来进一步探索机器学习模型的训练和调优方法。 过程: 生成了一个模拟的二分类数据集&#xff1a;通过随机生成包含两个特征的数据data_x&#xff0c;并基于一定规则生…

秋招突击——算法打卡——5/25、5/26——寻找两个正序数组的中位数

题目描述 自我尝试 首先&#xff0c;就是两个有序的数组进行遍历&#xff0c;遍历到一半即可。然后求出均值&#xff0c;下述是我的代码。但这明显是有问题的&#xff0c;具体错误的代码如下。计算复杂度太高了&#xff0c;O&#xff08;n&#xff09;&#xff0c;所以会超时&…

数据结构--《二叉树》

二叉树 1、什么是二叉树 二叉树(Binar Tree)是n(n>0)个结点的优先集合&#xff0c;该集合或者为空集(称为空二叉树)&#xff0c;或者由一个根结点和两颗互不相交的、分别称为根结点的左子树和右子树的二叉树构成。 这里给张图&#xff0c;能更直观的感受二叉树&#xff1…

GDPU JavaWeb mvc模式

搭建一个mvc框架的小实例。 简易计算器 有一个名为inputNumber.jsp的页面提供一个表单&#xff0c;用户可以通过表单输入两个数和运算符号提交给Servlet控制器&#xff1b;由名为ComputerBean.java生成的JavaBean负责存储运算数、运算符号和运算结果&#xff0c;由名为handleCo…

简单好用的文本识别方法--付费的好用,免费的更有性价比-记笔记

文章目录 先说付费的进入真题&#xff0c;免费的来喏&#xff01;PixPin微信 先说付费的 直达网址!!! 进入真题&#xff0c;免费的来喏&#xff01; PixPin 商店里就有 使用示例&#xff1a; 可以看到&#xff1a;贴在桌面上的图片可以复制图片中的文字&#xff0c;真的很…

Springboot+Vue+ElementUI开发前后端分离的员工管理系统01--系统介绍

项目介绍 springboot_vue_emp是一个基于SpringbootVueElementUI实现的前后端分离的员工管理系统 功能涵盖&#xff1a; 系统管理&#xff1a;用户管理、角色管理、菜单管理、字典管理、部门管理出勤管理&#xff1a;请假管理、考勤统计、工资发放、工资统计、离职申请、个人资…