string的模拟实现(c++)

前言

        string是用来管理字符的容器,它在物理上是一个可以动态增长的字符数组,了解string类核心接口的实现对于我们更好的理解string类有很大的帮助,下面让我们一起来实现一下string类的核心接口吧!

目录

1.四个默认成员函数

2.迭代器

3.增删查改

4.容量相关

5.测试代码 

6.判断大小 ,输入和输出

7.完整代码


1.四个默认成员函数

string(const char* s = "")//默认拷贝函数
			: _str(new char[strlen(s) + 1])//开空间
			, _size(strlen(s))
			, _capacity(strlen(s))
		{
			strcpy(_str, s);//完成字符的拷贝
		}
        string(const string& s)//拷贝构造函数
			:_str(new char[strlen(s._str) + 1])//开空间
			, _size(s._size)
			, _capacity(s._capacity)
		{
			strcpy(_str, s._str);//拷贝字符
		}
        void swap( string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity,s._capacity);
		}
		~string()//析构函数
		{
			delete[]_str;
			_str = nullptr;
			_size = _capacity = 0;
		}
        string &operator=(const string& s)
		{
			if (this != &s)//防止自己给自己赋值
			{
				//申请新空间
				char* newstr = new char[strlen(s._str) + 1];
				strcpy(newstr, s._str);//拷贝数据
				delete[]_str;//释放旧空间
				_str = newstr;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}

        注意:拷贝构造函数和operator=有新的不同的写法,如下:

        要注意深浅拷贝的问题所以不能直接进行赋值。

        string(const string& s)//拷贝构造函数
			:_str(nullptr)
			, _size(0)
			, _capacity(0)
		{
			string tmp(s._str);
			//this->swap(tmp);//调用自己实现的swap
			swap(tmp);//调用自己实现的swap
		}
		void swap( string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity,s._capacity);
		}
        string& operator=(string s)
		{
			if (*this != s)//避免对象自己给自己赋值
			{
				::swap(*this,s);//调用全局的swap函数
				return *this;
			}
		}

         现代写法不同于传统的写法,这种写法是借助别人构造的对象实现函数的功能,不需要自己来写,只需要“换来”用就行了。

2.迭代器

        string的迭代器是原生的指针。

        typedef  char* iterator;
		typedef const char* const_iterator;
        //迭代器
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		//const 迭代器
		const_iterator begin()const
		{
			return _str;
		}
		const_iterator end()const
		{
			return _str + _size;
		}

3.增删查改

        //尾插尾删一个字符
		void push_back(const char value)
		{
			if (_size == _capacity)//扩容
			{
				size_t len = _capacity == 0  ?  2 : 2 * _capacity;
				reserve(len);
			}
			_str[_size] = value;//插入数据
			++_size;//更新size
			_str[_size] = '\0';
			//insert(_size,value);
		}
		void pop_back()
		{
			assert(_size);//字符数组中有数据
			--_size;
			//erase(_size-1);
		}
		void append(const char* str)//尾插一个字符串
		{
			size_t len = strlen(str)+_size;
			if (_size + len > _capacity)//扩容
			{
				//len = (_capacity == 0 ? 2 : len);//考虑string的容量为空的情况
				reserve(len);
			}
			strcpy(_str + _size, str);//插入字符串
			_size =  len;//更新字符串的长度
		}
		//任意位置的插入和删除
		string& insert(size_t pox,char ch)//插入一个字符
		{
			assert(pox < _size);//确保位置有效性-尾插也可以
			int i = _size;
			if (_size == _capacity)//扩容
			{
				size_t len = (_capacity == 0 ? 2 : 2 * _capacity);
				reserve(len);
			}
			while (i >= (int)pox)//移动数据
			{
				_str[i + 1] = _str[i];
				--i;
			}
			//插入字符
			_str[pox] = ch;
			++_size;//更新size
			return *this;
		}
		string& insert(size_t pox,const char* s)//插入字符串
		{
			assert(pox < _size);//确保位置有效性
			size_t len = strlen(s);
			
			if (len + _size >  _capacity)//string满了扩容
				reserve(len + _size);
			int end = _size;
			while (end >= (int)pox)//pox与end比较会转换为size_t 为无符号整形,
			{
									//所以比较的时候必须将pox转换为int,不然头插就停不下来了
				_str[end+len] = _str[end];//向后挪动数据
				--end;
			}
			strncpy(_str + pox, s, len);//插入字符串
			_size += len;//更新size
			return *this;
		}
		string& erase(size_t pox,size_t len = npos)//删除pox位置的字符
		{
			assert(pox < _size);
			if (len > strlen(_str + pox))
			{
				_str[pox] = '\0';
				_size = pox;
			}           
			else
			{
				while (pox < (int)_size)//移动数据
				{
					_str[pox] = _str[pox + len];
					++pox;
				}
				_size -= len;//更新size
			}
			return *this;
		}
        string& operator+=(const string& s)
		{
			append(s._str);
			return *this;
		}
		string& operator+=(const char* s)
		{
			append(s);
			return *this;
		}
		string& operator+=(const char s)
		{
			push_back(s);
			return *this;
		}

