那些年我与c++的叫板(一)--string类自实现

引子:我们学习了c++中的string类,那我们能不能像以前数据结构一样自己实现string类呢?以下是cplusplus下的string类,我们参考参考!

废话不多说,直接代码实现:(注意函数之间的复用!)

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
//一般在类外进行静态区变量赋值
const static size_t npos = -1;
//本string简单实现,代码量小,故直接写在声明中
namespace bit
{
    class string
    {
    public:
        //采用typedef 让iterator保持接口的一致性
        //iterator底层是模版template
        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))
        {
            _str = new char[_size + 1];//为深拷贝,因为如果浅拷贝的话,共用一块空间,那结果可想而知
            _capacity = _size;
            strcpy(_str, str);//注意char * strcpy ( char * destination, const char * source );
        }
        //拷贝构造,可以隐式类型赋值
        string(const string& s)
        {
            _str = new char[s._capacity + 1];
            strcpy(_str, s._str);
            _size = s._size;
            _capacity = s._capacity;
        }
        string& operator=(const string& s)
        {
            if (this != &s)//排除等于自身的情况
            {
                char* tmp = new char[s._capacity + 1];
                strcpy(tmp, s._str);
                delete[]_str;//只析构_str上的资源
                _str = tmp;
                _size = s._size;
                _capacity = s._capacity;
            }
            return *this;
        }
        ~string()
        {
            delete[]_str;
            _str = nullptr;
            _size = _capacity = 0;
        }
        const char* c_str() const
        {
            return _str;
        }
        size_t size() const
        {
            return _size;
        }
        char& operator[](size_t pos)
        {
            assert(pos < _size);
            return _str[pos];
        }
        const char& operator[](size_t pos) const
        {
            assert(pos < _size);
            return _str[pos];
        }

        void reserve(size_t n)
        {
            if (n > _capacity)
            {
                char* tmp = new char[n + 1];
                strcpy(tmp, _str);
                delete[] _str;

                _str = tmp;
                _capacity = n;
            }
        }
        void insert(size_t pos, char ch)
        {
            assert(pos <= _size);

            if (_size == _capacity)
            {
                size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
                reserve(newcapacity);
            }
            size_t end = _size + 1;
            while (end > pos)
            {
                _str[end] = _str[end - 1];
                --end;
            }
            _str[pos] = ch;
            ++_size;
        }
        void 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;
            //注意pos=0时,对应的值为size_t类型,要int转
            while (end > (int)pos)
            {
                _str[end+len] = _str[end];
                --end;
            }

            memcpy(_str + pos, str, len);//void * memcpy ( void * destination, const void * source, size_t num );
            _size += len;
        }
        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 erase(size_t pos = 0, size_t len = npos)
        {
            assert(pos < _size);

            // len大于前面字符个数时,有多少删多少
            if (len >= _size - pos)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                strcpy(_str + pos, _str + pos + len);
                _size -= len;
            }
        }

        size_t find(char ch, size_t pos = 0)
        {
            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)
        {
            char* p = strstr(_str + pos, str);//char * strstr (char * str1, const char * str2 );
            return  p - _str;
        }
        void swap(string& s)
        {
            std::swap(_str, s._str);
            std::swap(_size, s._size);
            std::swap(_capacity, s._capacity);
        }
        string substr(size_t pos = 0, size_t len = npos)
        {
            // len大于后面剩余字符,有多少取多少
            if (len > _size - pos)
            {
                string sub(_str + pos);
                return sub;
            }
            else
            {
                string sub;
                sub.reserve(len);
                for (size_t i = 0; i < len; i++)
                {
                    sub += _str[pos + i];
                }
                return sub;
            }
        }
        bool operator<(const string& s) const
        {
            return strcmp(_str, s._str) < 0;
        }
        bool operator>(const string& s) const
        {
            return !(*this <= s);
        }
        bool operator<=(const string& s) const
        {
            return *this < s || *this == s;
        }
        bool operator>=(const string& s) const
        {
            return !(*this < s);
        }
        bool operator==(const string& s) const
        {
            return strcmp(_str, s._str) == 0;
        }
        bool operator!=(const string& s) const
        {
            return !(*this == s);
        }
        void clear()
        {
            _str[0] = '\0';
            _size = 0;
        }
    private:
        // char _buff[16];
        char* _str;
        size_t _size;
        size_t _capacity;
        const static size_t npos;
    };
    istream& operator>> (istream& is, string& str)
    {
        str.clear();
        char ch = is.get();
        while (ch != ' ' && ch != '\n')
        {
            str += ch;
            ch = is.get();
        }
        return is;
    }
    ostream& operator<< (ostream& os, const string& str)
    {
        for (size_t i = 0; i < str.size(); i++)
        {
            os << str[i];
        }
        return os;
    }
}

