Sting主要接口模拟实现

发布于:2022-11-09 ⋅ 阅读:(10) ⋅ 点赞:(0) ⋅ 评论:(0)

目录

前言

成员变量

 构造,析构,拷贝构造

iterator(迭代器)

Capacity(容量)

实现[]

插入单个字符或字符串

删除指定位置的数据

查找字符或字符串

重载+=

流输入和流提取

总代码


前言

1.string是表示字符串的字符串类                                                                                                        2.该类的结构和常规容器的接口基本相同,只是多了一些专门操作string类的操作                            3.不可操作多字节或者变长字符的序列

成员变量

char* _str;//
size_t _size;//该str长度
size_t _capacity;//空间容量大小

 构造,析构,拷贝构造

//构造函数
string(const char* str = " ")//确保创建string str1,空串报错的情况;
{
    _size = strlen(str);
    _capacity = _size;
    _str = new char[_capacity + 1];//为什么要+1是为了给'\0'留取空间,因为字符串是\0结束
    strcpy(_str, str);
}

//拷贝构造
string(const string& str)
	:_str(nullptr)
	,_size(0)
	,_capacity(0)
{
	string tmp(str._str);
	_str = tmp._str;
	_size = tmp._size;
	_capacity = tmp._capacity;
}

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

iterator(迭代器)

只介绍常见的四种迭代器的实现

//const和非const
//begin()获取首元素,end()size位
//也就是前闭后开的形式
typedef char* iterator;
typedef const char* const_iterator;

iterator begin()
{
	return _str;
}

iterator end()
{
	return _str + _size;
}

const_iterator begin() const
{
	return _str;
}

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

Capacity(容量)

官方定义

Resizes the string to a length of n characters.

If n is smaller than the current string length, the current value is shortened to its first n character, removing the characters beyond the nth.

If n is greater than the current string length, the current content is extended by inserting at the end as many characters as needed to reach a size of n. If c is specified, the new elements are initialized as copies of c, otherwise, they are value-initialized characters (null characters).

改变大小,具有初始化的作用,也就是resize的大小大于size时,n-size的空间补0,resize的大小小于size时,size-n的位置删除。

        void resize(size_t n, char ch = '\0')
		{
			if (n > _size)
			{
				reserve(n);
				for (size_t i = _size; i < n; ++i)
				{
					_str[i] = ch;
				}
				_str[n] = '\0';
				_size = n;
			}
			else
			{
				_str[n] = '\0';
				_size = n;
			}
		}

 

 就是常见的扩容写法。

        void reserve(size_t n)//扩容
		{
			assert(n > _capacity);
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);
			delete _str;
			_str = tmp;
			_capacity = n;
		}

//只需要注意的是npos,npos用来表示不存在的位置,一般初始化为-1
        void erase(size_t pos, size_t len = npos)//判空
		{
			assert(pos < _size);

			if (len == npos || pos + len >= _size)
			{
				_str[_size] = '\0';
				_size = pos;
			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
		}

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

实现[]

实现[],可以让我们的string,像数组一样进行访问,获得相应下标的元素。

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

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

插入单个字符或字符串

由于直接实现insert,push_back直接进行复用就可以了。

        //插入单个字符
		string& insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if (_size == _capacity)
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			//挪动数据
			//int end = _size//
			//加1是为了防止pos = _size时,end = pos会报错.//
			size_t end = _size + 1;
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				--end;
			}
			_str[pos] = ch;
			_size++;
			return *this;
		}
		//插入字符串
		string& insert(size_t pos, const char* str)
		{
			assert(pos <= _size);
			int len = strlen(str);
			if (_size + len > _capacity)
				reserve(_size + len);
			//挪动
			size_t end = _size + len;
			while (end >= pos + len)
			{
				_str[end] = _str[end - len];
				--end;
			}
			strncpy(_str + pos, str, len);
			_size += len;

			return *this;
			
		}

删除指定位置的数据

需要注意的就是我们的erase是需要指定删除的长度的,没有给定长度,或者输入的长度大于(_size-pos),默认是将pos位之后的全部删除

        void erase(size_t pos, size_t len = npos)
		{
			assert(pos < _size);

			if (len == npos || pos + len >= _size)
			{
				_str[_size] = '\0';
				_size = pos;
			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
		}

查找字符或字符串

用法就是从自己给的位置去查找需要的字符或字符串

        //查找字符
		size_t find(char ch, size_t pos = 0) const
		{
			assert(pos < _size);
			for (size_t i = pos; i < _size; ++i)
			{
				if (ch == _str[i])
					return i;
			}
			return npos;
		}

		//查找字符串
		size_t find(const char* str, size_t pos = 0) const
		{
			assert(str);
			assert(pos < _size);
			const char* tmp = strstr(_str + pos, str);
			if (tmp == nullptr)
				return npos;
			else
				return tmp - _str;
		}

重载+=

        string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}

		string& operator+=(const char* str)
		{
			//append(str);
			insert(_size, str);
			return *this;
		}

