[C++]:9: string类的模拟实现

string类的模拟实现

  • 0:类的成员变量:
  • 一.构造析构赋值:
    • 1.构造:
    • 2.析构:
    • 3.赋值:
  • 二.容量相关:
    • 1.size()
    • 2.capacity()
    • 3.reserve()
    • 4.clear()
    • 5.empty()
  • 三.c_str和operator[]
    • 1.c_str
    • 2.operator[]
  • 四.push_back 和 append 和 operator+=
    • 1.push_back:
    • 2.append:
    • 3.operator+=:
      • string& operator+= (const string& str);
      • string& operator+= (const char* s);
      • string& operator+= (char c);
  • 五:insert 和 erase 和 swap
    • 1.insert:
      • 1-1: 在pos位置插入单个字符:
      • 1-2:在pos位置插入const char* 数据:
    • 2.erase:
    • 3.swap:
  • 六. find() 和 substr()
    • 1.find()
      • 1-1:size_t find (const char* s, size_t pos = 0) const;
      • 1-2:size_t find (char c, size_t pos = 0) const;
    • 2.substr()
  • 七:iterator:
  • 八:流插入和流提取:
    • 流插入:
    • 流提取:

0:类的成员变量:

在这里插入图片描述

//测试:遍历用来测试代码:void print_str(){assert(_str != nullptr);for (size_t pos = 0; pos < _size; pos++){std::cout << _str[pos];}std::cout << std::endl;}

一.构造析构赋值:

1.构造:

在这里插入图片描述

1.我们观察一下实现1和4可以实现一个缺陷省参数去把两个构造给包含在一起:

//1-1:空和const char* sstring(const char* str="\0")//const char* str = "" C语言特性空字符串就是一个"\0"{//问题一:建议不要使用初始化列表进行:因为初始化列表的顺序是根据成员变量声明的顺序。//问题二:应该开辟的空间大小?//_size 的意义是:当前有效字符的个数 _capacity的意义是:当前可以存放的最多的有效字符的个数:if (str == "\0"){_str = new char[1] {'\0'};_size = 0;_capacity = 0;}else{size_t len = strlen(str);_str = new char[len+1];strcpy(_str, str);_size = len;_capacity = len;}}

2.2是我们的拷贝构造是需要实现的!

string(const string& str){if (str._size == str._capacity){if (str._capacity == 0){_str = new char[1] {'\0'};_size = 0;_capacity = 0;}else{_str = new char[str._capacity + 1];for (int i = 0; i < str._size; i++){_str[i] = str._str[i];}_size = str._size;_capacity = str._capacity;}}}

3.6是使用n个C字符实现去构造一个字符串也可以实现一下:

string(size_t n, const char c){if (n == 0){_str = new char[1] {'\0'};_size = 0;_capacity = 0;}else{_str = new char[n + 1];size_t pos = 0;for (pos = 0; pos < n; pos++){_str[pos] = 'c';}_str[pos] = '\0';_size = n;_capacity = n;}}

2.析构:

//2:析构函数:~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}

3.赋值:

在这里插入图片描述

1.string 类型的赋值:

//2-1:字符串赋值:string& operator=(const string& str){//1.排除自己给自己赋值的情况!if (this == &str)return *this;//2.考虑str比较长的情况:if (str._size > _capacity){//1.开一个空间:char* tmp = new char[str._size + 1];//2.拷贝数据到新空间:strcpy(tmp, str._str);//3.释放旧空间:delete[] _str;_str = tmp;_size = str._size;_capacity = str._size;}//3.被赋值的变量的_capacity是足够的!else{strcpy(_str, str._str);_size = str._size;}return *this;}

2.const char* 类型的赋值:

//2-2:const char* 赋值:string& operator=(const char* str){size_t len = strlen(str);//2.考虑str比较长的情况:if (len > _capacity){//1.开一个空间:char* tmp = new char[len + 1];//2.拷贝数据到新空间:strcpy(tmp, str);//3.释放旧空间:delete[] _str;_str = tmp;_size = len;_capacity = len;}//3.被赋值的变量的_capacity是足够的!else{strcpy(_str, str);_size = len;}return *this;}

二.容量相关:

1.size()

在这里插入图片描述

//3-1:size():不对对象进行修改只去读数据的代码给*this加一个const修饰! size_t size()const{return _size;}

2.capacity()

在这里插入图片描述

//3-2: capacity()size_t capacity()const{return _capacity;}

3.reserve()

在这里插入图片描述

//3-3:reserve():n为多大就开多大的有效空间:void reserve(size_t n){//1.不考虑容量减少的情况://2.C++ 下是没有realloc函数://2-1:开一个大小为n的新的空间:char* tmp = new char[n+1];//2-2:把字符串用来的内容放到新开辟好的空间里面:strcpy(tmp, _str);//2-3:原来空间释放+数值的更新:delete[] _str;_str = tmp;_capacity = n;}

