C++STL中String简单模拟实现

前言

大家好,今天这篇文章介绍的主要是C++STL中String的简单模拟实现

构建架构

这里我们可以从cplusplus.com - The C++ Resources Network 中找到String,基于给出的函数来构建框架

1.私有变量

        size_t _size;
		size_t _capacity;
		char* _str;

		const static size_t npos = -1;

2.四个默认成员函数

        //构造
		string(const char* str = "");
		//析构
		~string();
		//拷贝构造
		string(const string& str);
		//赋值重载
		string operator = (const string& str);

3.迭代器

        //迭代器
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin();
		iterator end();
		const_iterator begin() const;
		const_iterator end() const;

4.访问

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

5.增、删、查

        //增
        string operator+=(char ch);        

		void push_back(char& ch);
		string& append(const char* str);
		string& append(const string& s);
		void insert(size_t pos, const char* str);
		void insert(size_t pos, string& s);
        //删
		void erase(size_t pos, size_t len);
        //查
		size_t find(char ch, size_t pos = 0) const;
		size_t find(const char* str, size_t pos = 0) const;
		size_t find(const string& s, size_t pos = 0) const;

6.输入输出重载

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

7。空间相关

		void reserve(size_t n = 0);
        size_t lenth() const;
		size_t capacity() const;

以上就是主要的函数了

函数实现

运行环境VS2022

我这里采用的声明定义分离的写法,分为2个文件,String.h,String.cpp

String.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include 
#include 
#include 
#include 

using namespace std;

//先把框架搭出来


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

		//检查空间
		void cheak_capacity();
		void reserve(size_t n = 0);
		

		//迭代器
		iterator begin();
		iterator end();

		const_iterator begin() const ;
		const_iterator end() const;

		//构造
		string(const char* str = "") ;
		
		//析构
		~string();
		//拷贝构造
		string(const string& str);

		//赋值重载
		string operator = (const string & str);

		
		string operator+=(char ch);

		char& operator[](size_t pos);

		


		//其他的函数
		const char* c_str() const
		{
			return _str;
		}
		/*char* c_str() 
		{
			return _str;
		}*/

		size_t lenth()
		{
			return _size;
		}

		size_t capacity()
		{
			return _capacity;
		}

		void clear()
		{
			_size = 0;
			_str[_size] = '\0';//加上这一步,是因为不写的话有特殊情况
		}

		string& append(const char& ch);
		string& append(const char* str);
		string& append(const string& s);

		void push_back(const char& ch);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos, size_t len);
		size_t find(const string& str, size_t pos = 0) const;
		size_t find(const char* s, size_t pos = 0) const;

		string substr(size_t pos = 0, size_t len = npos);
		void swap(string& str);


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

		const static size_t npos = -1;
	};
	

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

}

String.cpp

#include "String.h"

namespace lzp
{
	//检查空间
	void string::cheak_capacity()
	{
		//如果_size >= _capecity 的话,就要扩容
		//其实等于的时候就要扩容了
		if (_size >= _capacity)
		{
			_capacity = _capacity == 0 ? 4 : _capacity * 2;
			char* tem = _str;
			_str = new char[_capacity + 1];
			strcpy(_str, tem);
			delete[] tem;    
		}
		
	}

	//提前开好空间
	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			
			char* tem = new char[n + 1]; //应该要给\0留好空间
			strcpy(tem, _str);
			delete[] _str;
			_str = tem;

