string类的模拟实现--C++

string类的模拟实现–C++

C++中的string类是一个表示字符串的字符类,string的模拟实现也是一个考点及重点,在这里,我简单整理了一下string操作的模拟实现

模拟实现string类
class String
	{
	public:
	//成员函数
	private:
	   char* _str;
	   size_t _size;
	   size_t _capacity;
	};

注意:_size用来表示有效字符串的长度(不包括’\0’)
_capacity表示字符串的容量大小

成员函数
  1. 构造函数
//构造函数
 strings::String(const char* str = " ")
		{
			if (nullptr == str)
			{
				assert(false);
				return;
			}

			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
			cout << "构造:" << _str << endl;
		}   
  1. 拷贝构造
String(const String& s)
			:_str(new char[s._capacity + 1])//开辟空间
			, _size(s._size)
			, _capacity(s._capacity)
		{
			strcpy(_str, s._str);//拷贝内容
			cout << "拷贝:" << _str << endl;
		}

注意:这里运用深拷贝,重新给_str开辟一段新的空间,再使用strcpy将形参中s._str的内容拷贝过来

  1. 赋值运算符重载(传的String类)

法一:传参传的为String类

	String& operator=(const String& s)
		{
		if (this != &s)
		{
		delete[]_str;//释放旧的内存空间
		char* pStr = new char[s._capacity + 1];//申请新的内存空间
		strcpy(pStr,s._str);

		_str = pStr;
		_size = s._size;
		_capacity = s._capacity;
		}
		cout << "赋值重载:" << _str << endl;
		return *this;
		}

注意:释放_str旧空间后,再重新申请新的空间,将传参传的String类的s._str拷贝给新的空间,再将_size,_capacity重新设置

法二:创建一个临时变量,使用了拷贝构造函数

String& operator=(const String& s)
		{
		if (this != &s)
		{
		String tmp(s);//创建一个临时变量
		swap(_str, tmp._str);//使用swap函数交换
		_size = tmp._size;
		_capacity = tmp._capacity;
		}
		return *this;
		}

注意:这里没有重新申请空间,但是却在函数内部利用拷贝函数重新创建了一个string类型的临时变量,再利用交换函数进行交换,而且_size,_capacity也进行重新设置

法三:

