【C++课程学习】:string的模拟实现

🎁个人主页:我们的五年****

🔍系列专栏:C++课程学习****

🎉欢迎大家点赞👍评论📝收藏⭐文章

目录

一.string的主体框架:

二.string的分析:

🍔构造函数和析构函数:

🍔迭代器:

🍔赋值运算符重载:

🍔空间扩容:

🍔尾插:

🍔获取_str,_capacity,_size:

🍔[]重载,随机访问:

🍔在结尾追加字符串

🍔在指定位置插入和删除字符串:

🍔交换:

🍔获取子串和寻找元素和字符串:

🍔运算符重载:

🍔流插入和流提取重载:


通过对string的模拟实现,可以对string有更深的理解和认识,大概知道底层的逻辑,以后出现什么问题可以更好的解决。对学习以后的容器也有很大的帮助。

一.string的主体框架:

1.迭代器 2.运算符重载 3.

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<cstring>
#include<assert.h>
#include<algorithm>

using namespace std;

namespace bit {
	class string {
	public:
		//迭代器
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin();
		const_iterator begin()const;

		iterator end();
		const_iterator end()const;

		//构造函数
		string(size_t capacity = 4);
		string(const string& s);
		string(const char* str);
		string& operator=(const string& str);

		//析构函数
		~string();

		//异地扩容
		void reserve(size_t newcapacity);
		//尾插数据
		void push_back(char c);


		const char* c_str()const;

		size_t size()const;
		size_t capacity()const;

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

		void append(const char* str);

		string& operator+=(char ch);

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

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos = 0, size_t len = npos);

		void swap(string& s);

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

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


		//运算符重载
		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;

		//对sring进行清理
		void clear();
	private:
		const static size_t npos = -1;
		char* _str;
		//有效大小
		size_t _size;
		//空间的容量
		size_t _capacity;
	};

	//重载流插入和流提取
	istream& operator>> (istream& is, string& str);
	ostream& operator<< (ostream& os, const string& str);
}

二.string的分析:

🍔构造函数和析构函数:

构造函数常用的是三个,普通构造,拷贝构造,用const char*类型进行构造。

	//capacity表示要提前开的空间大小
	string::string(size_t capacity)
		:_str(new char[capacity + 1])
		, _capacity(capacity)
		, _size(0)
	{
		_str[0] = '\0';
	}

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

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

		strcpy(_str, str);
	}

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

🍔迭代器:

		//迭代器
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin();
		const_iterator begin()const;

		iterator end();
		const_iterator end()const;

🍔赋值运算符重载:

	string& string::operator=(const string& str)
	{
		if (str._capacity > _capacity)
			reserve(str._capacity);
		strcpy(_str, str._str);
		return *this;
	}

🍔空间扩容:

	void string::reserve(size_t newcapacity)
	{
		//先判断是否需要扩容
		//如果newcapacity小于等于,就不会扩,也不会缩容
		if (newcapacity <= _capacity)
			return;
		char* p = new char[newcapacity + 1];
		_capacity = newcapacity;
		strcpy(p, _str);
		delete[] _str;
		_str = p;
	}

🍔尾插:

	void string::push_back(char c)
	{
		if (_size == _capacity)
		{
			//不能直接乘以两倍,_capacity可能为0,乘二还是为0
			size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newcapacity);
		}
		_str[_size] = c;
		_size++;
	}

🍔获取_str,_capacity,_size:

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

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

	size_t string::capacity()const
	{
		return _capacity;
	}

🍔[]重载,随机访问:

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

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

🍔在结尾追加字符串

	void string::append(const char* s)
	{
		size_t length = strlen(s);
		if(_size + length > _capacity)
			reserve(_size + length);
		//
		strcat(_str, s);
		_size += length;
	}

🍔在指定位置插入和删除字符串:

	void string::insert(size_t pos, char ch)
	{
		assert(pos >= 0 && pos <= _size);
		if (_size == _capacity)
			reserve(_capacity * 2);
		size_t end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			end--;
		}
		_size++;
		_str[pos] = ch;
	}

	void string::insert(size_t pos, const char* str)
	{
		assert(pos >= 0 && pos <= _size);
		size_t length = strlen(str);
		if (length + _size > _capacity)
			reserve(length + _size);
		for (size_t i = _size - 1; i >= pos; i--)
			_str[i + length] = _str[i];
		_str[_size + length] = 0;
		for (size_t i = 0; i < length; i++)
			_str[i + pos] = str[i];
	}

	void string::erase(size_t pos, size_t len)
	{
		assert(pos >= 0 && pos < _size - 1);
		if (len>=_size-pos)
		{
			_str[pos] = '\0';
			_size = pos;
		}
		else
		{
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
	}

🍔交换:

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

🍔获取子串和寻找元素和字符串:

	string string::substr(size_t pos, size_t len)
	{
		assert(pos >= 0 && pos < _size);

		if (len > _size - pos)
		{
			bit::string substr(_str + pos);
			return substr;
		}
		else
		{
			bit::string substr(len);
			for (size_t i = pos; i < pos+len; i++)
				substr += _str[i];
			return substr;
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		for (size_t i = 0; i < pos; i++)
		{
			if (_str[i] == ch)
				return i;
		}
		return -1;
	}

	size_t string::find(const char* str, size_t pos)
	{
		char* p = strstr(_str + pos, str);
		return p - _str;
	}

🍔运算符重载:

	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 || (*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);
	}

	string& string::operator+=(char ch)
	{
		insert(_size, ch);
		return *this;
	}

	string& string::operator+=(const char* str)
	{
		insert(_size, str);
		return *this;
	}

🍔流插入和流提取重载:

	istream& operator>>(istream& is, string& s)
	{
		s.clear();
		char it = is.get();
		while (it != ' ' && it != '\n')
		{
			s += it;
			it = is.get();
		}
		return is;
	}

	ostream& operator<<(ostream& os, const string& s)
	{
		for (size_t i = 0; i < s.size(); i++)
			os << s[i];
		return os;
	}
相关推荐
Algorithm15763 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
shinelord明12 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
Monly2119 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
boligongzhu20 分钟前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
Eric.Lee202120 分钟前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
小俊俊的博客21 分钟前
海康RGBD相机使用C++和Opencv采集图像记录
c++·opencv·海康·rgbd相机
7yewh22 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
waicsdn_haha34 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
嵌入式科普35 分钟前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l
_WndProc36 分钟前
C++ 日志输出
开发语言·c++·算法