C++入门 string的模拟实现

目录

 再谈swap

string常见接口模拟实现 

构造函数 & 析构函数

拷贝构造 & 赋值运算符重载

begin迭代器 & end迭代器

size & swap & clear & c_str

operator[ ] & reserve

push_back & append

operator+= & find

insert & erase

关系运算符重载

流插入 & 流提取

string.h

string.cpp


 再谈swap

在string的库中有两个swap,标准库也有swap的实现,这些swap的区别是什么呢?

那么 string为什么要实现一个类成员函数swap一个非成员函数swap呢?


string常见接口模拟实现 

构造函数 & 析构函数

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

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

拷贝构造 & 赋值运算符重载

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

	string& 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;
	}

begin迭代器 & end迭代器

	string::iterator string::begin()
	{
		return _str;
	}

	string::const_iterator string::begin()const
	{
		return _str;
	}

	string::iterator string::end()
	{
		return _str + _size;
	}

	string::const_iterator string::end()const
	{
		return _str + _size;
	}

size & swap & clear & c_str

	size_t string::size()const
	{
		return _size;
	}

	void string::swap(string& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}

	void string::clear()
	{
		_size = 0;
		_str[0] = '\0';
	}

	const char* string::c_str()const
	{
		return _str;
	}

operator[ ] & reserve

	char& string::operator[](size_t pos)
	{
		assert(pos < _size);
		return _str[pos];
	}

	const char& string::operator[](size_t pos)const
	{
		assert(pos < _size);
		return _str[pos];
	}

push_back & append

	void string::push_back(char ch)
	{
		if (_size == _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newcapacity);
		}
		_str[_size] = ch;
		_str[_size + 1] = '\0';
		_size++;
	}

	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (len + _size > _capacity)
		{
			reserve(len + _size);
		}
		strcpy(_str+_size, str);
		_size += len;
	}

operator+= & find

	//加字符
    string& string::operator+=(char ch)
	{
		push_back(ch);
		return *this;
	}

    //加字符串
	string& string::operator+=(const char* str)
	{
		append(str);
		return *this;
	}

    //找字符
	size_t string::find(char ch, size_t pos)
	{
		for (size_t i = pos; i < _size; i++)
		{
			if (_str[i] == ch)
				return i;
		}
		return npos;
	}
    
    //找字符串
	size_t string::find(const char* str, size_t pos)
	{
		char* p = strstr(_str + pos, str);
		return p - _str;
	}

insert & erase

    //插入字符
	void string::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 string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);

		size_t len = strlen(str);
		if (len + _size > _capacity)
		{
			reserve(len + _size);
		}

		size_t end = _size + len;
		while (end > pos + len - 1)
		{
			_str[end] = _str[end - len];
			--end;
		}
		memcpy(_str + pos, str, len);
		_size += len;
	}

	void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);

		if (len >= _size - len)
		{
			_str[pos] = '\0';
			_size = 0;
		}
		else
		{
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
	}

关系运算符重载

	bool string::operator<(const string& s) const
	{
		return strcmp(_str, s._str) < 0;
	}
	bool string::operator>(const string& s) const
	{
		return !(*this <= s);
	}
	bool string::operator<=(const string& s) const
	{
		return *this < s || *this == s;
	}
	bool string::operator>=(const string& s) const
	{
		return !(*this < s);
	}
	bool string::operator==(const string& s) const
	{
		return strcmp(_str, s._str) == 0;
	}
	bool string::operator!=(const string& s) const
	{
		return !(*this == s);
	}

流插入 & 流提取

	istream& operator>> (istream& is, string& str)
	{
		str.clear();
		char ch = is.get();
		//遇到' '或'\n',流插入停止
		while (ch != ' ' && ch != '\n')
		{
			str += ch;
			ch = is.get();
		}
		return is;
	}

	ostream& operator<< (ostream& os, const string& str)
	{
		for (int i = 0; i < str.size(); i++)
		{
			os << str[i];
		}
		return os;
	}

string.h

#pragma once

#include<iostream>
#include<assert.h>

using namespace std;

namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		//begin()
		iterator begin();
		const_iterator begin()const;

		//end()
		iterator end();
		const_iterator end()const;

		// 构造
		string(const char* str = "");

		// 析构
		~string();

		// 拷贝构造
		string(const string& s);

		// 赋值运算符重载
		string& operator=(const string& s);

		//size
		size_t size()const;

		//operator[]
		char& operator[](size_t pos);
		const char& operator[](size_t pos)const;

		//reserve
		void reserve(size_t n);

		//push_back
		void push_back(char ch);

		//append
		void append(const char* str);
		
		//+=
		string& operator+=(char ch);
		string& operator+=(const char* str);

		//insert
		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);

		//erase
		void erase(size_t pos = 0, size_t len = npos);

		//find
		size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);

		//swap
		void swap(string& s);

		//substr
		string substr(size_t pos = 0, size_t len = npos);

		//relational operators
		bool operator<(const string& s) const;
		bool operator>(const string& s) const;
		bool operator<=(const string& s) const;
		bool operator>=(const string& s) const;
		bool operator==(const string& s) const;
		bool operator!=(const string& s) const;

		//clear
		void clear();
		
		// c_str
		const char* c_str() const;

	private:
		char* _str;
		size_t _size;
		size_t _capacity;

		const static size_t npos;
	};

	istream& operator>> (istream& is, string& str);
	ostream& operator<< (ostream& os, const string& str);
}

string.cpp

#define _CRT_SECURE_NO_WARNINGS 1

#include"string.h"

namespace bit
{
	const size_t string::npos = -1;

	string::string(const char* str)
		:_size(strlen(str))
	{
		_str = new char[_size + 1];
		_capacity = _size;
		strcpy(_str, str);
	}
	string& string::operator=(const string& s)
	{
		if (*this != s)
		{
			char* tmp = new char[_capacity + 1];
			strcpy(tmp, s._str);
			delete[]_str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}
		return *this;
	}
	string::string(const string& s)
	{
		_str = new char[s._capacity + 1];
		strcpy(_str, s._str);
		_size = s._size;
		_capacity = s._capacity;
	}
	string::~string()
	{
		delete[]_str;
		_str = nullptr;
		_size = _capacity = 0;
	}

	string::iterator string::begin()
	{
		return _str;
	}
	string::const_iterator string::begin()const
	{
		return _str;
	}

	string::iterator string::end()
	{
		return _str + _size;
	}
	string::const_iterator string::end()const
	{
		return _str + _size;
	}

	size_t string::size()const
	{
		return _size;
	}

	char& string::operator[](size_t pos)
	{
		assert(pos < _size);
		return _str[pos];
	}
	const char& string::operator[](size_t pos)const
	{
		assert(pos < _size);
		return _str[pos];
	}

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