4.容量相关

	//
		size_t size()const//加上const防止_size被改变,同时const对象和非const对象都可以调用
		{
			return _size;
		}
		size_t capacity()const//加上const防止_capacity被改变,同时const对象和非const对象都可以调用
		{
			return _capacity;
		}
		void reserve(size_t n)//改变容量的函数
		{
			if (n > _capacity)//增容
			{
				char* newstr = new char[n + 1];//开新空间
				if (_str)//确保str不为空
				{
					strcpy(newstr,_str);//拷贝数据
					delete[] _str;//释放旧空间
				}
				_str = newstr;//指向新空间
				_capacity = n;//给新的容量
			}
		}

		void resize(size_t n, const char ch = '\0')//改变size
		{
			if (n <(int) _size)//不需要插入字符
			{
				_str[n] = '\0';
				_size = n;
			}
			else
			{
				if (n = _capacity)//增容
					reserve(n);
				while(_size < n)//拷贝字符
				{
					_str[_size] = ch;
					++_size;
				}
				_str[_size] = '\0';//补'\0'
			}
		}

5.测试代码 

        

#include"string.h"
void testString1()
{
	qyy::string s1;
	qyy::string s2("hhhh");
	//s2 = s1;
	qyy::string s3(s2);
	cout << s2;
}
void testString2()
{
	qyy::string s1;
	s1.push_back('h');
	s1.push_back('e');
	s1.push_back('l');
	s1.push_back('l');
	s1.push_back('0');
	//s1.pop_back();
	s1.append("hahhaakkkkkkkkkkkkkkk");
	cout << s1;
}
void testString3()
{
	qyy::string s1;
	s1 += "hello ";
	s1 += "w";
	cout << s1;
	/*cout << s1.find('s')<<endl;
	cout << s1.find('l')<<endl;*/
	s1.insert(1, 'k');
	s1.insert(5, "qqqqqq");
	cout << s1 << endl;
	s1.resize(2);
	cout << s1 << endl;
	s1.resize(20);
	cout << s1 << endl;

}
void testString4()
{
	qyy::string s1;
	cout << s1 << endl;
	s1 += "hhhh1234567xxxxxxxxx";
	s1.erase(3, 5);
	cout << s1 << endl;
	cin >> s1;
	cout << s1 << endl;
	s1.insert(0, "99999");
	cout << s1 << endl;
}

6.判断大小 ,输入和输出

bool operator==(const string& s)
		{
			if (strcmp(_str, s._str) == 0)
				return true;
			else
				return false;
		}
		bool operator!=(const string& s)
		{
			return !(*this == s);
		}
		bool operator<(const string& s)
		{
			if (strcmp(_str, s._str) < 0)
				return true;
			else
				return false;
		}
		bool operator<=(const string& s)
		{
			return (*this < s || *this == s);
		}
		bool operator>(const string& s)
		{
			return !(*this<=s);
		}
		bool operator>=(const string& s)
		{
			return !(*this < s);
		}
		void getline()
		{
			while (1)
			{
				char ch;
				cin.get(ch);
				if (ch == '\0')
				{
					break;//结束输入
				}
				*this += ch;
			}
		}
        ostream& operator<<(ostream& out,const string&s)
	{
		size_t i = 0;
		for (i = 0; i < s.size(); ++i)
		{
			cout << s[i];
		}
		cout << endl;
		return out;
	}
	istream& operator>>(istream& in,string &s)
	{
		
		while (1)
		{
			char ch;
			//ch = getchar();
			in.get(ch);
			if (ch == ' ' || ch == '\n')
			{
				break;
			}
			s += ch;
		}
		return in;
	}