			_capacity = n;
		}
	}


	//迭代器
	string::iterator string::begin()
	{
		return _str;
	}

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

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

	//构造
	string::string(const char* str)
		:_size(strlen(str))
		, _capacity(_size)
		, _str(nullptr)

	{
		assert(str); 
		_str = new char[_capacity + 1];
		strcpy(_str, str);
	}

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

	//拷贝构造
	string::string(const string& str)
	{
		//肯定是深拷贝
		//先new一个和str一样大小的空间,再把数据拷贝过去

		_str = new char[str._capacity + 1];
		_size = str._size;
		_capacity = str._capacity;

		strcpy(_str, str._str);
	}


	//赋值重载
	string string::operator = (const string& str)
	{
		//赋值是指两个以及存在的对象进行赋值

		char* tem = new char[str._capacity + 1];
		delete[] _str;
		_str = tem;
		_size = str._size;
		_capacity = str._capacity;

		strcpy(_str, str._str);

		return *this;
	}


	//重载
	string string::operator+=(char ch)
	{
		//先检查空间大小,不够扩容
		//然后在后面插入ch

		cheak_capacity();

		_str[_size] = ch;
		_str[_size + 1] = '\0'; //这个置0很关键
		_size++;

		return *this;
	}


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


	//追加
	string& string::append(const char& ch)
	{
		*this += ch;
		_size++;
		return *this;
	}
	string& string::append(const char* str)
	{
		int n = _size + strlen(str);
		if (n > _capacity)
		{
			reserve(n);
		}
		strcat(_str, str);
		
		//int cnt = n - _size; //strlen(str)
		//for (int i = 0; i < cnt; i++)
		//{
		//	_str[_size + i] = str[i];
		//}
		//_str[_size + cnt] = '\0';

		_size = n;
		return *this;
	}
	string& string::append(const string& s)
	{
		append(s._str);
		return *this;
	}

	void string::push_back(const char& ch)
	{
		*this += ch;
		_size++;
	}

	void string::insert(size_t pos, char ch)
	{
		assert(pos >= 0);

		cheak_capacity();

		//挪动,插入数据
		int i = 0;
		for (i = _size - 1; i > pos; i--)
		{
			_str[i + 1] = _str[i];
		}
		_str[i + 1] = _str[i];

		_str[pos] = ch;
		_size++;
		_str[_size] = '\0';
	}

	void string::insert(size_t pos, const char* str)
	{
		assert(pos >= 0);

		size_t len = strlen(str);
		reserve(len + _size);

		//还是挪动,然后插入
		int i = 0;
		for (int i = _size - 1; i > pos; i--)
		{
			_str[i + len] = _str[i];
		}
		_str[i + len] = _str[i];

		int j = pos;
		for (i = 0; i < len; i++)
		{
			_str[j++] = str[i];
		}

		_size += len;
		_str[_size] = '\0';
	}

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

		//直接往前覆盖
		int i = pos;
		int count = _size - len;
		while (count--)
		{
			_str[i] = _str[i + len];
			i++;
		}
		

		_size -= len;
		_str[_size] = '\0';
	}

	size_t string::find(const string& str, size_t pos) const
	{
		char* ptr = &_str[pos];
		if (char* p = strstr(ptr, str._str))
		{
			return p - &_str[0];
		}

		return npos;
	}
	size_t string::find(const char* s, size_t pos) const
	{
		char* ptr = &_str[pos];
		if (char* p = strstr(ptr, s))
		{
			return p - &_str[0];
		}

		return npos;
	}
	
	string string::substr(size_t pos, size_t len)
	{
		
		char* p = &_str[pos];
		string s;
		
		size_t cnt = len;
		if (cnt != npos)
		{
			while (cnt--)
			{
				s += *p;
				p++;
			}
		}
		else
		{
			s.reserve(_size - pos);//这个s没有能用的空间,得提前开好
			strcpy(s._str, p);
		}
		

		return s;
	}

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



	//标准输入输出
	istream& operator>> (istream& in, string& str)
	{
		str.clear();
		char ch = in.get();
		
		while (ch != ' ' && ch != '\n')
		{
			str += ch;
			ch = in.get();
		}

		return in;
	}
	ostream& operator<< (ostream& out, const string& str)
	{
		out << str.c_str();
		return out;
	}


}

虽然可以简单使用,但是仍存在大量的漏洞,下面我会一一修正

你可能感兴趣的:(C++,c++,开发语言)