	void string::push_back(char ch)
	{
		if (_size == _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newcapacity);
		}
		_str[_size] = ch;
		_str[_size + 1] = '\0';
		_size++;
	}

	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (len + _size > _capacity)
		{
			reserve(len + _size);
		}
		strcpy(_str+_size, str);
		_size += len;
	}

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

	void string::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 string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);

		size_t len = strlen(str);
		if (len + _size > _capacity)
		{
			reserve(len + _size);
		}

		size_t end = _size + len;
		while (end > pos + len - 1)
		{
			_str[end] = _str[end - len];
			--end;
		}
		memcpy(_str + pos, str, len);
		_size += len;
	}

	void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);

		if (len >= _size - len)
		{
			_str[pos] = '\0';
			_size = 0;
		}
		else
		{
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		for (size_t i = pos; i < _size; i++)
		{
			if (_str[i] == ch)
				return i;
		}
		return npos;
	}
	size_t string::find(const char* str, size_t pos)
	{
		char* p = strstr(_str + pos, str);
		return p - _str;
	}

	const char* string::c_str()const
	{
		return _str;
	}

	void string::swap(string& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}

	string string::substr(size_t pos, size_t len)
	{
		if (len > _size - pos)
		{
			string s(_str + pos);
			return s;
		}
		else
		{
			string sub;
			sub.reserve(len);
			for (size_t i = 0; i < len; i++)
			{
				sub += _str[pos + i];
			}
			return sub;
		}
	}

	bool string::operator<(const string& s) const
	{
		return strcmp(_str, s._str) < 0;
	}
	bool string::operator>(const string& s) const
	{
		return !(*this <= s);
	}
	bool string::operator<=(const string& s) const
	{
		return *this < s || *this == s;
	}
	bool string::operator>=(const string& s) const
	{
		return !(*this < s);
	}
	bool string::operator==(const string& s) const
	{
		return strcmp(_str, s._str) == 0;
	}
	bool string::operator!=(const string& s) const
	{
		return !(*this == s);
	}

	void string::clear()
	{
		_size = 0;
		_str[0] = '\0';
	}

	istream& operator>> (istream& is, string& str)
	{
		str.clear();
		char ch = is.get();
		//遇到' '或'\n',流插入停止
		while (ch != ' ' && ch != '\n')
		{
			str += ch;
			ch = is.get();
		}
		return is;
	}
	ostream& operator<< (ostream& os, const string& str)
	{
		for (int i = 0; i < str.size(); i++)
		{
			os << str[i];
		}
		return os;
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络之网络层知识总结

网络层功能概述 主要任务 主要任务是把分组从源端传到目的端&#xff0c;为分组交换网上的不同主机提供通信服务。网络层传输单位是数据报。 分组和数据报的关系&#xff1a;把数据报进行切割之后&#xff0c;就是分组。 主要功能&#xff1a; 路由选择与分组转发 路由器…

openh264 编码器源码分析:WelsCodeOneSlice 函数

介绍 功能&#xff1a;openh264 编码每个 slice 的核心函数原型&#xff1a; int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, SSlice* pCurSlice, const int32_t kiNalType)参数&#xff1a; pEncCtx&#xff1a;指向编码上下文结构体sWelsEncCtx的指针&#xff0c;包含编…

gpt、llama大模型模型结构细节探索

参考&#xff1a; https://github.com/naklecha/llama3-from-scratch&#xff08;一定要看看&#xff09; https://github.com/karpathy/build-nanogpt/blob/master/play.ipynb 视频&#xff1a; https://www.youtube.com/watch?vl8pRSuU81PU https://tiktokenizer.vercel…

Vitis HLS 学习笔记--移除内存分配malloc

目录 1. 简介 2. 示例解析 2.1 源码解释 2.2 malloc 分析 2.3 替代方案分析 3. 总结 1. 简介 Vitis HLS 也不支持动态创建或删除 C/C 对象&#xff08;用于综合&#xff09;。 本文探究如何在C/C代码中避免使用显式的malloc函数来分配内存。在硬件设计和FPGA开发中&…

b站视频下载到电脑本地mp4格式,b站视频下载到手机相册

有时候我们想把网站上的视频下载到电脑或手机&#xff0c;其实有多种方法可供选择。本文将详细介绍几种常见的下载方式&#xff0c;并探讨它们的优缺点&#xff0c;帮助读者根据自己的需求选择最适合的下载方法。 方法一&#xff1a; 1、使用 "小白兔视频格式在线转换网站…

LogicFlow 学习笔记——3. LogicFlow 基础 节点 Node

节点 Node LogicFlow 内置了一些基础节点&#xff0c;开发者在实际应用场景中&#xff0c;可以基于这些基础节点&#xff0c;定义符合自己业务逻辑的节点。 认识基础节点 LogicFlow是基于svg做的流程图编辑框架&#xff0c;所以我们的节点和连线都是svg基本形状&#xff0c;…

中电联系列四:rocket手把手教你理解中电联协议!

分享《慧哥的充电桩开源SAAS系统&#xff0c;支持汽车充电桩、二轮自行车充电桩。》 电动汽车充换电服务信息交换 第4部分&#xff1a;数据传输与安全 Interactive of charging and battery swap service information for electric vehicle Part 4:Data transmission and secu…

nosql数据库的特点

NoSQL简介 NoSQL是一种不同于关系数据库的数据库管理系统设计方式,是对非关系型数据库的统称,它所采用的数据模型并非传统关系数据库的关系模型,而是类似键/值、列族、文档等非关系模型。NoSQL数据库没有固定的表结构,通常也不存在连接操作,也没有严格遵守ACID约束。因此…

Redis高性能原理:Redis为什么这么快?

目录 前言&#xff1a; 一、Redis知识系统观 二、Redis为什么这么快&#xff1f; 三、Redis 唯快不破的原理总结 四、Redis6.x的多线程 前言&#xff1a; Redis 为了高性能&#xff0c;从各方各面都进行了优化。学习一门技术&#xff0c;通常只接触了零散的技术点&#xff…

用ChatGPT 4o画漂亮的燃尽图代码

把代码给ChatGPT&#xff0c;然后他就会帮我生成出来了。 而且图是动态的&#xff0c;可以调整颜色文字之类的内容 # Given data for Sprint 5 Progress data_sprint_5 {User Story: [BEAN-40, BEAN-42, BEAN-41, BEAN-22, BEAN-33, BEAN-44, BEAN-10, BEAN-26, BEAN-37, BEA…

【学术小白成长之路】03三方演化博弈(基于复制动态方程)均衡点与稳定性分析

从本专栏开始&#xff0c;笔者正式研究演化博弈分析&#xff0c;其中涉及到双方演化博弈分析&#xff0c;三方演化博弈分析&#xff0c;复杂网络博弈分析等等。 先阅读了大量相关的博弈分析的文献&#xff0c;总结了现有的研究常用的研究流程&#xff0c;针对每个流程进行拆解。…

Sqlite3入门和c/c++下使用

1. SQLite3基本介绍 1.1 数据库的数据类型 1.2 基本语法 1. 创建数据表格 create table 表名(字段名 数据类型&#xff0c; 字段名 数据类型)&#xff1b; create table student(id int, name varchar(256), address text, QQ char(32)); 2. 插入数据 insert into 表名 valu…

手机流畅运行470亿参数大模型,上交大发布PowerInfer-2推理框架,性能提升29倍

苹果一出手&#xff0c;在手机等移动设备上部署大模型迅速成为行业焦点。 目前&#xff0c;移动设备上运行的模型相对较小&#xff08;苹果的是3B&#xff0c;谷歌的是2B&#xff09;&#xff0c;并且消耗大量内存&#xff0c;这在很大程度上限制了其应用场景。 即使是苹果&…

运营商二要素核验-手机号机主姓名核验接口-运营商二要素核验接口

通过电信运营商验证手机号码与姓名是否一致。广泛用于实名注册、风控审核等场景&#xff0c;如电商、游戏、直播、金融等需要用户实名认证的场景。支持携号转网核验。 更新周期&#xff1a;联通T1 电信T3 移动T3~5 均为工作日 接口地址&#xff1a; https://www.wapi.cn/api_de…

RabbitMQ系列-rabbitmq无法重新加入集群,启动失败的问题

当前存在3个节点&#xff1a;rabbitmq5672、rabbitmq5673、rabbitmq5674 当rabbitmq5673节点掉线之后&#xff0c;重启失败 重启的时候5672节点报错如下&#xff1a; 解决方案 在集群中取消失败节点 rabbitmqctl forget_cluster_node rabbitrabbitmq5673删除失败节点5673的…

木头姐预测:2029年特斯拉股价将达2600美元,市值8.2万亿美元

ARK预计特斯拉将在未来两年内推出robotaxi服务&#xff0c;并估计到2029年特斯拉近90%的市值和盈利将归功于robotaxi业务。此外研究表明&#xff0c;FSD模式下的特斯拉比人类驾驶的特斯拉安全约5倍&#xff0c;比道路上的普通汽车安全约16倍。 北京时间12日晚&#xff0c;木头姐…

【课程总结】Day9(上):深度学习基本流程

前言 在上一篇课程《【课程总结】Day7&#xff1a;深度学习概述》中&#xff0c;我们了解到&#xff1a; 模型训练过程→本质上是固定w和b参数的过程&#xff1b;让模型更好→本质上就是让模型的损失值loss变小&#xff1b;让loss变小→本质上就是求loss函数的最小值&#xf…

Java中ArrayList(顺序表)的自我实现(如果想知道Java中怎么自我实现ArrayList,那么只看这一篇就足够了!)

前言&#xff1a;在 Java 编程中&#xff0c;ArrayList 是一种非常常用的数据结构&#xff0c;它提供了动态数组的实现方式&#xff0c;可以方便地存储和操作数据。相比于传统的数组&#xff0c;ArrayList 具有更多的灵活性和便利性&#xff0c;可以根据需要动态地调整大小&…

构建 deno/fresh 的 docker 镜像

众所周知, 最近 docker 镜像的使用又出现了新的困难. 但是不怕, 窝们可以使用曲线救国的方法: 自己制作容器镜像 ! 下面以 deno/fresh 举栗, 部署一个简单的应用. 目录 1 创建 deno/fresh 项目2 构建 docker 镜像3 部署和测试4 总结与展望 1 创建 deno/fresh 项目 执行命令…

嵌套查询(一)-谓词IN、量词ANY、量词ALL

一、在多个表之间进行数据查询&#xff0c;除了可以使用连接查询之外&#xff0c;也可以使用嵌套查询&#xff0c;那么什么是嵌套查询呢&#xff1f;如何使用嵌套查询呢&#xff1f; 1、将一个SELECT-FROM查询&#xff0c;嵌套在另一个SELECT查询语句中&#xff0c;那么这个SE…