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

【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博客

基本思路

  1. 构建string类框架

    构造函数, 拷贝构造,析构,返回字符串的 C 风格表示,返回字符串长度,返回总容量

  2. 构建函数重载

    operator=,operator[],> == >= < <= !=

  3. 迭代器:

    begin() && end()

  4. 遍历string

  5. resetve 开空间,insert任意位置插入,push_back,append,+=,交换

  6. erase删除,clear清除,resize缩容

  7. 流插入,流提取

代码实现

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.构建框架&#xff1a; 2.构建函数重载 3.迭代器&#xff1a; 4.遍历string 5.resetve 开空间&#xff0c;insert任意位置插入push_back,append,(按顺序依次实现) 6.erase删除&#xff0c;clear清除&#xff0c;resize缩容 7.流插入&#xff0…...

【数据结构和算法】确定两个字符串是否接近

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1操作 1 的本质&#xff1a;字符可以任意排列 2.2操作 2 的本质&#xff1a;出现次数是可以交换的 2.…...

[足式机器人]Part2 Dr. CAN学习笔记-Ch0-1矩阵的导数运算

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Ch0-1矩阵的导数运算 1. 标量向量方程对向量求导&#xff0c;分母布局&#xff0c;分子布局1.1 标量方程对向量的导数1.2 向量方程对向量的导数 2. 案例分析&#xff0c;线性回归3. 矩阵求导的链…...

如何让软文更具画面感,媒介盒子分享

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

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

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

Java多线程:代码不只是在‘Hello World‘

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

使用PCSS实现的实时阴影效果

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

用于缓存一些固定名称的小组件

项目中&#xff0c;用于缓存姓名、地名、单位名称等一些较固定名称的id-name小组件。用于减少一些表的关连操作和冗余字段。优化代码结构。扩展也方便&#xff0c;写不同的枚举就行了。 具体用法&#xff1a; {NameCacheUser.USER.getName(userId);NameCacheUser.ACCOUNT.getN…...

Python 读取电子发票PDF 转成Excel

Python 读取电子发票PDF 转成Excel 目录 0.前提 1.python相关的处理PDF的库 2.实际好用的 3.实际代码 4.思考 0.前提 只识别普通电子发票PDF&#xff0c;提取其中某些关键内容到excel中。 1.python相关的处理PDF的库 如下4个库是经常更新维护的&#xff01; pyP…...

我的项目问题

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

【c】杨辉三角

下面介绍两种方法 1.利用上面性质的第五条&#xff0c;我们可以求各行各列的组合数 2.利用上面性质的第7条&#xff0c;我们可以用数组完成 下面附上代码 1. #include<stdio.h> void fact(int n ,int m )//求组合数 {long long int sum11;long long int sum21;int a…...

算法刷题之数组篇

题目一&#xff1a;两数之和 给出一个整型数组 numbers 和一个目标值 target&#xff0c;请在数组中找出两个加起来等于目标值的数的下标&#xff0c;返回的下标按升序排列。 &#xff08;注&#xff1a;返回的数组下标从1开始算起&#xff0c;保证target一定可以由数组里面2…...

TR转发路由器测评—云企业网实现跨地域跨VPC的网络互通测评实战【阿里云产品测评】

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

1.1美术理论基础

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

【Java 基础】21 多线程同步与锁

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

Python语言基础知识(一)

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

Xilinx FPGA平台DDR3设计详解(三):DDR3 介绍

本文介绍一下常用的存储芯片DDR3&#xff0c;包括DDR3的芯片型号识别、DDR3芯片命名、DDR3的基本结构等知识&#xff0c;为后续掌握FPGA DDR3的读写控制打下坚实基础。 一、DDR3芯片型​号 电路板上的镁光DDR3芯片上没有具体的型号名。 ​如果想知道具体的DDR3芯片型号&#…...

字典的遍历

字典不是有序的集合&#xff0c;就不能通过index来遍历了&#xff0c;那如何遍历字典呢? 方法一:直接用字典 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源&#xff0c;对比前后yum源6.查看yum源是否生效7.安装MySQL服务8.查看相对应的配置文件9.启动服务10.查看启动服务11.登录方法一12.登录方法二13.登录方法三14.设置开…...

