c++|string模拟实现

 

目录

一、string.h

二、string.cpp

三、Test.cpp


对string的各种接口进行一个简易版的模拟实现,在模拟实现完之后对string的底层实现有了进一步的理解,了解大佬的编程写法思路。也算是对string有了一个小总结。

一、string.h

接口的声明。放在.h文件中 

#include <iostream>
#include <string>
#include <assert.h>
using namespace std;namespace bit
{class string{public:typedef char* iterator;//迭代器本质上就是指针typedef const char* const_iterator;iterator begin() const{return _str;}iterator end(){return _str + _size;}const_iterator end() const{return _str + _size;}string(const char* s = "");string(const string& s);string& operator=(string s);~string();void push_back(char c);string& operator+=(char c);string& operator+=(const string& s);string& operator+=(const char* str);void append(const char* str);void clear();void swap(string& s);const char* c_str()const;//capacitysize_t size();size_t capacity();void resize(size_t n, char c = '\0');void reserve(size_t n);bool empty()const;bool operator<(const string& s);bool operator<=(const string& s);bool operator>(const string& s);bool operator>=(const string& s);bool operator==(const string& s);;bool operator!=(const string& s);char& operator[](size_t i);const char& operator[](size_t i) const;//返回字符第一次在字符串出现的位置size_t find(char c, size_t pos = 0) const;;//在pos位置插入字符cstring& insert(size_t pos, char c);//在pos位置插入字符串string& insert(size_t pos, const char* str);//返回子串在字符串中出现的位置size_t find(const char* str, size_t pos = 0);string substr(size_t pos = 0, size_t len = npos);//	删除pos位置上的元素,并返回该元素的下一个位置string& erase(size_t pos, size_t len = npos);private:size_t _size;size_t _capacity;char* _str;//静态变量可以赋值处理的前提是有const修饰,这个可以看作是编译器的特殊处理,只能适用于整形家族static const size_t npos = -1;};ostream& operator<<(ostream& out, const string& s);istream& operator>>(istream& in, string& s);
}

二、string.cpp

接口的各种实现。进行声明定义分离时,要注意格式上的变化,指定类域,声明和定义中,只有声明中可以给缺省值,定义中不能给。string的构造函数有传统写法和现代写法,现代写法更简洁,但和传统写法本质上没有太大的区别

#include "string.h"namespace bit
{//string()//	:_str(nullptr)//不能给空,析构时会对空指针解引用,从而报错//	,_size(0)//	,_capacity(0)//{}//string()//	:_size(0)//	,_capacity(_size)//	,_str(new char[_capacity + 1])//这样必须给定成员变量声明顺序。//{}string::string(const char* s){_size = strlen(s);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, s);}//传统写法/*	string(const string& s){_str = new char[s._capacity + 1];_size = s._size;_capacity = s._capacity;strcpy(_str, s._str);}*///现代写法string::string(const string& s){string tmp(s._str);swap(tmp);}//传统写法//string& operator=(const string& s)//{//	if (*this != s)//	{//		char* tmp = new char[s._capacity + 1];//		delete[] _str;//		strcpy(tmp, s._str);//		_str = tmp;//		_size = s._size;//		_capacity = s._capacity;//		return *this;//	}//	return *this;//	//}//现代写法/*string& operator=(const string s){string tmp(s._str);swap(tmp);return *this;}*/string& string::operator=(string s){swap(s);return *this;}string::~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}//modifyvoid string::push_back(char c){if (_size == _capacity)//初始化容量以及判断容量是否满了{size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;/*		if (_str != ""){char* tmp = new char[newcapacity + 1];memcpy(tmp, _str, _size);delete[] _str;_str = tmp;_capacity = newcapacity;}*/reserve(newcapacity);}_str[_size] = c;_size++;_str[_size] = '\0';}string& string::operator+=(char c){push_back(c);return *this;}string& string::operator+=(const string& s){if (_size + s._size > _capacity){reserve(_size + s._size);}strcpy(_str + _size, s._str);_size += s._size;return *this;}string& string::operator+=(const char* str){append(str);return *this;}void string::append(const char* str){if (_size + strlen(str) > _capacity){reserve(_size + strlen(str));}strcpy(_str + _size, str);_size += strlen(str);}void string::clear(){_str[0] = '\0';_size = 0;_capacity = 0;}void string::swap(string& s){std::swap(_str, s._str);std::swap(this->_size, s._size);std::swap(this->_capacity, s._capacity);}const char* string::c_str()const{return _str;}//capacitysize_t string::size(){return _size;}size_t string::capacity(){return _capacity;}void string::resize(size_t n, char c){if (n > _capacity){reserve(n);for (int i = _capacity; i < n; i++)push_back(c);}else if (n > _size && n < _capacity){for (int i = _size; i < n; i++)push_back(c);}else if (n < _size){_str[n] = '\0';}}void string::reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;//_size = strlen(tmp);_capacity = n;}}bool string::empty()const{return _str == "";}bool string::operator<(const string& s){return strcmp(_str, s._str) < 0;}bool string::operator<=(const string& s){return !(*this > s);}bool string::operator>(const string& s){return strcmp(_str, s._str) > 0;}bool string::operator>=(const string& s){return !(*this < s);}bool string::operator==(const string& s){return strcmp(_str, s._str) == 0;}bool string::operator!=(const string& s){return !(strcmp(_str, s._str) == 0);}char& string::operator[](size_t i){return _str[i];}const char& string::operator[](size_t i) const{return _str[i];}//返回字符第一次在字符串出现的位置size_t string::find(char c, size_t pos) const{assert(pos <= _size);for (int i = pos; i < _size; i++){if (_str[i] == c)return i;}return npos;}//在pos位置插入字符cstring& string::insert(size_t pos, char c){assert(pos <= _size);if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}if (pos == _size)push_back(c);else{size_t len = _size - pos;while (len){_str[pos + len] = _str[pos + len - 1];len--;}_str[pos] = c;}_size++;_str[_size] = '\0';return *this;}//在pos位置插入字符串string& string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (len + _size >= _capacity){reserve(len + _size);}if (pos == _size){append(str);}else{size_t ilen = _size - pos;while (ilen){_str[pos + ilen + len] = _str[pos + ilen];ilen--;}for (int i = pos, j = 0; i < pos + len; i++, j++){_str[i] = str[j];}}_size += len;_str[_size] = '\0';return *this;}//返回子串在字符串中出现的位置size_t string::find(const char* str, size_t pos){assert(pos <= _size);size_t len = strlen(str);if (pos + len > _size)return npos;else{size_t fpos = find(str[0], pos);for (int i = fpos, j = 0; i < fpos + len; i++, j++){if (str[j] != _str[i])return npos;}return fpos;}}string string::substr(size_t pos, size_t len){assert(pos <= _size);string tmp;size_t end = pos + len;//if (len == npos || len >= _size - pos)//{//	tmp.reserve(_size - pos);//	strcpy(tmp._str, _str + pos);//	return tmp;//}//else//{//	memcpy(tmp._str, _str + pos, len);//	tmp[len] = '\0';//	return tmp;//}if (len == npos || len >= _size - pos){end = _size;}tmp.reserve(end - pos);for (int i = pos; i < end; i++){tmp += _str[i];}return tmp;}//	删除pos位置上的元素,并返回该元素的下一个位置string& string::erase(size_t pos, size_t len){assert(pos < _size);if (len == npos || len > _size){_str[pos] = '\0';}else{/*size_t length = len + pos;while (pos < length){_str[pos] = _str[pos + len];pos++;}_str[_size - len] = '\0';*/strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}ostream& operator<<(ostream& out, const string& s){for (auto e : s){out << e;}return out;}istream& operator>>(istream& in, string& s){s.clear();char buff[128];char ch = in.get();int i = 0;while (ch != ' ' && ch != '\n'){buff[i] = ch;i++;if (i == 127){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}}

三、Test.cpp

测试版本,对接口进行测试,写了三个测试版本,但并没有调用全部接口,进行一番演示,大致还行,可能还有错误,也是水平有限。 

#include "string.h"
namespace bit
{void stringtest1(){string s("hello world");string::iterator it = s.begin();while (it != s.end()){cout << *it;it++;}cout << endl;for (auto e : s){cout << e;}cout << endl;string s1(s);string s2 = s1;for (auto e : s1){cout << e;}cout << endl;for (auto e : s2){cout << e;}cout << endl;}void stringtest2(){string s("hello world");s += "hello world";for (auto e : s){cout << e;}cout << endl;string s1;s1.push_back('a');s1.push_back('b');s1.push_back('c');s1.push_back('d');for (auto e : s1){cout << e;}cout << endl;cout << (s < s1);cout << (s > s1);cout << (s == s1);cout << (s <= s1);cout << (s >= s1);cout << true;};void stringtest3(){string s("hello world");string s1 = "excuse me";/*s.swap(s1);cout << s.c_str() << " " << s1.c_str() << endl;cout << s.capacity() << endl;s.reserve(100);cout << s.capacity() << endl;s.resize(5);cout << s.capacity() << " " << s.c_str() << endl;;*///cout << s[0];size_t pos = s.find("world");cout << pos << endl;cout << s.substr().c_str() << endl;s.insert(0, 'w');cout << s.c_str() << endl;s.insert(6, 'e');cout << s.c_str() << endl;s1.insert(0, "hello");cout << s1.c_str() << endl;s1.insert(5, "hello");cout << s1.c_str() << endl;cin >> s1;cout << s1;}
}
int main()
{bit::stringtest1();bit::stringtest2();bit::stringtest3();return 0;
}

三个测试函数的输出结果 :

 

 

 

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

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

相关文章

MySQL安装和配置(超详细)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

武汉星起航公司助力零经验新手卖家征战亚马逊跨境电商市场

在数字化浪潮的推动下&#xff0c;亚马逊跨境电商行业正逐渐成为众多创业者和企业家们的新战场。然而&#xff0c;对于零经验的新手卖家而言&#xff0c;这片广袤的电商海洋无疑充满了未知与挑战。在这个关键时刻&#xff0c;武汉星起航公司以其专业的服务和深厚的行业积累&…

day 36 贪心算法 part05● 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

一遍过。首先把区间按左端点排序&#xff0c;然后右端点有两种情况。 假设是a区间&#xff0c;b区间。。。这样排列的顺序&#xff0c;那么 假设a[1]>b[0],如果a[1]>b[1]&#xff0c;就应该以b[1]为准&#xff0c;否则以a[1]为准。 class Solution { public:static bo…

老阳分享:视频号带货怎么做?有哪些方法?

在数字化浪潮中&#xff0c;视频号带货成为了一种新兴的商业模式&#xff0c;它结合了视频内容的吸引力和电商销售的便捷性&#xff0c;为品牌和商家带来了无限商机。那么&#xff0c;视频号带货究竟应该怎么做?又有哪些有效的方法呢? 首先&#xff0c;视频号带货的核心在于内…

行为管理设置能监控或者检测哪些东西

3 月 27 日&#xff0c;国新办举行“推动高质量发展”系列主题新闻发布会&#xff0c;浙江省省长王浩&#xff1a;全省市场经营主体 1040 万户&#xff0c;相当于平均每 6.5 个浙江人就有 1 个老板。 不由让小编想到&#xff0c;这么多老板&#xff0c;那么老板创办企业也怪不容…

【JavaEE】初识线程,线程与进程的区别

文章目录 ✍线程是什么&#xff1f;✍线程和进程的区别✍线程的创建1.继承 Thread 类2.实现Runnable接口3.匿名内部类4.匿名内部类创建 Runnable ⼦类对象5.lambda 表达式创建 Runnable ⼦类对象 ✍线程是什么&#xff1f; ⼀个线程就是⼀个 “执行流”. 每个线程之间都可以按…

大数据开发(离线实时音乐数仓)

大数据开发&#xff08;离线实时音乐数仓&#xff09; 一、数据库与ER建模1、数据库三范式2、ER实体关系模型 二、数据仓库与维度建模1、数据仓库&#xff08;Data Warehouse、DW、DWH&#xff09;1、关系型数据库很难将这些数据转换成企业真正需要的决策信息&#xff0c;原因如…

【快速解决】解决谷歌自动更新的问题,禁止谷歌自动更新,如何防止chrome自动升级 chrome浏览器禁止自动升级设置方法

目录 问题描述 解决方法 1、搜索栏搜索控制面板 2、搜索&#xff1a;服务 ​编辑 3、点击Windows工具 4、点击服务 ​5、禁止谷歌更新 问题描述 由于我现在需要装一个谷歌的驱动系统&#xff0c;但是目前的谷歌驱动系统的版本都太旧了&#xff0c;谷歌自身的版本又太新了…

上海:6月1日起取消企业复工复产白名单制

财经新闻5月29日消息&#xff1a;上海市人民政府关于印发《上海市加快经济恢复振兴行动计划》的通知。 《方案》包括千方百计缓解各类市场主体困难&#xff0c;全面有序推进复工复产和市场复工复产&#xff0c;多措并举稳外资稳外贸&#xff0c;大力促进消费加速复苏&#xff0…

argocd cli工具使用

一、前言 ragocd除了使用web界面操作之外&#xff0c;也可以通过argocd cli工具进行操作&#xff0c;关于集群创建、gitlab仓库创建、app创建都是可以通过yaml 文件去操作&#xff0c;使用web界面创建的操作也需要使用argocd cli工具进行备份 二、使用 在argocd部署的章节已经…

Windows安装Odoo结合内网穿透实现公网访问本地企业管理系统

文章目录 前言1. 下载安装Odoo&#xff1a;2. 实现公网访问Odoo本地系统&#xff1a;3. 固定域名访问Odoo本地系统 前言 Odoo是全球流行的开源企业管理套件&#xff0c;是一个一站式全功能ERP及电商平台。 开源性质&#xff1a;Odoo是一个开源的ERP软件&#xff0c;这意味着企…

盏燕生物科技将出席2024第七届燕窝天然滋补品博览会

参展企业介绍 深圳市盏燕生物科技有限公司&#xff0c;办公室地址位于中国第一个经济特区&#xff0c;鹏城深圳&#xff0c;深圳市龙岗区平湖街道禾花社区富安大道18号亚钢工贸大楼1栋1017A&#xff0c;我公司主要提供一般经营项目是&#xff1a;初级农产品、海产品、化妆品、…

R使用netmeta程序包实现生存数据的频率学网状meta分析

之前的推文系统的介绍了使用netmeta包实现对二分类变量、连续型变量和罕见事件的网状meta分析。今天的文章介绍如何使用netmeta程序包实现生存数据的频率学网状meta分析&#xff0c;用来评估6种免疫疗法&#xff08; Camrelizumab、Tislelzumab、Toripalimab、Sintilimab、Pemb…

影视文件数字指纹签名检验系统的用户操作安全大多数

国内网盘服务大规模出现版权问题。 一些个人或团体会通过云存储客户端将主要由电影、电视、音乐组成的文件上传到网盘&#xff0c;然后在圈子里分享。 可供下载。 大量受版权保护的视频音乐就是通过这种特殊的盗版方式传播的&#xff0c;而这种传播方式暂时不受监管。 一些云存…

STM32/GD32——自己制定协议和解析协议数据

温馨提醒&#xff1a; 由于我最害怕的就是接触各种新协议&#xff0c;尤其是对各种协议和解析协议数据简直就是职业生涯的噩梦&#xff0c;但工作中不免和不同的协议打交道。本着要啃就啃最难的&#xff0c;大不了放弃的心态。所以我学习了如何自定义制定自己的协议&#xff0c…

小程序的编译上传

小程序如果是hbuilderx开发的&#xff0c;当开发完成后运行到小程序模拟器里面的微信开发者工具&#xff0c;或者&#xff08;发行里面的小程序微信&#xff08;仅适用于uniapp&#xff09;&#xff09;&#xff0c;然后打开微信开发者工具的 项目→里面的导入项目 &#x…

k8s 如何获取加入节点命名

当k8s集群初始化成功的时候&#xff0c;就会出现 加入节点 的命令如下&#xff1a; 但是如果忘记了就需要找回这条命令了。 kubeadm join 的命令格式如下&#xff1a;kubeadm join --token <token> --discovery-token-ca-cert-hash sha256:<hash>--token 令牌--…

虚拟机-从头配置Ubuntu18.04(包括anaconda,cuda,cudnn,pycharm,ros,vscode)

最好先安装anaconda后cuda和cudnn&#xff0c;因为配置环境的时候可能conda会覆盖cuda的路径&#xff08;不确定这种说法对不对&#xff0c;这里只是给大家的建议&#xff09; 准备工作&#xff1a; 1.Ubuntu18.04&#xff0c;x86_64&#xff0c;amd64 虚拟机下载和虚拟机Ubu…

[密码学] 密码学基础

目录 一 为什么要加密? 二 常见的密码算法 三 密钥 四 密码学常识 五 密码信息威胁 六 凯撒密码 一 为什么要加密? 在互联网的通信中&#xff0c;数据是通过很多计算机或者通信设备相互转发&#xff0c;才能够到达目的地,所以在这个转发的过程中&#xff0c;如果通信包…

康耐视visionpro-CogToolBlock工具详细说明

CogToolBlock功能: 将多个工具组合在一起完成某个功能&#xff0c;接口简单且可以重用 CogToolBlock操作说明&#xff1a; 1.打开工具栏&#xff0c;双击或点击鼠标拖拽添加CogToolBlock CogToolBlock操作说明 ②.添加输入图像&#xff0c;右键“链接到”或以连线拖拽的方式选…