模拟实现string类——【C++】

W...Y的主页 😊

代码仓库分享 💕


🍔前言:

我们已经将STL中的string类重要接口全部认识并熟练掌握,为了让我们对string与C++类与对象更深层次的了解,我们这篇博客将string类进行模拟实现。

目录

 string类的模拟实现

构造函数与析构函数

拷贝构造函数

其余string类对象接口模拟实现


 string类的模拟实现

我们第一步就是区分自己模拟实现的string与STL中的string的区别,所以我们得实用命名域进行区分。然后就是私有成员的设定,string的底层就是一个数组,所以我们得创建一个字符指针,还有两个变量分别是_size检测数组中内容的大小,与_capacity检测数组的空间大小的,与顺序表的数据是相同的。

构造函数与析构函数

这两个函数是非常关键的,承载了整个string类,string的初始化与销毁都是依靠与这两个函数。

string(const char* str = ""):_size(strlen(str))
{_capacity = _size == 0 ? 4 : _size;_str = new char[_capacity + 1];strcpy(_str, str);
}

因为我们知道在STL提供的构造函数中既可以传参也可以不传参进行初始化,所以我们也使用这种初始化类型,当我们没有进行传参数时,默认创建一个空字符串。当我们传参后,我们创建的构造函数默认开辟传入字符串大小的参数,反之开辟大小为4bit的空间。如果我们选择在不传参数时不开辟空间大小,在后面的函数中会起冲突。

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

析构函数就非常简单,将开辟的空间进行释放,最后将_size与_capacity进行制空即可。

拷贝构造函数

针对拷贝构造函数,我们已经不能使用C++默认生成的拷贝构造函数了,因为数据类型已经不是简单的内置类型,里面有我们开辟的空间,如果使用浅拷贝就会在析构函数中释放两次相同的空间导致程序崩溃。

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

使用深拷贝使每个对象都有一份独立的资源,不要和其他对象共享 。

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

其余string类对象接口模拟实现

 在string的模拟实现中,我们有许多类似接口可以实现,在这里我想说针对模拟实现时,我们可以使用复用已经C库中的各种函数来简单实现,并不需要进行大规模的写代码,这样可以巩固我们对函数的使用。

以下是string类函数的模拟实现完整代码:

string.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace why
{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}typedef const char* const_iterator;iterator begin()const{return _str;}iterator end()const{return _str + _size;}/*string():_str(new char[1]), _size(0), _capacity(0){_str[0] = '\0';}*/string(const char* str = ""):_size(strlen(str)){_capacity = _size == 0 ? 4 : _size;_str = new char[_capacity + 1];strcpy(_str, str);}const char* c_str(){return _str;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& operator[](size_t pos)const{assert(pos < _size);return _str[pos];}size_t size()const{return _size;}size_t capacity()const{return _capacity;}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}//拷贝构造string(const string& s):_size(s._size), _capacity(s._capacity){_str = new char[s._capacity + 1];strcpy(_str, s._str);}string& operator=(const string& s){if (this != &s){/*delete[] _str;_str = new char[s._capacity + 1];strcpy(_str, s._str);*///防止new开辟空间失败导致原数据被释放char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);_str = tmp;_size = s._size;_capacity = s._capacity;}return *this;}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 || *this < s;}bool operator>=(const string& s)const{return *this == s || *this > s;}bool operator!=(const string& s)const{return !(*this == s);}void reserve(size_t n){if (_capacity < n){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size + 1 > _capacity){reserve(_capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';}void append(const char* s){size_t len = sizeof(s);if (_size + len > _capacity){reserve(_size + len);}strcpy(_str + _size, s);_size += len;}string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* s){append(s);return *this;}void resize(size_t n, char ch = '\0'){if (n < _size){_size = n;_str[_size] = '\0';}else{if (n > _capacity){reserve(n);}size_t i = _size;while (i < n){_str[i] = ch;}_size = n;_str[_size] = '\0';}}void insert(size_t pos, char x){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] = x;_size++;}string& 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;}/*size_t i = 0;while (i < len){_str[pos] = s[i];pos++;i++;}*/strncpy(_str+pos, s, len);_size += len;return *this;}string& erase(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}void swap(string& s){std::swap(_str, s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}size_t find(char ch, size_t pos = 0){assert(pos < _size);for (size_t i = pos; i < _size; ++i){if (_str[i] == ch){return i;}}return npos;}size_t find(const char* str, size_t pos = 0){assert(pos < _size);// kmpchar* p = strstr(_str + pos, str);if (p == nullptr){return npos;}else{return p - _str;}}void clear(){_str[0] = '\0';_size = 0;}private:char* _str;size_t _size;size_t _capacity;static const size_t npos;//static const size_t npos = -1;};const size_t string::npos = -1;void print(const string& s){for (int i = 0; i < s.size(); i++){cout << s[i] << ' ';}cout << endl;string::const_iterator it = s.begin();while (it != s.end()){cout << *it << ' ';++it;}cout << endl;for (auto ch : s){cout << ch << ' ';}cout << endl;}void test1(){string s1;string s2("hello world");std::cout << s1.c_str() << std::endl;std::cout << s2.c_str() << std::endl;s2[0]++;std::cout << s2.c_str() << std::endl;}void test2(){string s1;string s2("hello world");string s3(s2);std::cout << s2.c_str() << std::endl;std::cout << s3.c_str() << std::endl;s2[0]++;std::cout << s2.c_str() << std::endl;std::cout << s3.c_str() << std::endl;s1 = s3;std::cout << s1.c_str() << std::endl;}void test3(){string s1("hello world");print(s1);string::iterator it = s1.begin();while (it != s1.end()){cout << *it << ' ';++it;}cout << endl;for (auto ch : s1){cout << ch << ' ';}cout << endl;}void test4(){string s1("hello world");string s2("hello world");string s3("wwwwwww");cout << (s1 == s2) << endl;cout << (s1 != s2) << endl;cout << (s1 > s2) << endl;}void test5(){string s1 = "hello world";cout << s1.c_str() << endl;string s2 = "xxxxxxxxxx";s1.append("xxxxxxxx");cout << s1.c_str() << endl;s1 += 'c';s2 += "yyyyyyy";cout << s1.c_str() << endl;cout << s2.c_str() << endl;string s3;s3 += "ssssssss";cout << s3.c_str() << endl;string s4;s4 += '1';cout << s4.c_str() << endl;}void test6(){string s1("hello worlddddddddddddddd");cout << s1.capacity() << endl;s1.reserve(10);cout << s1.capacity() << endl;}void test7(){string s1;s1.resize(20, 'x');cout << s1.c_str() << endl;s1.resize(30, 'y');cout << s1.c_str() << endl;s1.resize(10);cout << s1.c_str() << endl;}void test8(){string s1("xxxxx");s1.insert(0, 'y');cout << s1.c_str() << endl;s1.insert(0, "wwwwww");cout << s1.c_str() << endl;}
}