4.clear()

在这里插入图片描述

//3-4:clear():擦除字符串内容+把字符串变成空字符串void clear(){delete[] _str;_str = new char[1] {'\0'};_size = 0;_capacity = 0;}

5.empty()

在这里插入图片描述

//3-5:empty():判断字符串是否为空:bool empty(){if (_size == 0){return true;}return false;}

三.c_str和operator[]

1.c_str

//4-1:c_str():const char* c_str()const{return _str;}

2.operator[]

//4-2:operator[]//4-2-1:只读://const string * this 修饰内容://1.引用返回造就了可读可写!//2.双const修饰防止了引用返回导致的修改的可能性!const char& operator[](size_t pos)const{assert(_str != nullptr);return _str[pos];}//4-2-2:可读可写://1.引用返回造就了可读可写!char& operator[](size_t pos){assert(_str != nullptr);return _str[pos];}

四.push_back 和 append 和 operator+=

1.push_back:

在这里插入图片描述

//5-1:push_back()void push_back(char c){assert(_str != nullptr);if (_size == _capacity){//1.处理开始为0的情况,正常就去扩二倍:_capacity = _capacity == 0 ? 4 : _capacity*2;//2.使用reserve非常方便:reserve(_capacity);}//3.要保持住结尾的'\0'_str[_size++] = c;_str[_size] = '\0';}

2.append:

在这里插入图片描述

1.加上一个字符串:

	//5-2-1:添加一个字符串:string& append(const string& str){assert(_str != nullptr);size_t len = str.size();if (len + _size > _capacity){reserve(len + _size + 1);}strcpy(_str+_size, str._str);_size += str._size;return *this;}

2.加上一个const char*

//5-2-2:添加一个const char* 的值:string& append(const char* str){assert(_str != nullptr);size_t len = strlen(str);if (len + _size > _capacity)ize{reserve(len + _size + 1);}strcpy(_str + _size, str);_size += len;return *this;}

3.operator+=:

在这里插入图片描述

string& operator+= (const string& str);

string& operator+= (const string& str){append(str);return *this;}

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

string& operator+= (char c){push_back(c);return *this;}

string& operator+= (char c);

string& operator+= (const char* s){append(s);return *this;}

五:insert 和 erase 和 swap

1.insert:

在这里插入图片描述

1-1: 在pos位置插入单个字符:

string& insert(size_t pos , char c){assert(pos < _size);if (_size + 1 > _capacity){reserve(_size + 1);}size_t end = _size + 1;while (pos < end){_str[end] = _str[end - 1];end--;}_str[pos] = c;_size += 1;_str[_size] = '\0';return *this;}

1-2:在pos位置插入const char* 数据:

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 (pos < end){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str,len);_size += len;_str[_size] = '\0';return *this;}

2.erase:

在这里插入图片描述

	string& erase(size_t pos = 0, size_t len = npos){assert(_str != nullptr);if (len == npos || len > _size - pos){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);}return *this;}

3.swap:

在这里插入图片描述

1.swap 为什么会有三个重载:
2.string 类实现的swap方法:
3.swap一个全局的:
4.使用全局函数模板生成的一个string

void swap(string& s1, string& s2){char* tmp = s1._str;size_t tmp_1 = s1._size;size_t tmp_2 = s2._capacity;s1._str= s2._str;s1._size= s2._size;s1._capacity= s2._capacity;s2._str = tmp;s2._size = tmp_1;s2._capacity = tmp_2;}//6-3:swap()void swap(string& str){swap(*this, str);}

六. find() 和 substr()

1.find()

在这里插入图片描述

1-1:size_t find (const char* s, size_t pos = 0) const;