梦想与魔法:编程之路的挑战与荣耀

在年少轻狂的岁月里&#xff0c;我们都有过一些不切实际的梦想&#xff0c;渴望成为某种神奇的存在。我的梦想是成为一名神奇的码农&#xff0c;用键盘编织魔法&#xff0c;创造出炫酷的虚拟世界。然而&#xff0c;现实是残酷的&#xff0c;当我刚入门计算机领域时&#xff0c;…...

qt 5.15.2 主窗体菜单工具栏树控件功能

qt 5.15.2 主窗体菜单工具栏树控件功能 显示主窗体效果&#xff1a; mainwindow.h文件内容&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QFileDialog> #include <QString> #include <QMessageBox>#inc…...

Day15——File类与IO流

1.java.io.File类的使用 1.1 File类的理解 File 类及本章下的各种流&#xff0c;都定义在 java.io 包下。一个 File 对象代表硬盘或网络中可能存在的一个文件或者文件目录&#xff08;俗称文件夹&#xff09;&#xff0c;与平台无关。&#xff08;体会万事万物皆对象&#xf…...

【Qt】QLineEdit显示输入十六进制,位数不足时按照规则填充显示及每两个字符以空格填充

问题 在实际开发中&#xff0c;有时候需要对输入进行限制&#xff0c;一是更加合理&#xff0c;二是防止出现误操作。 比如&#xff1a; 使用Qt进行应用程序开发时&#xff0c;对单行编辑框QLineEdit控件&#xff0c;设置只可输入十六进制。 限制输入的方式常用且经典的是使用…...

GPT 中文提示词技巧:参照 OpenAI 官方教程

前言 搜了半天什么 prompt engineering 的课&#xff0c;最后会发现 gpt 官方其实是有 prompt 教程的。因此本文主要是学习这篇教程。 概述 - OpenAI API 部分案例是参考&#xff1a;根据吴恩达老师教程总结出中文版prompt教程_哔哩哔哩_bilibili up主的内容。 一、尽可能清…...

原生微信小程序将字符串生成二维码图片

weapp-qrcode.js再最后 inde.ts中的内容 // pages/qrCode/index.ts // 引入weapp-qrcode.js文件 var QRCode require(../../utils/weapp-qrcode) Page({/*** 页面的初始数据*/data: {orderNo:"",imagePath:},/*** 生命周期函数--监听页面加载*/onLoad(options:any)…...

深入理解HTTPS加密协议

在现代网络环境中&#xff0c;数据安全和隐私保护至关重要。HTTPS&#xff08;全称为HyperText Transfer Protocol Secure&#xff09;是一种用于保障互联网通信安全的加密协议&#xff0c;它通过在HTTP协议的基础上添加SSL/TLS层来实现对数据的加密传输。本文将详细介绍HTTPS的…...

路径规划之PRM算法

系列文章目录 路径规划之Dijkstra算法 路径规划之Best-First Search算法 路径规划之A *算法 路径规划之D *算法 路径规划之PRM算法 路径规划之PRM算法 系列文章目录前言一、前期准备1.栅格地图2.采样3.路标 二、PRM算法1.起源2.流程3. 优缺点4. 实际效果 前言 之前提到的几种…...

深入理解数据在内存中是如何存储的,位移操作符如何使用(能看懂文字就能明白系列)文章超长,慢慢品尝

系列文章目录 C语言笔记专栏 能看懂文字就能明白系列 &#x1f31f; 个人主页&#xff1a;古德猫宁- &#x1f308; 信念如阳光&#xff0c;照亮前行的每一步 文章目录 系列文章目录&#x1f308; *信念如阳光&#xff0c;照亮前行的每一步* 前言引子一、2进制和进制转化为什么…...

ArcGIS提示当前许可不支持影像服务器

1、问题&#xff1a; 在用ArcGIS上处理影像栅格数据时&#xff08;比如栅格数据集裁剪、镶嵌数据集构建镶嵌线等&#xff09;经常会出现。 无法启动配置 RasterComander.ImageServer <详信息 在计算机XXXXX上创建服务器对象实例失败 当前许可不支持影像服务器。 ArcGIS提示当…...