【C++】手撕string思路梳理
目录
基本思路
代码实现
1.构建框架:
2.构建函数重载
3.迭代器:
4.遍历string
5.resetve 开空间,insert任意位置插入push_back,append,+=(按顺序依次实现)
6.erase删除,clear清除,resize缩容
7.流插入,流提取
全部代码
本文是对模拟string步骤进行梳理 若要详细讲解请跳转至:【C++】string模拟-CSDN博客
string讲解:【C++】String类-CSDN博客
基本思路
-
构建string类框架
构造函数, 拷贝构造,析构,返回字符串的 C 风格表示,返回字符串长度,返回总容量
-
构建函数重载
operator=,operator[],> == >= < <= !=
-
迭代器:
begin() && end()
-
遍历string
-
resetve 开空间,insert任意位置插入,push_back,append,+=,交换
-
erase删除,clear清除,resize缩容
-
流插入,流提取
代码实现
1.构建框架:
class string{private:char *_str;size_t _size;size_t _capacity;public:string(const char *str = ""): _size(strlen(str)){_capacity = _size = 0 ? 3 : _size;_str = new char[_size + 1];strcpy(_str, str);}// 拷贝string(const string &s): _size(s._size), _capacity(s._capacity){_str = new char[_capacity + 1];strcpy(_str, s._str);}~string(){delete[] _str;_str = nullptr;_capacity = _size = 0;}const char *c_str(){return _str;}//?size_t size() const // const?{return _size;}size_t capacity() const{return _capacity;}};
2.构建函数重载
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;}char &operator[](size_t pos){assert(pos < _size);return _str[pos];}const char &operator[](size_t pos) const{assert(pos < _size);return _str[pos];}bool operator<(string &s) const{return strcmp(_str, s._str) < 0;}bool operator==(string &s) const{return strcmp(_str, s._str) == 0;}bool operator<=(string &s) const{return *this < s || *this == s;}bool operator>(string &s) const{return !(*this <= s);}bool operator>=(string &s) const{return !(*this < s);}bool operator!=(string &s) const{return !(*this == s);}
3.迭代器:
typedef char *iterator;typedef const char *const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}
4.遍历string
void Print(const string &s){//方法1for (size_t i = 0; i < s.size(); i++){cout << s[i] << " ";}cout << endl;//方法二:迭代器遍历const_iterator rit = s.begin();while (rit != s.end()){cout << *rit << " ";++rit;}}
5.resetve 开空间,insert任意位置插入push_back,append,+=(按顺序依次实现)
void reserve(size_t n){if (n > _capacity){char *tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}string &insert(size_t pos, char ch){assert(pos <= _size);// 判断大小if (_size + 1 > _capacity){reserve(2 * _capacity);}size_t end = _size + 1;while (end > pos){_str[end] = _str[end + 1];end--;}_str[pos] = ch;++_size;return *this;}string &insert(size_t pos, const char *str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1){_str[end - len] = _str[end];--end;}strncpy(_str + pos, str, end);_size += len;return *this;}void push_back(char ch){insert(_size, ch);}void append(const char *str){insert(_size, str);}string &operator+=(char ch){push_back(ch);return *this;}string &operator+=(const char *str){append(str);return *this;}
交换:void swap(string &s){std::swap(_str, s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}
6.erase删除,clear清除,resize缩容
string &erase(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || len >= _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}void resize(size_t n, char ch = '\0'){if (n < _size){_size = n;_str[_size] = '\0';}else if (n > _size){if (n > _capacity){reserve(n);}size_t i = _size;while (i < n){_str[i] = ch;++i;}_size = n;_size = '\0';}}void clear(){_str[0] = '\0';_size = 0;}
7.流插入,流提取
ostream &operator<<(ostream &out, const string &s){for (size_t i = 0; i < s.size(); ++i){out << s[i];}return out;}istream &operator>>(istream &in, string &s){s.clear();char ch = in.get();char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = ch;buff[i + 1] = '\0';s += buff;}return in;}
全部代码
string.h
#include <iostream>#include <assert.h>using namespace std;namespace wzf{class string{private:char *_str;size_t _size;size_t _capacity;static size_t npos;public: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;}string(const char *str = ""): _size(strlen(str)){_capacity = _size = 0 ? 3 : _size;_str = new char[_size + 1];strcpy(_str, str);}// 拷贝string(const string &s): _size(s._size), _capacity(s._capacity){_str = new char[_capacity + 1];strcpy(_str, s._str);}~string(){delete[] _str;_str = nullptr;_capacity = _size = 0;}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;}char &operator[](size_t pos){assert(pos < _size);return _str[pos];}const char &operator[](size_t pos) const{assert(pos < _size);return _str[pos];}bool operator<(string &s) const{return strcmp(_str, s._str) < 0;}bool operator==(string &s) const{return strcmp(_str, s._str) == 0;}bool operator<=(string &s) const{return *this < s || *this == s;}bool operator>(string &s) const{return !(*this <= s);}bool operator>=(string &s) const{return !(*this < s);}bool operator!=(string &s) const{return !(*this == s);}void reserve(size_t n){if (n > _capacity){char *tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}string &insert(size_t pos, char ch){assert(pos <= _size);// 判断大小if (_size + 1 > _capacity){reserve(2 * _capacity);}size_t end = _size + 1;while (end > pos){_str[end] = _str[end + 1];end--;}_str[pos] = ch;++_size;return *this;}string &insert(size_t pos, const char *str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1){_str[end - len] = _str[end];--end;}strncpy(_str + pos, str, end);_size += len;return *this;}void push_back(char ch){insert(_size, ch);}void append(const char *str){insert(_size, str);}string &operator+=(char ch){push_back(ch);return *this;}string &operator+=(const char *str){append(str);return *this;}string &erase(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || len >= _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}void resize(size_t n, char ch = '\0'){if (n < _size){_size = n;_str[_size] = '\0';}else if (n > _size){if (n > _capacity){reserve(n);}size_t i = _size;while (i < n){_str[i] = ch;++i;}_size = n;_size = '\0';}}void clear(){_str[0] = '\0';_size = 0;}const char *c_str(){return _str;}//?size_t size() const // const?{return _size;}size_t capacity() const{return _capacity;}};size_t string::npos = -1;ostream &operator<<(ostream &out, const string &s){for (size_t i = 0; i < s.size(); ++i){out << s[i];}return out;}istream &operator>>(istream &in, string &s){s.clear();char ch = in.get();char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = ch;buff[i + 1] = '\0';s += buff;}return in;}void TestString1(){string s1("Hello");cout << s1.c_str() << endl;string s2 = s1;string s3(s1);cout << s3.c_str() << endl;s1[0]++;cout << s1.c_str() << endl;}void TestString2(){string s1("Hello");cout << s1.c_str() << endl;string s2("NI");cout << (s1 > s2) << endl;cout << (s1 >= s2) << endl;cout << (s1 == s2) << endl;cout << (s1 != s2) << endl;cout << (s1 <= s2) << endl;}void TestString3(){string s1("Hello");cout << s1.c_str() << endl;s1 += '!';s1 += "2345";cout << s1.c_str() << endl;}void TestString4(){string s1("HelloWord");string s2("HelloWord");s1.erase(3, 1);cout << s1.c_str() << endl;s1.erase(3, 100);cout << s1.c_str() << endl;s2.resize(4);cout << s2.c_str() << endl;s2.resize(10, 'x');cout << s2.c_str() << endl;}void TestString5(){string s1("HelloWord");cout << s1 << endl;cin >> s1;string::iterator it = s1.begin();while (it != s1.end() - 1){cout << *it << "";++it;}cout << endl;}}
string.cpp
#include "string.h"int main(){try // char* tmp = new char[s._capacity + 1];是否开辟异常{wzf::TestString5();}catch (const std::exception &e){std::cerr << e.what() << '\n';}return 0;}
相关文章:
【C++】手撕string思路梳理
目录 基本思路 代码实现 1.构建框架: 2.构建函数重载 3.迭代器: 4.遍历string 5.resetve 开空间,insert任意位置插入push_back,append,(按顺序依次实现) 6.erase删除,clear清除,resize缩容 7.流插入࿰…...
【数据结构和算法】确定两个字符串是否接近
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1操作 1 的本质:字符可以任意排列 2.2操作 2 的本质:出现次数是可以交换的 2.…...

[足式机器人]Part2 Dr. CAN学习笔记-Ch0-1矩阵的导数运算
本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-Ch0-1矩阵的导数运算 1. 标量向量方程对向量求导,分母布局,分子布局1.1 标量方程对向量的导数1.2 向量方程对向量的导数 2. 案例分析,线性回归3. 矩阵求导的链…...

如何让软文更具画面感,媒介盒子分享
写软文这种带有销售性质的文案时,总说要有画面感,要有想象空间。只有针对目标用户的感受的设计,要了解用户想的是什么,要用可视化的描述来影响用户的感受,今天媒介盒子就和大家分享:如何让软文更具画面感。…...

Hadoop学习笔记(HDP)-Part.19 安装Kafka
目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …...

Arrays类练习 - Java
案例:自定义Book类,里面包含name和price,按price排序(从大到小)。要求使用两种方式排序,有一个 Book[] books 4本书对象。 使用前面学习过的传递实现Comparator接口匿名内部类,也称为定制排序。可以按照price (1)从大到…...

Java多线程:代码不只是在‘Hello World‘
Java线程好书推荐 概述01 多线程对于Java的意义02 为什么Java工程师必须掌握多线程03 Java多线程使用方式04 如何学好Java多线程写在末尾: 主页传送门:📀 传送 概述 摘要:互联网的每一个角落,无论是大型电商平台的秒杀…...

使用PCSS实现的实时阴影效果
PCSS的技术可以使得阴影呈现出近硬远软的效果,并且能够实时实现。 其核心理念是通过模拟光源的面积来产生更自然、更柔和的阴影边缘。 具体步骤: 1、生成shadowmap 2、在进行阴影的比较时候进行平均,并非之前的shadow map 或者之后完全的阴影…...

用于缓存一些固定名称的小组件
项目中,用于缓存姓名、地名、单位名称等一些较固定名称的id-name小组件。用于减少一些表的关连操作和冗余字段。优化代码结构。扩展也方便,写不同的枚举就行了。 具体用法: {NameCacheUser.USER.getName(userId);NameCacheUser.ACCOUNT.getN…...
Python 读取电子发票PDF 转成Excel
Python 读取电子发票PDF 转成Excel 目录 0.前提 1.python相关的处理PDF的库 2.实际好用的 3.实际代码 4.思考 0.前提 只识别普通电子发票PDF,提取其中某些关键内容到excel中。 1.python相关的处理PDF的库 如下4个库是经常更新维护的! pyP…...

我的项目问题
1.一点缩放和旋转就消失,需要再次平移才出现 解决方案:在显示当前图形时,显示已有图形。 2.每次点击平移,图形移动到上次点击的位置。 ho_RegionUnion.Dispose(); ho_RegionUnion ExpTmpOutVar_0;这两段代码放到显示之后的&am…...

【c】杨辉三角
下面介绍两种方法 1.利用上面性质的第五条,我们可以求各行各列的组合数 2.利用上面性质的第7条,我们可以用数组完成 下面附上代码 1. #include<stdio.h> void fact(int n ,int m )//求组合数 {long long int sum11;long long int sum21;int a…...
算法刷题之数组篇
题目一:两数之和 给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。 (注:返回的数组下标从1开始算起,保证target一定可以由数组里面2…...

TR转发路由器测评—云企业网实现跨地域跨VPC的网络互通测评实战【阿里云产品测评】
文章目录 一.转发路由器 Transit Router 测评1.1 准备阶段1.2 本文测评收获1.3 什么是云企业网实例、转发路由器实例和云数据传输服务 二.使用云企业网实现跨地域跨VPC的网络互通2.2 **测试连通性**2.3 网络拓扑如下: 心得:总结: 声明&#x…...

1.1美术理论基础
一、光影 物体呈现在人们眼前的时候,不同的受光面其明暗变化以及物体的影子。 1.什么是黑白灰 在美术中黑白灰指亮面、灰面、暗面,属于素描的三大面,主要体验一个物体的整体寿光过程。普遍存在于各种艺术和设计领域。黑白灰作品的出现&#x…...

【Java 基础】21 多线程同步与锁
文章目录 1.存在的问题2.使用同步解决问题1) synchronized2) volatile3) 锁 总结 用多线程过程中,有可能出现 多个线程同时处理(获取或修改等)同一个数据,这个时候就 会发生数据不同步的问题, 因此出现了同步和锁来…...

Python语言基础知识(一)
文章目录 1、Python内置对象介绍2、标识符与变量3、数据类型—数字4、数据类型—字符串与字节串5、数据类型—列表、元组、字典、集合6、运算符和表达式7、运算符和表达式—算术运算符8、运算符和表达式—关系运算符9.1、运算符和表达式— 成员测试运算符in9.2、运算符和表达式…...

Xilinx FPGA平台DDR3设计详解(三):DDR3 介绍
本文介绍一下常用的存储芯片DDR3,包括DDR3的芯片型号识别、DDR3芯片命名、DDR3的基本结构等知识,为后续掌握FPGA DDR3的读写控制打下坚实基础。 一、DDR3芯片型号 电路板上的镁光DDR3芯片上没有具体的型号名。 如果想知道具体的DDR3芯片型号&#…...
字典的遍历
字典不是有序的集合,就不能通过index来遍历了,那如何遍历字典呢? 方法一:直接用字典 for key in a_dict: print a_dict[key] 通过这样的结构可以的。 d {"liming" : 98, "wangli":95, "mali":90, "liping&q…...

Linux环境下的MySQL安装
文章目录 前提说明1.卸载内置环境2.检查系统安装包3.卸载这些默认安装包4.获取MySQL官方yum源5.安装MySQLyum源,对比前后yum源6.查看yum源是否生效7.安装MySQL服务8.查看相对应的配置文件9.启动服务10.查看启动服务11.登录方法一12.登录方法二13.登录方法三14.设置开…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...
FOPLP vs CoWoS
以下是 FOPLP(Fan-out panel-level packaging 扇出型面板级封装)与 CoWoS(Chip on Wafer on Substrate)两种先进封装技术的详细对比分析,涵盖技术原理、性能、成本、应用场景及市场趋势等维度: 一、技术原…...

网页端 js 读取发票里的二维码信息(图片和PDF格式)
起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的ÿ…...

新版NANO下载烧录过程
一、序言 搭建 Jetson 系列产品烧录系统的环境需要在电脑主机上安装 Ubuntu 系统。此处使用 18.04 LTS。 二、环境搭建 1、安装库 $ sudo apt-get install qemu-user-static$ sudo apt-get install python 搭建环境的过程需要这个应用库来将某些 NVIDIA 软件组件安装到 Je…...