7.完整代码

#include<iostream>
#include<assert.h>
#include<string.h>
using namespace std;
namespace qyy
{
	size_t static npos = -1;
	class string
	{
	public:
		typedef  char* iterator;
		typedef const char* const_iterator;
		string(const char* s = "")//默认拷贝函数
			: _str(new char[strlen(s) + 1])//开空间
			, _size(strlen(s))
			, _capacity(strlen(s))
		{
			strcpy(_str, s);//完成字符的拷贝
		}

		//string(const string& s)//拷贝构造函数
		//	:_str(new char[strlen(s._str) + 1])//开空间
		//	, _size(s._size)
		//	, _capacity(s._capacity)
		//{
		//	strcpy(_str, s._str);//拷贝字符
		//}
		//现代写法
		string(const string& s)//拷贝构造函数
			:_str(nullptr)
			, _size(0)
			, _capacity(0)
		{
			string tmp(s._str);
			//this->swap(tmp);//调用自己实现的swap
			swap(tmp);//调用自己实现的swap
		}
		void swap( string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity,s._capacity);
		}
		~string()//析构函数
		{
			delete[]_str;
			_str = nullptr;
			_size = _capacity = 0;
		}
		//string &operator=(const string& s)
		//{
		//	if (this != &s)//防止自己给自己赋值
		//	{
		//		//申请新空间
		//		char* newstr = new char[strlen(s._str) + 1];
		//		strcpy(newstr, s._str);//拷贝数据
		//		delete[]_str;//释放旧空间
		//		_str = newstr;
		//		_size = s._size;
		//		_capacity = s._capacity;
		//	}
		//	return *this;
		//}
		string& operator=(string s)
		{
			if (*this != s)//避免对象自己给自己赋值
			{
				::swap(*this,s);//调用全局的swap函数
				return *this;
			}
		}
		//迭代器
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		//const 迭代器
		const_iterator begin()const
		{
			return _str;
		}
		const_iterator end()const
		{
			return _str + _size;
		}

		//
		size_t size()const//加上const防止_size被改变,同时const对象和非const对象都可以调用
		{
			return _size;
		}
		size_t capacity()const//加上const防止_capacity被改变,同时const对象和非const对象都可以调用
		{
			return _capacity;
		}
		void reserve(size_t n)//改变容量的函数
		{
			if (n > _capacity)//增容
			{
				char* newstr = new char[n + 1];//开新空间
				if (_str)//确保str不为空
				{
					strcpy(newstr,_str);//拷贝数据
					delete[] _str;//释放旧空间
				}
				_str = newstr;//指向新空间
				_capacity = n;//给新的容量
			}
		}