长图形式:

还需大家一起改善!我们共赴山海!~~~~~

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

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

相关文章

【Qt】Qt开源项目

1、Flameshot 截图工具 1.1 简介 Flameshot是一款功能强大但易于使用的屏幕截图软件,中文名称火焰截图。 Flameshot 简单易用并有一个CLI版本,所以可以从命令行来进行截图。 Flameshot 是一个Linux发行版中完全免费且开源的截图工具 1.2 源码 github:https://github.com…

波搜索算法(WSA)-2024年SCI新算法-公式原理详解与性能测评 Matlab代码免费获取

​ 声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 一、初始化阶段 二、全…

计算机Java项目|Springboot高校心理教育辅导设计与实现

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…

ThreadLocal,一次到位

一、定义 ThreadLocal是线程私有变量&#xff0c;用于保存每个线程的私有数据。 那么什么情况下需要进行线程隔离 二、源码分析 public class ThreadLocalTest01 {ThreadLocal<Integer> t new ThreadLocal<>();public void test() {t.set(1);Integer integer…

前馈神经网络FNN、多层感知机MLP和反向传播推导

目录 一、前馈神经网络FNN 激活函数的使用 二、多层感知机MLP MLP的典型结构 多层感知机MLP的特点 和前馈神经网络FNN的区别 三、传播推导 1、前向传播(Forward propagation) &#xff08;1&#xff09;输入层到隐藏层 &#xff08;2&#xff09;隐藏层到输出层 2、…

如何去除字符串两侧的空白字符?

TRIM函数会去掉字符串左侧和右侧的空格&#xff0c;语法是&#xff1a;TRIM(字符串) excel中&#xff0c;TRIM函数能去掉字符串左侧和右侧的空格&#xff0c;它的ASCII码是32。 以下设定一个字符串组合&#xff0c;它的第一个字符中空格&#xff0c;最后一个字符是换行符 &q…

头歌实践教学平台:CG1-v1.0-点和直线的绘制

第3关&#xff1a;OpenGL直线绘制 一.任务描述 根据下面要求&#xff0c;在右侧修改代码&#xff0c;绘制出预期输出的图片。平台会对你编写的代码进行测试。 1.本关任务 理解基本图形元素光栅化的基本原理&#xff1b; 了解和使用OpenGL的生成直线的命令&#xff0c;来验证…

MySQL深入理解MVCC机制(详解)

深入理解MVCC 1、MVCC定义 MVCC:Multi-Version Concurrency Control&#xff0c;多版本并发控制机制。 在mysql中&#xff0c;为了满足事务的四大特性之一的隔离性&#xff0c;就是当前事务中的查询的数据不受其他事务的增删改操作的影响&#xff0c;因此mysql主要是通过这个…

VUE之旅—day2

文章目录 Vue生命周期和生命周期的四个阶段created应用—新闻列表渲染mounted应用—进入页面搜索框就获得焦点账单统计&#xff08;Echarts可视化图表渲染&#xff09; Vue生命周期和生命周期的四个阶段 思考&#xff1a; 什么时候可以发送初始化渲染请求&#xff1f;&#xff…

08 - hive的集合函数、高级聚合函数、炸裂函数以及窗口函数

目录 1、集合函数 1.1、size&#xff1a;集合中元素的个数 1.2、map&#xff1a;创建map集合 1.3、map_keys&#xff1a; 返回map中的key 1.4、map_values: 返回map中的value 1.5、array 声明array集合 1.6、array_contains: 判断array中是否包含某个元素 1.7、sort_a…