test.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include"string.h"int main()
{//why::test1();//why::test2();//why::test3();//why::test4();//why::test5();//why::test7();why::test8();return 0;
}

我们在模拟实现时一定要边写边测试,从而将问题进行模块纠正,这样可以以最快的速度完成大量代码。


以上就是本次博客全部内容,感谢大家观看。

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

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

相关文章

【Proteus仿真】【51单片机】多路温度控制系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用按键、LED、蜂鸣器、LCD1602、DS18B20温度传感器、HC05蓝牙模块等。 主要功能&#xff1a; 系统运行后&#xff0c;默认LCD1602显示前4路采集的温…

Zabbix监控SSL证书有效期

一、介绍 由于业务需要&#xff0c;最近通过 Let’s Encrypt 申请了一些 SSL 证书&#xff0c;而证书有效期为 3 个月&#xff0c;需要在证书到期之前 renew。由于域名较多经常忘记 renew&#xff0c;导致证书过期&#xff0c;因此想通过 Zabbix 的方式监控证书的到期时间&…

中国电信终端产业联盟5G Inside行业子联盟正式成立!宏电股份作为副理事单位受邀加入

11月9日&#xff0c;中国电信于广州召开“2023中国电信终端生态合作暨中国电信终端产业联盟&#xff08;以下简称CTTA&#xff09;第十四次会员大会”&#xff0c;联盟成员齐聚现场。作为CTTA大会的一个重要环节&#xff0c;中国电信终端产业联盟5G Inside行业子联盟正式成立&a…

Vue.Draggable 踩坑:add 事件与 change 事件中 newIndex 字段不同之谜

背景 最近在弄自定义表单&#xff0c;需要拖动组件进行表单设计&#xff0c;所以用到了 Vue.Draggable(中文文档)。Vue.Draggable 是一款基于 Sortable.js 实现的 vue 拖拽插件&#xff0c;文档挺简单的&#xff0c;用起来也方便&#xff0c;但没想到接下来给我遇到了灵异事件……

学者观察 | 联邦学习与区块链、大模型等新技术的融合与挑战-北京航空航天大学童咏昕

导语 当下&#xff0c;数据已成为经济社会发展中不可或缺的生产要素&#xff0c;正在发挥越来越大的价值。但是在数据使用过程中&#xff0c;由于隐私、合规或者无法完全信任合作方等原因&#xff0c;数据的拥有者并不希望彻底和他方共享数据。为解决原始数据自主可控与数据跨…

Leetcode—67.二进制求和【简单】

2023每日刷题&#xff08;二十八&#xff09; Leetcode—67.二进制求和 实现代码 void reverse(char *a, int len) {for(int i 0; i < len / 2; i) {char tmp a[i];a[i] a[len - 1 - i];a[len - 1 - i] tmp;} }char* addBinary(char* a, char* b) {int len1 strlen(a…

golang 库之「依赖注入」

文章目录 1. 写在最前面2. 依赖注入2.1 使用场景2.2 框架对比 3. fx 框架使用场景示例3.1 示例3.2 golang 原生的库3.3 fx 库3.4 对比3.4.1 如上两种实现方式对比3.4.2 关于过度设计3.4.3 感悟 4. 碎碎念5. 参考资料 1. 写在最前面 同事在技术分享的时候用了 golang 的 fx 框架…