String& operator=(String& s)
		{
			if (this != &s)
			{
				//传入进来的参数是传值,相当于上面的临时变量
				Swap(s);
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}
		void Swap(String& s)
		{
			swap(_str, s._str);
			swap(_size, s._size);
			swap(_capacity, s._capacity);
		}

注意:此方法不用创建临时变量,利用了函数传参时是传值的原理,直接由编译器拷贝一份,拿来用即可

赋值运算符的重载(传的是字符串)

String& operator=(const char* str)
		{
			delete[]_str;//删除旧的内存空间
			size_t size_str = strlen(str);//算出字符串的大小
			//开辟空间
			_capacity = size_str + 1;
			_str = new char[_capacity];
			//复制
			strcpy(_str, str);
			_size = _capacity - 1;

			return *this;
		}
  1. 析构函数
~String()
		{
			if (_str)
			{
				delete[]_str;
				_str = nullptr;
				_size = 0;
				_capacity = 0;
			}
		}

注意:在使用new与delete是要成对使用,切记不可以混搭使用

  1. push_back

尾插一个字符

void PushBack(char c)
		{
			if (_size == _capacity)
				_Reserved_(_capacity * 2);//扩容

			_str[_size++] = c;//后置++
			_str[_size] = '\0';
		}

注意:再进行尾插操作时,一定要判断字符串的容量是否足够,不够则需进行扩容操作

尾插一个字符串

void PushBack(const char* str)
		{
			size_t str_size = strlen(str);

			//如果容量不够,则扩容(包含'\0')
			if (_size + str_size + 1 >= _capacity)
			{
				//扩容
				_capacity += str_size;
				expand(_capacity);

				//拷贝
				while (*str != '\0')
				{
					_str[_size++] = *str++;
				}
				_str[_size] = '\0';
			}
		}
//扩容(重新申请一个空间大小足够的空间,包括原来的和现在需要的空间大小)
		void expand(size_t n)
		{
			char* tmp = new char[n];

			//复制原来空间的内容
			strcpy(tmp, _str);
			delete[]_str;
			_str = tmp;
			_capacity = n;
		}
  1. append
void Append(const char* str)
		{
			reserve(_size + strlen(str) + 1);
			strcpy(_str + _size, str);
			_size += strlen(str);
			/*for (size_t i = 0; i < strlen(str); i++)
			{
				PushBack(str[i]);
			}*/
		}

注意:append函数:追加字符串str

  1. Insert

在指定位置插入一个字符

void Insert(size_t pos, char c)
		{
			if (_size < pos)
			{
				cout << "地址错误" << endl;
				return;
			}
			else
			{
				//pos位置正常,可以插进去
				if (_size + 1 >= _capacity)
				{
					expand(_capacity * 2);//扩容
				}
				_str[_size+1] = '\0';

				//将pos后的位置全部向后移动一位
				for (size_t i = _size; i > pos; --i)
				{
					_str[i] = _str[i - 1];
				}
				_str[pos] = c;
				_size++;
			}
		}

注意:在插入时要先判断要插的位置是否合理,不合理便直接退出;经过判断之后,先扩容再将pos之后的位置全部向后移动一位,最后将字符放在要插的位置

在指定位置插入字符串

void Insert(size_t pos, const char* str)
		{
			if (_size < pos)
			{
				cout << "地址错误" << endl;
				return;
			}

			size_t str_size = strlen(str);
			if (str_size == 0)
			{
				cout << "str为空字符串" << endl;
				return;
			}

			if (_size + str_size + 1 >= _capacity)
			{
				_capacity = _size + str_size + 1;
				expand(_capacity);//扩容
			}

			int last_index = _size + str_size;
			_str[last_index--] = '\0';//加'\0'

			//将pos后的字符串都向后移str_size个位置
			for (int i = _size - 1; i > (int)pos; --i)
			{
				_str[last_index--] = _str[i];
			}

			//插入字符
			while (*str != '\0')
			{
				_str[pos++] = *str++;
			}

			_size += str_size;
		}

注意:首先判断地址pos是否合理、字符串的长度是否为0;然后再扩容,并且提前加好’\0’,将pos后的字符串都向后移str_size个位置,最后插入字符

  1. PopBack:尾删一个字符
void PopBack()
		{
			if (_size == 0)
			{
				cout << "字符串为空" << endl;
				return;
			}
			_size--;
			_str[_size] = '\0';
		}	

注意:在判断字符串非空后,直接将_size减一,则完成尾删操作

  1. Erase:在指定位置pos之后删除一个长度为n的字符串
void Erase(size_t pos, size_t n)
		{
			if (pos >= _size)
			{
				cout << "pos的位置不合法" << endl;
				return;
			}

			if (pos + n < _size)
			{
				//pos之后的字符个数大于n
				size_t index_erase = pos + n;
				while (index_erase != _size)
				{
					_str[pos++] = _str[index_erase++];
				}
			}

			//pos之后的字符个数小于n
			_str[pos] = '\0';
			_size = pos;
		}
  1. 查找字符
size_t Find(char c)
		{
			for (size_t i = 0; i < _size; i++)
			{
				if (_str[i] == c)
					return i;
			}
			return -1;
		}
  1. 运算符重载

+=运算符重载

String& operator+=(char c)
		{
			PushBack(c);
			return *this;
		}

[]运算符重载

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

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

< > <= >= != ==的重载

bool operator>(const String& s)
		{
			size_t i = 0;
			while (_str[i] == s._str[i] && i < _size)
			{
				i++;
			}

			if (i == _size)
			{
				return  false;
			}
		}
		//法一
		/*bool operator==(const String& s)
		{
			for (int i = 0; i<_size; i++)
			{
				if (_str[i] != s._str[i])
				{
					return false;
				}
			}
			return true;
		}*/

		//法二
		bool operator==(const String& s)
		{
			size_t i = 0;
			while (_str[i] == s._str[i] && i < _size)
			{
				i++;
			}
			if (i == _size && s._str[i] == '\0')
			{
				return true;
			}
			else
				return false;
		}

		bool operator>=(const String& s)
		{
			if (*this > s || *this == s)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		bool operator != (const String& s)
		{
			if (*this == s)
			{
				return false;
			}
			else
				return true;
		}

		bool operator<=(const String& s)
		{
			if (!(*this > s))
			{
				return true;
			}
			return false;
		}
  1. 容量的操作
size_t size()const
		{
			return _size;
		}

		size_t capacity()const
		{
			return _capacity;
		}

		bool empty()const
		{
			return 0 == _size;
		}

		//将有效字符的个数改成newsize,多出来的空间用c来替代
		void resize(size_t newsize, char c = char())
		{
			if (newsize > _size)
			{
				if (newsize > _capacity)
				{
					expand(newsize);
				}

				memset(_str + _size, c, newsize - _size);
			}
			else
			{
				_size = newsize;
				_str[newsize] = '\0';
			}
		}

		//预留空间
		void reserve(size_t newcapacity)
		{
			if (newcapacity > _capacity)
			{
				expand(newcapacity);
			}
		}

		void print()
		{
			printf("%s\n", _str);
		}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值