string的模拟实现(上)

发布于:2024-04-30 ⋅ 阅读:(30) ⋅ 点赞:(0)

一、模拟实现构造函数、析构函数

class string
{
	public:
		string(const char* str="")
			:_size(strlen(str))
			,_capacity(_size)
		{
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
        ~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}

}

二、实现扩容

void reserve(size_t n)
{
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];//多一个留\0
		strcpy(tmp, _str); //strcpy会把\0也拷贝过去
		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}

三、模拟实现插入

1.push_back

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

2.append

	//5  20
void append(const char* str)//插入字符串
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
}

3.+=

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

4.insert

void insert(size_t pos, char ch)//在pos位置插入一个字符
{
	assert(pos <= _size);
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}
	int end = _size;
	while (end >=(int) pos)
	{
		_str[end + 1] = _str[end];
		--end;
	}
	_str[pos] = ch;
	_size++;
}
头插存在问题,循环在end<pos才会结束,pos最小是0,size_t无符号整形,最小是0,所以会崩溃,解决方案一:把pos转为int

 

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

四、运算符重载

 > < == >=   <=  !=

//s1<s2
bool operator<(const string& s) const//只要不修改
{
	return strcmp(_str,s._str) < 0;
}
bool operator==(const string& s) const
{
	return strcmp(_str,s._str) == 0;
}
bool operator<=(const string& s) const
{
	return *this < s || *this == s;
}
bool operator>(const string& s) const
{
	return !(*this <= s);
}
bool operator>=(const string& s) const
{
	return !(*this < s);
}
bool operator!=(const string& s) const
{
	return !(*this == s);
}

 五、流插入和流提取

1.流插入

ostream& operator<<(ostream& out, const string& s)//用友元是因为我们想访问私有,但是我们通过公有的成员函数就可以访问就不需要友元
{
	for (size_t i = 0; i < s.size(); i++)
	{
		out << s[i];
	}
	return out;
}

2.流提取

istream& operator>>(istream& in, string& s)//流提取是要从缓冲区中取字符
{
    s.clear();
	char ch;
	//in >> ch;//拿不到空格
	ch = in.get();//一个字符一个字符的拿,可以拿到空格
	while (ch != ' ' && ch != '\n')//遇到空格或者换行默认结束
	{
		s += ch;
		//in >> ch;
		ch = in.get();
	}
	return in;
}

相比较于C语言的scanf的优势是什么?

不需要提前开空间,空间不够会扩容,+=,不管你输入多少字符串,只要你内存够,都可以搞定 

#pragma once
namespace bit
{
	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];
			strcpy(_str, str);
		}
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		const char& operator[](size_t pos) const  //可以读不能写
		{
			assert(pos < _size);
			return _str[pos];
		}
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];//多一个留\0
				strcpy(tmp, _str); //strcpy会把\0也拷贝过去
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}
		void push_back(char ch)//插入字符
		{
			if (_size== _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}
		//5  20
		void append(const char* str)//插入字符串
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
		}
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		string& operator+=(const char* str)
		{
			append(str);
			return *this;
		}
		void insert(size_t pos, char ch)//在pos位置插入一个字符
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			size_t end = _size+1;
			while (end > pos)
			{
				_str[end] = _str[end-1];
				--end;
			}
			_str[pos] = ch;
			_size++;
		}
		void insert(size_t pos, const char* str)//在pos位置插入一个字符串
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			size_t end = _size + 1;
			size_t len = strlen(str);
			while (end > pos)
			{
				_str[end+len-1] = _str[end - 1];
				--end;
			}
			for (size_t i = 0; i < len; i++)
			{
				_str[pos++] = str[i];
			}
			_size++;
		}
		void erase(size_t pos, size_t len = npos)
		{

		}
		//s1<s2
		bool operator<(const string& s) const//只要不修改
		{
			return strcmp(_str,s._str) < 0;
		}
		bool operator==(const string& s) const
		{
			return strcmp(_str,s._str) == 0;
		}
		bool operator<=(const string& s) const
		{
			return *this < s || *this == s;
		}
		bool operator>(const string& s) const
		{
			return !(*this <= s);
		}
		bool operator>=(const string& s) const
		{
			return !(*this < s);
		}
		bool operator!=(const string& s) const
		{
			return !(*this == s);
		}
		size_t capacity() const
		{
			return _capacity;
		}
		size_t size() const
		{
			return _size;
		}
		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
		const char* c_str()
		{
			return _str;
		}
		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		const static size_t npos;//静态成员变量不属于对象,必须类外初始化,只有const静态整形可以
	};
	const size_t string::npos = -1;
	ostream& operator<<(ostream& out, const string& s)//用友元是因为我们想访问私有,但是我们通过公有的成员函数就可以访问就不需要友元
	{
		for (size_t i = 0; i < s.size(); i++)
		{
			out << s[i];
		}
		return out;
	}
	istream& operator>>(istream& in, string& s)//流提取是要从缓冲区中取字符
	{
		s.clear();
		char ch;
		//in >> ch;//拿不到空格
		ch = in.get();//一个字符一个字符的拿,可以拿到空格
		while (ch != ' ' && ch != '\n')//遇到空格或者换行默认结束
		{
			s += ch;
			//in >> ch;
			ch = in.get();
		}
		return in;
	}
	void test_string1()
	{
		
		/*string s2;
		cout << s2.c_str() << endl;

		for (size_t i = 0; i < s1.size(); i++)
		{
			cout << s1[i] << " ";
		}
		cout << endl;

		string::iterator it = s1.begin();
		while (it != s1.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
		for (auto ch : s1)
		{
			cout << ch << " ";
		}
		cout << endl;*/
		string s1("hello world");
		cout << s1.c_str() << endl;
	
		const char* str = "str";
		s1.insert(10, str);
		cout << s1.c_str() << endl;
	}

}

 欢迎指正!