目录

简介:

1.指定位置插入删除的实现

1.1指定位置插入字符串

1.2指定位置删除指定长度字符串

1.3将字符串长度调整到指定长度

1.4从指定位置开始找指定字符和指定字符串

2.拷贝构造,赋值操作符重载,以及子字符串拷贝

2.1拷贝构造函数

2.2赋值操作符重载

2.3子字符串拷贝

3关系操作符的重载

4.输入输出操作符重载

摘要:


简介:

本文为上篇内容的后半部分,看本文之前最好先看前一部分内容

1.指定位置插入删除的实现

1.1指定位置插入字符串

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

		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(std::max(_size + len, _capacity * 2));
		}

		// 挪动数据
		/*int end = _size;
		while (end >= (int)pos)
		{
			_str[end + len] = _str[end];
			--end;
		}*/

		size_t end = _size + len;
		while (end > pos + len - 1)//与上边的情况相比避免了无符号整型溢出的情况
		{
			_str[end] = _str[end - len];
			--end;
		}

		//strncpy(_str + pos, str, len);
		memcpy(_str + pos, str, len);

		_size += len;
	}

1.2指定位置删除指定长度字符串

void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);

		if (len == npos || len >= _size - pos)//npos是整数的最大值
		{
			// 删完
			_size = pos;
			_str[_size] = '\0';
		}
		else
		{
			// 删部分
			//strcpy(_str + pos, _str + pos + len);
			memcpy(_str + pos, _str + pos + len, _size - (pos + len) + 1);

			_size -= len;
		}
	}

1.3将字符串长度调整到指定长度

void string::resize(size_t n, char ch)
	{
		if (n <= _size)
		{
			// 删除,保留前n个
			_size = n;
			_str[_size] = '\0';
		}
		else
		{
			reserve(n);
			for (size_t i = _size; i < n; i++)//多出来的用指定字符补齐
			{
				_str[i] = ch;
			}
			_size = n;
			_str[_size] = '\0';
		}
	}

1.4从指定位置开始找指定字符和指定字符串

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

		return npos;//找不到返回-1
	}

	size_t string::find(const char* str, size_t pos)
	{
		assert(pos < _size);
		const char* ptr = strstr(_str + pos, str);
		if (ptr)
		{
			return ptr - str;
		}
		else
		{
			return npos;
		}
	}

2.拷贝构造,赋值操作符重载,以及子字符串拷贝

2.1拷贝构造函数

// string s2(s1);
	string::string(const string& s)
	{
		_str = new char[s._capacity + 1];//因为_capacity不包括\0,所以加一
		//strcpy(_str, s._str);
		memcpy(_str, s._str, s._size + 1);//与上同理
		_size = s._size;
		_capacity = s._capacity;
	}

2.2赋值操作符重载

当双目操作符作为成员函数重载时,第一个操作数为当前对象(this,第二个操作数通过参数传递

// s1 = s3
	string& string::operator=(const string& s)
	{
		if (this != &s)
		{
			char* tmp = new char[s._capacity + 1];
			//strcpy(tmp, s._str);
			memcpy(tmp, s._str, s._size + 1);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}

		return *this;
	}

2.3子字符串拷贝

string string::substr(size_t pos, size_t len)
	{
		assert(pos < _size);
		if (len == npos || len > _size - pos)
		{
			len = _size - pos;
		}
		string sub;
		sub.reserve(len);
		for (size_t i = 0; i < len; i++)
		{
			sub += _str[pos + i];
		}
		return sub;
	}

3关系操作符的重载

   	bool string::operator==(const string& s) const
	{
		return strcmp(_str, s._str) == 0;
	}
    bool string::operator<(const string& s) const
	{
		return strcmp(_str, s._str) < 0;
	}

	bool string::operator<=(const string& s) const
	{
		return *this < s || *this == s;
	}

	bool string::operator>(const string& s) const
	{
		return !(*this <= s);
	}

	bool string::operator>=(const string& s) const
	{
		return !(*this > s);
	}

	bool string::operator!=(const string& s) const 
	{
		return !(*this == s);
	}

4.输入输出操作符重载

输入输出操作符只能被重载成全局函数,需要访问私有成员变量时可将其声明为友缘函数

    std::ostream& operator<<(std::ostream& out, const string& s)
	    {
	    	for (auto ch : s)
	    	{
		    	out << ch;
		    }
		    return out;
    	}

	std::istream& operator>>(std::istream& in, string& s)
   	{
		s.clear();

		char buff[256];
		int i = 0;

		char ch;
		//in >> ch;拿不到空格
		ch = in.get();//一个字符一个字符地拿
		while (ch != '\n' && ch != ' ')
		{
			buff[i++] = ch;
			if (i == 255)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}
	
			ch = in.get();
		}

		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;
	}

	std::istream& getline(std::istream& in, string& s, char delim )
	{
		s.clear();

		char buff[256];
		int i = 0;

		char ch;
		//in >> ch;
		ch = in.get();
		while (ch != delim)
		{
			buff[i++] = ch;
			if (i == 255)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}

			ch = in.get();
		}

		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}

		return in;
	}

摘要:

本文是字符串类实现的后半部分,重点介绍了插入、删除、查找等核心功能的实现细节。通过指定位置插入字符串时处理容量不足和内存挪动,删除操作区分全删与部分删除的情况。查找功能支持字符和子串定位,拷贝构造与赋值操作确保深拷贝正确性。关系运算符重载基于strcmp实现字符串比较,输入输出运算符重载则通过缓冲机制高效处理流数据。整体实现了标准字符串类的关键功能。

更多推荐