常见的比较运算符重载

只需要重载其中的>,==,别的直接对其进行复用即可实现

        bool operator>(const string& str) const
		{
			return strcmp(_str, str._str) > 0;
		}

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

		bool operator>=(const string& str) const
		{
			return *this > str || *this == str;
		}

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

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

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

		const char* c_str() const
		{
			return _str;
		}

		size_t size() const
		{
			return _size;
		}

		size_t capacity() const
		{
			return _capacity;
		}

流输入和流提取

更多需要注意的是输入

    ostream& operator<<(ostream& out, const string& str)
	{
		for (size_t i = 0; i < str.size(); i++)
		{
			out << str[i];
		}
		return out;
	}

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

		char ch;
		ch = in.get();

		const size_t N = 32;
		char buff[N];
		size_t i = 0;

		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			if (i == N - 1)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}

			ch = in.get();
		}

		buff[i] = '\0';
		s += buff;

		return in;
	}

总代码

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string.h>
#include<assert.h>

using namespace std;

namespace anwtie
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

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

		string(const char* str = " ")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];// '\0'
			strcpy(_str, str);
		}

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

		//s2(s1);
		string(const string& str)
			:_str(nullptr)
			,_size(0)
			,_capacity(0)
		{
			string tmp(str._str);
			/*_str = tmp._str;
			_size = tmp._size;
			_capacity = tmp._capacity;*/
			swap(tmp);
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
		//扩容
		void reserve(size_t n)
		{
			assert(n > _capacity);
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);
			delete _str;
			_str = tmp;
			_capacity = n;
		}

		//更改大小,多了补0,少了扔
		void resize(size_t n, char ch = '\0')
		{
			if (n > _size)
			{
				reserve(n);
				for (size_t i = _size; i < n; ++i)
				{
					_str[i] = ch;
				}
				_str[n] = '\0';
				_size = n;
			}
			else
			{
				_str[n] = '\0';
				_size = n;
			}
		}

		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';
		}

		//更改容量,可以理解成push_back字符串
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
				reserve(_size + len);
			strcpy(_str + _size, str);
			_size += len;
		}

		//插入单个字符
		string& insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if (_size == _capacity)
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			//挪动数据
			//int end = _size//
			//加1是为了防止pos = _size时,end = pos会报错.//
			size_t end = _size + 1;
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				--end;
			}
			_str[pos] = ch;
			_size++;
			return *this;
		}
		//插入字符串
		string& insert(size_t pos, const char* str)
		{
			assert(pos <= _size);
			int len = strlen(str);
			if (_size + len > _capacity)
				reserve(_size + len);
			//挪动
			size_t end = _size + len;
			while (end >= pos + len)
			{
				_str[end] = _str[end - len];
				--end;
			}
			strncpy(_str + pos, str, len);
			_size += len;

			return *this;
			
		}

		void erase(size_t pos, size_t len = npos)
		{
			assert(pos < _size);

			if (len == npos || pos + len >= _size)
			{
				_str[_size] = '\0';
				_size = pos;
			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
		}

		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}

		//查找字符
		size_t find(char ch, size_t pos = 0) const
		{
			assert(pos < _size);
			for (size_t i = pos; i < _size; ++i)
			{
				if (ch == _str[i])
					return i;
			}
			return npos;
		}

		//查找字符串
		size_t find(const char* str, size_t pos = 0) const
		{
			assert(str);
			assert(pos < _size);
			const char* tmp = strstr(_str + pos, str);
			if (tmp == nullptr)
				return npos;
			else
				return tmp - _str;
		}

		//s1 = s3;
		string& operator=(const string& str)
		{
			if (this != &str)
			{
				string tmp(str);
				swap(tmp);
			}
			return *this;
		}
		//s1 =s3;
		//类似于给老板打工的行为
		string& operator=(string str)
		{
			swap(str);
			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];
		}

		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}

		string& operator+=(const char* str)
		{
			//append(str);
			insert(_size, str);
			return *this;
		}

		bool operator>(const string& str) const
		{
			return strcmp(_str, str._str) > 0;
		}

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

		bool operator>=(const string& str) const
		{
			return *this > str || *this == str;
		}

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

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

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

		const char* c_str() const
		{
			return _str;
		}

		size_t size() const
		{
			return _size;
		}

		size_t capacity() const
		{
			return _capacity;
		}


	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	public:
		const static size_t npos = -1;
	};

	ostream& operator<<(ostream& out, const string& str)
	{
		for (size_t i = 0; i < str.size(); i++)
		{
			out << str[i];
		}
		return out;
	}

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

		char ch;
		ch = in.get();

		const size_t N = 32;
		char buff[N];
		size_t i = 0;

		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			if (i == N - 1)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}

			ch = in.get();
		}

		buff[i] = '\0';
		s += buff;

		return in;
	}

}