Java中的数组、Set、List、Map类型的互相转换总结

序言 数组、Set、List、Map是Java语言非常常用的几种数据类型&#xff0c;他们之间存在着千丝万缕的联系。关于底层的数据结构我这里就不再多说啦&#xff0c;直接从应用出发&#xff0c;总结他们之间的转换方法&#xff0c;并给出推荐方法。 大家可以点赞收藏等到需要的时候…

四、基于Stage模型的应用架构设计

前面我们了解了如何构建鸿蒙应用以及开发了第一个页面&#xff0c;这只是简单的demo&#xff1b;那么如何去设计&#xff0c;从0到1搭建一个真正的应用呢 一、基本概念 1、Stage模型基本概念 Stage模型概念图 AbilityStage&#xff1a;是一个Module级别的组件容器&#xff0…

C语言/数据结构——栈的实现

一.前言 今天我们讲解新的领域——栈。 二.正文 1.栈 1.1栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其允许在固定的一段进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#…

LLama3大模型本地部署 仅需6步完成对话模型本地安装部署。附送可视化ui安装、自定义模型目录,修改模型保存地址,第三方微调模型、中文模型下载地址

本篇分为三部分 一&#xff1a;6步完成llama3大模型本地部署 二&#xff1a;8步完成llama3可视化对话界面安装 三&#xff1a;重设模型文件路径 四&#xff1a;微调模型、中文模型下载资源分享 一、LLama3 大模型本地部署安装 首先去mata官网下载ollama客户端 Ollama 选择合适…

通俗易懂讲乐观锁与悲观锁

浅谈乐观锁与悲观锁 乐观锁和悲观锁是Java并发编程中的两个概念。使用乐观锁和悲观锁可以解决并发编程中数据不一致性、死锁、性能差等问题&#xff0c;乐观锁与悲观锁的实行方式不同&#xff0c;所以其特性也不近相同&#xff0c;下文将详细介绍两者的特性与适用场景。 《熊…

OFDM 802.11a的FPGA实现(十六)长训练序列:LTS(含Matlab和verilog代码)

目录 1.前言2.原理3.Matlab生成长训练序列4.硬件实现5.ModelSim仿真6.和Matlab仿真结果对比 原文链接&#xff08;相关文章合集&#xff09;&#xff1a; OFDM 802.11a的xilinx FPGA实现 1.前言 在之前已经完成了data域数据的处理&#xff0c;在构建整个802.11a OFDM数据帧的时…

【Redis】Redis面试和工作中十有八九会遇到的问题

1. 数据类型 常用的Redis数据类型有5种&#xff0c;分别是&#xff1a; String、List、Set、SortedSet、Hash 还有一些高级数据类型&#xff0c;比如Bitmap、HyperLogLog、GEO等&#xff0c;其底层都是基于上述5种基本数据类型。因此在Redis的源码中&#xff0c;其实只有5种数…

React: memo

React.memo 允许你的组件在 props 没有改变的情况下跳过重新渲染。 const MemoizedComponent memo(SomeComponent, arePropsEqual?)React 通常在其父组件重新渲染时重新渲染一个组件。你可以使用 memo 创建一个组件&#xff0c;当它的父组件重新渲染时&#xff0c;只要它的新…

Docker Compose常用命令与属性

大家好&#xff0c;今天给大家分享Docker Compose的常用命令&#xff0c;以及docker-compose文件的属性。Docker Compose 是一个用于定义和运行多容器 Docker 应用应用的重要工具。它通过一个配置文件&#xff08;docker-compose.yml&#xff09;来详细定义多个容器之间的关联、…

软考中级-软件设计师 (十一)标准化和软件知识产权基础知识

一、标准化基础知识 1.1标准的分类 根据适用的范围分类&#xff1a; 国际标准指国际化标准组织&#xff08;ISO&#xff09;、国际电工委员会&#xff08;IEC&#xff09;所制定的标准&#xff0c;以及ISO所收录的其他国际组织制定的标准。 国家标准&#xff1a;中华人民共和…