STL_string模拟实现

string介绍:

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
  4. 不能操作多字节或者变长字符的序列

代码:

代码实现:

namespace ZYY
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		string(const char* x = ""):_str(new char[strlen(x)+1])
		{
			strcpy(_str,x);
			_size = strlen(_str);
			_capacity = _size;
		}

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

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

		//在pos位置插入一个ch字符
		void insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if(_size == _capacity)
			{
				if(_capacity == 0)
				{
					reserve(8);
				}
				else
				{
					reserve(_capacity * 2);
				}
			}
			size_t end = _size + 1; //end指向的是\0
			while (end >= pos + 1)
			{
				_str[end] = _str[end - 1];
				--end;
			}
			_str[pos] = ch;
			_size++;
		}

		//在pos位置出插入一个str字符串
		void 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 (pos + len <= end)
			{
				_str[end] = _str[end - len];
				--end;
			}
			while (*str)
			{
				_str[pos] = *str;
				++pos;
				++str;
				//_str[pos++] = *str++;
			}
			_size += len;
		}

		//查找ch第一次出现在string串中的下标
		size_t find(const char ch)
		{
			for(size_t i = 0 ; i < _size ;i++)
			{
				if(_str[i] == ch)
				{
					return i;
				}
			}
			return string::_npos;
		}

		//查找str第一次出现在string串中的下标
		size_t find(const char* str)
		{
			const char* pos = strstr(_str,str);//strstr函数-从_str中获取str串
			if(pos == nullptr)
			{
				return string::_npos;
			}
			else
			{
				return pos-_str;
			}
		}

		//扩容
		void reserve(size_t n)
		{
			if(n > _capacity) //如果reserve的大小 小于_capacity就不做任何处理
			{
				char* tmp = new char[n+1]; 
				strcpy(tmp,_str);
				delete []_str;
				_str = tmp;
				_capacity = n;
			}
		}

		//在string串尾部插入一个字符
		void push_back(const char ch)
		{
			if (_size == _capacity)
			{
				if (_capacity == 0)
				{
					reserve(8);
				}
				else
				{
					reserve(_capacity * 2);
				}
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}

		//清空string串
		void clear()
		{
			_size = 0;
			_str[_size] = '\0';
		}

		//在string串尾部追加一个字符串,append函数用的比较少,一般都是用加号运算符重载
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			strcpy(_str + _size, str);
			_size += len;
		}

		//在string串尾部追加一个字符
		void append(size_t n, char c)
		 {
			 for (size_t i = 0; i < n; ++i)
			 push_back(c);
		 }

		//在string串后面追加一个ch字符
		const string& operator+=(char ch)//复用push_back
		{
			push_back(ch);
			return *this;
		}

		//在string串后面追加一个str串
		const string& operator+=(const char* str)//复用append
		{
			append(str);
			return *this;
		}

		

		//在string串后面追加一个string串
		const string& operator+=(const string& s)//复用append
		{
			append(s._str);
			return *this;
		}

		//比较两个string串的大小
		bool operator>(const string& s)const
		{
			char* str1 = _str;
			char* str2 = s._str;
			while (*str1 && *str2)
			{
				if (*str1 > *str2)
				{
					return true;
				}
				else if (*str1 < *str2)
				{
					return false;
				}
				else
				{
					++str1;
			    	++str2;
				}
			}
			if (str1)
			{
				return true;
			}
			else return false;
		}


		bool operator==(const string& s)const
		{
			const char* str1 = _str;
			const char* str2 = s._str;
			while (*str1 && *str2)
			{
				if (*str1 == *str2)
				{
					++str1;
					++str2;
				}
				else
				{
					return false;
				}
			}
			if (str1 == nullptr && str2 == nullptr)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		bool operator>=(const string& s)const
		{
			return operator>(s) || operator==(s);
		}

		friend ostream& operator<<(ostream &_cout,const string& s);
		friend istream& operator>>(istream &_cin,string& s);

		///
		const_iterator begin() const
		{
			return _str;
		}

		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

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

		size_t size()const
		{
			return _size;
		}
		
		size_t capacity()
		{
			return _capacity;
		}

		const char* c_str()//c_str函数返回的值是const类型的
		{
			return _str;
		}

		char& operator[](size_t pos)//返回的是引用,所以可以通过[]对string串进行修改
		{
			assert(pos < _size);
			return _str[pos];
		}

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

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

		

		
	private:
		char* _str;
		size_t _size; //有效元素的个数,不包含\0
		size_t _capacity;
		static size_t _npos;
	};
	size_t string:: _npos = -1;
}

ostream& ZYY::operator<<(ostream &_cout,const ZYY::string& s)
{
	cout<<s._str;
	return _cout;
}

istream& ZYY::operator>>(istream &_cin,string& s)
{
	char ch = _cin.get();
	while(ch != ' ' && ch != '\n')
	{
		s += ch;
		ch = _cin.get();
	}
	return _cin;
}

代码测试:

int main()
{
	cout<<"打印s1:"<<endl;
	ZYY::string s1 = "nihao";
	cout<<s1<<endl;

	cout<<"打印s2:"<<endl;
	ZYY::string s2 = "pengyou";
	cout<<s2<<endl;

	cout<<"比较s1与s2的大小:"<<endl;
	if(s1 > s2)
	{
		cout<<"s1大于s2"<<endl;
	}
	else
	{
		cout<<"s1不大于s2"<<endl;
	}

	cout<<"将s1的值赋给s2:"<<endl;
	s2 = s1;
	cout<<s2<<endl;

	cout<<"将s1末尾追加一个字符:"<<endl;
	s1 += 'a';
	cout<<s1<<endl;

	cout<<"将s1末尾追加一个字符串:"<<endl;
	s1 += " hao";
	cout<<s1<<endl;

	cout<<"将s1末尾追加一个s2:"<<endl;
	s1 += s2;
	cout<<s1<<endl;

	cout<<"从s1中提取字符串:"<<endl;
	const char* s = s1.c_str();
	cout<<s<<endl;

	cout<<"给s1的4位置插入y:"<<endl;
	s1.insert(4,'y');
	cout<<s1<<endl;

	cout<<"给s1的末尾位置插入p:"<<endl;
	s1.push_back('p');
	cout<<s1<<endl;

	cout<<"清空s2:"<<endl;
	s2.clear();
	cout<<s2.size()<<endl;
	cout<<s2<<endl;

	cout<<"输入s3:"<<endl;
	ZYY::string s3;
	cin>>s3;
	cout<<s3<<endl;
}

测试结果:

在这里插入图片描述

注意事项:

  1. string可以通过c_str函数转换为const char类型,char类型也可以用to_string转换为string类型
  2. STL中的string是深拷贝!!
  3. STL中的string的底层在插入的时候也会给string串预留一些空间,避免频繁扩容
  4. 在cin输入string的时候,默认是遇到空格与回车就结束(在笔试题中尤为重要)
  5. string的末尾追加通常都是用+号的运算符重载,比较方便,当然也可以用append函数
  6. 深浅拷贝
    ①浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以 当继续对资源进项操作时,就会发生发生了访问违规
    ②深拷贝:如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出,一般情况都是按照深拷贝方式提供
  7. string的缺省参数是string s = “”,不能是string s = nullptr或者string s = ‘\0’
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值