套接字的多种可选项

套接字可选项和I/O缓冲大小 套接字的多种可选项 套接字可选项分为 IPPROTO_IP、IPPROTO_TCP、SOL_SOCKET 三层&#xff0c;各层的含义为&#xff1a; IPPROTO_IP&#xff1a;IP 协议相关事项&#xff1b; IPPROTO_TCP&#xff1a;TCP 协议相关事项&#xff1b; SOL_SOCKET&am…

苍穹外卖-day09

用户端历史订单模块 1. 查询历史订单 1.1 需求分析和设计 产品原型&#xff1a; 业务规则 分页查询历史订单可以根据订单状态查询展示订单数据时&#xff0c;需要展示的数据包括&#xff1a;下单时间、订单状态、订单金额、订单明细&#xff08;商品名称、图片&#xff09;…

如何设置静态代理IP切换电脑上网地址使用?

在当今的网络时代&#xff0c;代理IP已成为一种常见的网络访问方式。通过使用代理IP&#xff0c;我们可以隐藏自己的真实IP地址&#xff0c;从而保护自己的隐私和安全。但是&#xff0c;有时候我们需要切换代理IP来满足不同的上网需求。本文将介绍如何设置静态代理IP切换电脑上…

优秀智慧园区案例 - 珠海华发智慧园区,万字长文解析先进智慧园区建设方案经验

一、项目背景 珠海华发产业园运营管理有限公司&#xff08;简称“产业园公司”&#xff09;是2016年起连续五年跻身“中国企业500强”、国务院国企改革“双百企业”的珠海华发集团旗下的实体产业发展载体运营平台&#xff0c;依托“四园一基地”&#xff1a;中以国际产业园、信…

Java自学第11课:电商项目(4)重新建立项目

经过前几节的学习&#xff0c;我们已经找到之前碰到的问题的原因了。那么下面接着做项目学习。 1 新建dynamic web project 建立时把web.xml也生成下&#xff0c;省的右面再添加。 会询问是否改为java ee环境&#xff1f;no就行&#xff0c;其实改过来也是可以的。这个不重要。…

基于springboot实现福聚苑社区团购平台系统项目【项目源码】

基于springboot实现福聚苑社区团购平台系统演示 Javar技术 Java是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&…

【KVM-4】硬件虚拟化技术(详)

前言 大家好&#xff0c;我是秋意零。 经过前面章节的介绍&#xff0c;已经知道KVM虚拟化必须依赖于硬件辅助的虚拟化技术&#xff0c;本节就来介绍一下硬件虚拟化技术。 &#x1f47f; 简介 &#x1f3e0; 个人主页&#xff1a; 秋意零&#x1f525; 账号&#xff1a;全平…

从替代走向引领,永洪科技迈向全球化

对于数据分析领域而言&#xff0c;这是一个最好的时代。 《全球数字经济白皮书&#xff08;2023年&#xff09;》介绍&#xff0c;2016年-2022年&#xff0c;中国数字经济年均复合增长率为14.2%&#xff0c;数字经济发展增速和规模兼具。随着数字基础实施持续夯实、数字应用不…

前端面试系列之工程化篇

如果对前端八股文感兴趣&#xff0c;可以留意公重号&#xff1a;码农补给站&#xff0c;总有你要的干货。 前端工程化 Webpack 概念 本质上&#xff0c;webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时&#xff0c;它会在内部从一个…

MyBatis 反射工具箱:带你领略不一样的反射设计思路

反射是 Java 世界中非常强大、非常灵活的一种机制。在面向对象的 Java 语言中&#xff0c;我们只能按照 public、private 等关键字的规范去访问一个 Java 对象的属性和方法&#xff0c;但反射机制可以让我们在运行时拿到任何 Java 对象的属性或方法。 有人说反射打破了类的封装…

企业微信开发教程一:添加企微应用流程图解以及常见问题图文说明

最近在前辈的基础上新添加了一个企微应用&#xff0c;过程中遇到了一些卡点&#xff0c;这里一一通过图片标注与注释的方式记录一下&#xff0c;希望能给后来人提供一些清晰明了的帮助&#xff0c;话不多说&#xff0c;大家直接看图吧。 &#xff08;文中包括一些本项目独有的配…

matlab背景部分最小化算法人脸检测

1、内容简介 略 18-可以交流、咨询、答疑 matlab背景部分最小化算法人脸检测 2、内容说明 matlab人脸检测 matlab人脸检测&#xff0c;背景部分最小化算法 3、仿真分析 略. 4、参考论文 略 链接&#xff1a;https://pan.baidu.com/s/1yQ1yDfk-_Qnq7tGpa23L7g 提取码&…

双H桥直流马达步进电机驱动芯片SS8833E

由工采网代理的率能SS8833E是一款适用于有刷直流或双极步进电机的集成电机驱动芯片&#xff1b;采用eTSSOP16封装&#xff1b;该器件集成了两个PNMOS H桥和电流调节电路&#xff1b;电机输出电流可以由外部脉宽调制器&#xff08;PWM&#xff09;或内部PWM电流控制器控制。 工…