size_t find(const char* ch, size_t pos = 0){assert(pos < _size);//1.有可能找不到子串:const char* ptr = strstr(_str, ch);if (ptr == nullptr){return npos;}else{return ptr - _str;}}

1-2:size_t find (char c, size_t pos = 0) const;

//7:find() substr()size_t pos(char ch , size_t pos = 0){assert(pos < _size);for (size_t pos = 0; pos < _size; pos++){if (_str[pos] == ch){return pos;}}}

2.substr()

在这里插入图片描述

string substr(size_t pos , size_t len=npos){string str;if (len == npos || len > _size-pos){str.reserve(_size - pos);}for (size_t i = pos; i < _size; i++){str += _str[i];}return str;}

七:iterator:

在这里插入图片描述

1.begin()

//8:iterator()typedef char* iterator;iterator begin(){return _str;}

2.end()

iterator end(){return _str + _size;}

3.使用:

void text_8()
{sfpy::string s1("hello iterator");sfpy::string::iterator it_1 = s1.begin();while (it_1!=s1.end()){std::cout << (*it_1);it_1++;}}

八:流插入和流提取:

流插入:

在这里插入图片描述

std::istream& operator>>(std::istream& _cin, string& s1)
{//assert(string::_str != nullptr);char tmp = 0;while (scanf("%c", &tmp) != 0 && tmp != '\n'){s1.push_back(tmp);}return _cin;
}

流提取:

在这里插入图片描述

std::ostream& operator<<(std::ostream& _cout, string& s1)
{//assert(string::_str != nullptr);string::iterator it_1 = s1.begin();while (it_1 != s1.end()){_cout << (*it_1);it_1++;}return _cout;
}

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

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

相关文章

进入最后倒计时!就在深圳福田明天上午9点正式开幕!不容错过!

会展中心介绍 深圳会展中心交通快捷便利&#xff0c;南邻滨河快速干道&#xff0c;与口岸、港口及高速公路相连&#xff0c;驾车驱往深圳火车站仅需15分钟、深圳机场仅需30分钟。地铁1号、4号线在会展中心站接驳&#xff0c;通过市政地下通道可从馆内直达地铁站&#xff0c;仅需…

【MATLAB】RLMD分解+FFT+HHT组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 RLMD分解FFTHHT组合算法是一种强大的分析方法&#xff0c;结合了局部均值分解&#xff08;LMD&#xff09;、快速傅里叶变换&#xff08;FFT&#xff09;和希尔伯特-黄变换&#xff08;H…

5W2H分析法

5W2H分析法 5W2H分析法又叫七问分析法。 模型介绍 简单、方便&#xff0c;易于操作的思考&#xff08;框架&#xff09;模型&#xff0c;问题分析模型&#xff0c;它可以帮助我们保证思考的严谨与全面&#xff0c;也能给人启发&#xff0c;有着广泛的应用&#xff1a; 提问-可…

MySQL索引使用总结

索引(index) 官方定义&#xff1a;一种提高MySQL查询效率的数据结构 优点&#xff1a;加快查询速度 缺点&#xff1a; 1.维护索引需要消耗数据库资源 2.索引需要占用磁盘空间 3.增删改的时候会影响性能 索引分类 索引和数据库表的存储引擎有关&#xff0c;不同的存储引擎&am…

探索Python内置类属性__repr__:展示对象的魅力与实用性

概要 在Python中&#xff0c;每个对象都有一个内置的__repr__属性&#xff0c;它提供了对象的字符串表示形式。这个特殊的属性在调试、日志记录和交互式会话等场景中非常有用。本文将详细介绍__repr__属性的使用教程&#xff0c;包括定义、常见应用场景和注意事项&#xff0c;…

单片机复位电路

有时候我们的代码会跑飞,这个时候基本上是一切推到重来.”推倒重来”在计算机术语上称为复位.复位需要硬件的支持,复位电路就是在单片机的复位管脚上产生一个信号&#xff0c;俗称复位信号.这个信号需要持续一定的时间,单片机收到该信号之后就会复位,从头执行。 复位原理: 那么…

Vue实现可拖拽边界布局

Vue实现可拖拽边界布局 在前端开发中&#xff0c;有时需要实现一种可拖拽边界的布局&#xff0c;通过拖动分隔线来调整不同区域大小。例如&#xff0c;下图是一个典型的可拖拽边界布局&#xff0c;它由左右两个区域组成&#xff0c;左边是一个树形菜单&#xff0c;右边是一个上…

如何用眼精星票证识别系统识别名片?

近年来&#xff0c;随着信息化技术的不断发展&#xff0c;越来越多的人开始使用电子名片来进行商务交流和信息传递。然而&#xff0c;如何将纸质名片转化为电子名片并结构化数据&#xff0c;却一直是许多人的难题。本文将介绍一种使用眼精星票证识别系统的方法&#xff0c;将纸…

C++ day42背包理论基础01 + 滚动数组

背包问题的重中之重是01背包 01背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 每一件物品其实只有两个状态&#xff0c;取或者不…

springboot2.0 集成swagger3+Knife4j导出离线API 配置

springboot 版本2.3.1 一、集成swagger3 引入swagger依赖包 <!--swagger3集成--><dependency><groupId>org.springframework.plugin</groupId><artifactId>spring-plugin-core</artifactId><version>2.0.0.RELEASE</version>…

Mysql单表查询练习

一、单表查询 素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker (部门号 int(11) NOT NULL,职工号 int(11) NOT NULL,工作时间 date NOT NULL,工资 float(8,2) NOT NULL,政治面貌 varchar(10…

为什么Redis这么快?5分钟成为Redis高手

Redis简介 Redis 是 C 语言开发的一个开源高性能键值对的内存数据库&#xff0c;可以用来做数据库、缓存、消息中间件等场景&#xff0c;是一种 NoSQL&#xff08;not-only sql&#xff0c;非关系型数据库&#xff09;的数据库。 Redis特点 优秀的性能&#xff0c;数据是存储…