		void resize(size_t n, const char ch = '\0')//改变size
		{
			if (n <(int) _size)//不需要插入字符
			{
				_str[n] = '\0';
				_size = n;
			}
			else
			{
				if (n = _capacity)//增容
					reserve(n);
				while(_size < n)//拷贝字符
				{
					_str[_size] = ch;
					++_size;
				}
				_str[_size] = '\0';//补'\0'
			}
		}
		//尾插尾删一个字符
		void push_back(const char value)
		{
			if (_size == _capacity)//扩容
			{
				size_t len = _capacity == 0  ?  2 : 2 * _capacity;
				reserve(len);
			}
			_str[_size] = value;//插入数据
			++_size;//更新size
			_str[_size] = '\0';
			//insert(_size,value);
		}
		void pop_back()
		{
			assert(_size);//字符数组中有数据
			--_size;
			//erase(_size-1);
		}
		void append(const char* str)//尾插一个字符串
		{
			size_t len = strlen(str)+_size;
			if (_size + len > _capacity)//扩容
			{
				//len = (_capacity == 0 ? 2 : len);//考虑string的容量为空的情况
				reserve(len);
			}
			strcpy(_str + _size, str);//插入字符串
			_size =  len;//更新字符串的长度
		}
		//任意位置的插入和删除
		string& insert(size_t pox,char ch)//插入一个字符
		{
			assert(pox < _size);//确保位置有效性-尾插也可以
			int i = _size;
			if (_size == _capacity)//扩容
			{
				size_t len = (_capacity == 0 ? 2 : 2 * _capacity);
				reserve(len);
			}
			while (i >= (int)pox)//移动数据
			{
				_str[i + 1] = _str[i];
				--i;
			}
			//插入字符
			_str[pox] = ch;
			++_size;//更新size
			return *this;
		}
		string& insert(size_t pox,const char* s)//插入字符串
		{
			assert(pox < _size);//确保位置有效性
			size_t len = strlen(s);
			
			if (len + _size >  _capacity)//string满了扩容
				reserve(len + _size);
			int end = _size;
			while (end >= (int)pox)//pox与end比较会转换为size_t 为无符号整形,
			{
									//所以比较的时候必须将pox转换为int,不然头插就停不下来了
				_str[end+len] = _str[end];//向后挪动数据
				--end;
			}
			strncpy(_str + pox, s, len);//插入字符串
			_size += len;//更新size
			return *this;
		}
		string& erase(size_t pox,size_t len = npos)//删除pox位置的字符
		{
			assert(pox < _size);
			if (len > strlen(_str + pox))
			{
				_str[pox] = '\0';
				_size = pox;
			}           
			else
			{
				while (pox < (int)_size)//移动数据
				{
					_str[pox] = _str[pox + len];
					++pox;
				}
				_size -= len;//更新size
			}
			return *this;
		}
		size_t find(char ch, size_t pos = 0)
		{
			assert(pos < _size);
			char * p=strstr(_str + pos, &ch);
			return p - (_str );
		}
		size_t find(const char *str, size_t pos = 0)
		{
			assert(pos < _size);
			char* p=strstr(_str + pos, str);
			if (p == nullptr)
			{
				return npos;
			}
			else
			{
				return p - (_str + pos);
			}
		}
		string& operator+=(const string& s)
		{
			append(s._str);
			return *this;
		}
		string& operator+=(const char* s)
		{
			append(s);
			return *this;
		}
		string& operator+=(const char s)
		{
			push_back(s);
			return *this;
		}
		//c—str
		char* c_str()
		{
			return _str;
		}
		const char* c_str()const
		{
			return _str;
		}
		//
		char& operator[](size_t i)
		{
			assert(i < _size); 
			return _str[i];
		}
		const char& operator[](size_t i)const
		{
			assert(i < _size);
			return _str[i];
		}
		bool operator==(const string& s)
		{
			if (strcmp(_str, s._str) == 0)
				return true;
			else
				return false;
		}
		bool operator!=(const string& s)
		{
			return !(*this == s);
		}
		bool operator<(const string& s)
		{
			if (strcmp(_str, s._str) < 0)
				return true;
			else
				return false;
		}
		bool operator<=(const string& s)
		{
			return (*this < s || *this == s);
		}
		bool operator>(const string& s)
		{
			return !(*this<=s);
		}
		bool operator>=(const string& s)
		{
			return !(*this < s);
		}
		void getline()
		{
			while (1)
			{
				char ch;
				cin.get(ch);
				if (ch == '\0')
				{
					break;//结束输入
				}
				*this += ch;
			}
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	};

	ostream& operator<<(ostream& out,const string&s)
	{
		size_t i = 0;
		for (i = 0; i < s.size(); ++i)
		{
			cout << s[i];
		}
		cout << endl;
		return out;
	}
	istream& operator>>(istream& in,string &s)
	{
		
		while (1)
		{
			char ch;
			//ch = getchar();
			in.get(ch);
			if (ch == ' ' || ch == '\n')
			{
				break;
			}
			s += ch;
		}
		return in;
	}
	
}      

        string就是一个可以动态增长的字符数组,由于比较简单这里就不做过多的讲解了。只要注意深浅拷贝的问题就行。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值