[C++]string及其模拟实现

2023-05-11 09:29:58 浏览数 (1)

string及其模拟实现::

1.构造函数

代码语言:javascript复制
//注意: '' "" ""的区别
string(const char* str = "")
{
	 //对空指针不能strlen
	 _size = strlen(str);
	 _capacity = _size;
	 _str = new char[_capacity   1];
	 strcpy(_str, str);
}

2.拷贝构造函数

传统写法:

代码语言:javascript复制
//拷贝构造传统写法
//s2(s1)
string(const string& s)
{
	_str = new char[s._capacity   1];
	_capacity = s.capacity();
	_size = s._size;
	strcpy(_str, s._str);
}

现代写法:

代码语言:javascript复制
void swap(string& s)
{
	  std::swap(_str, s._str);
	  std::swap(_size, s._size);
	  std::swap(_capacity, s._capacity);
}
string(const string& s)
	  :_str(nullptr)
	  ,_size(0)
	  ,_capacity(0)
{
	    string tmp(s._str);//构造函数
		//交换s2和tmp
		//this->swap(tmp);
		swap(tmp);
}

3.赋值运算符重载

传统写法:

代码语言:javascript复制
//赋值重载传统写法:
//s1=s3
string& operator=(const string& s)
{
		if (this != &s)
		{
			char* tmp = new char[s._capacity   1];
			strcpy(tmp, s._str);
			//释放s1的旧空间
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}
		return *this;
}

现代写法:

代码语言:javascript复制
//赋值重载现代写法:
//s1=s3
//string& operator=(const string& s)
//{
//	//string tmp(s._str);
//	string tmp(s);
//	swap(tmp);
//	return *this;
//}
//s1=s3
string& operator=(string s)
{
	//不用传引用传参 就用传值传参 s是s3的拷贝构造
	swap(s);
	return *this;
}

4.析构函数

代码语言:javascript复制
~string()
{
	delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}

5.string中的小接口

代码语言:javascript复制
const char* c_str() const
{
	return _str;
}
size_t size() const
{
	return _size;
}
size_t capacity() const
{
	return _capacity;
}
void clear()
{
    _arr[0] = '';
    _size = 0;
}

6.operator[]的运算符重载

代码语言:javascript复制
//普通对象可读可写
char& operator[](size_t pos)
{
	assert(pos < _size);
	return _str[pos];
}
//const对象:只读
const char& operator[](size_t pos) const
{
	assert(pos < _size);
	return _str[pos];
}

7.迭代器

代码语言:javascript复制
typedef char* iterator;
iterator begin()
{
	return _str;
}
iterator end()
{
	return _str   _size;
}

8.reserve和resize

代码语言:javascript复制
void reserve(size_t n)
{
	//保证只扩容不缩容
	if (n > _capacity)
	{
		char* tmp = new char[n   1];
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}
void resize(size_t n, char ch = '')
{
	if (n > _size)
	{
		reserve(n);
		for (size_t i = _size; i < n;   i)
		{
			_str[i] = ch;
		}
		_size = n;
		_str[_size] = '';
	}
	else
	{
		_str[n] = '';
		_size = n;
	}
}

9.push_back、append和 =的重载

代码语言:javascript复制
void push_back(char ch)
{
	if (_size == _capacity)
	{
		size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
		reserve(newCapacity);
	}
	_str[_size] = ch;
	  _size;
	_str[_size] = '';
}
void append(const char* str)
{
	size_t len = strlen(str);
	if (_size   len > _capacity)
	{
		reserve(_size   len);
		strcpy(_str   _size, str);
		_size  = len;
	}
}
string& operator =(char ch)
{
	push_back(ch);
	return *this;
}
string& operator =(const char* str)
{
	append(str);
	return *this;
}

10.insert、erase和find

代码语言:javascript复制
string& insert(size_t pos, char ch)
{
	assert(pos <= _size);
	if (_size == _capacity)
	{
		size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
		reserve(newCapacity);
	}
	//挪动数据
	//int end = _size;
	//操作符两边的操作数类型不一样时会发生隐式类型的提升 解决办法1:将pos强转为int
	//注意: >= 一定要强转 如果想用无符号 判断部分就不能是>=
	/*while (end >= (int)pos)
	{
		_str[end   1] = _str[end];
		--end;
	}*/
	//解决方法2:将_str[end-1]赋值给_str[end]
	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)
{
	size_t len = strlen(str);
	if (_size   len > _capacity)
	{
		reserve(_size   len);
	}
	/*int end = _size;
	while (end >= (int)pos)
	{
		_str[end   len] = _str[end];
		--end;
	}*/
	size_t end = _size   len;
	//问题:当end < len _str[end - len]存在越界 
	//while (end > pos)
	while (end >= pos   len)
	{
		_str[end] = _str[end - len];
		--end;
	}
	//使用strcpy(_str   pos,str)会拷贝使字符串提前结束
	strncpy(_str   pos, str, len);
	_size  = len;
	return *this;
}
string& erase(size_t pos, size_t len = npos)
{
	assert(pos < _size);
	if (len == npos || pos   len >= _size)
	{
		_str[pos] = '';
		_size = pos;
	}
	else
	{
		strcpy(_str   pos, _str   pos   len);
		_size -= len;
	}
	return *this;
}
size_t find(char ch, size_t pos = 0) const
{
	assert(pos < _size);
	while (pos < _size)
	{
		if (_str[pos] == ch)
		{
			return pos;
		}
		  pos;
	}
	return npos;
}
size_t find(const char* str, size_t pos = 0) const
{
	assert(pos < _size);
	const char* ptr = strstr(_str   pos, str);
	if (ptr == nullptr)
	{
		return npos;
	}
	else
	{
		return ptr -> _str;
	}
}

11.<<和>>的运算符重载

代码语言:javascript复制
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, const string& s)
{
	/*char ch;
	cin >> ch;
	while (ch != ' ' && ch != 'n')
	{
		s  = ch;
		cin >> ch;
	}*/
	/*char ch = in.get();
	while (ch != ' ' && ch != 'n')
	{
		s  = ch;
		ch = in.get();
	}*/
	//该写法不需要频繁扩容
	s.clear();
	char buff[128] = { '' };
	size_t i = 0;
	char ch = in.get();
	while (ch != ' ' && ch != 'n')
	{
		if (i == 127)
		{
			//满了
			s  = buff;
			i = 0;
		}
		buff[i  ] = ch;
		ch = in.get();
	}
	if (i >= 0)
	{
		buff[i] = '';
		s  = buff;
	}
	return in;
}

12.模拟实现string的整体代码

代码语言:javascript复制
#include<iostream>
#include<assert.h>
using namespace std;
namespace TXLF
{
	class string
	{
	public:
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str   _size;
		}
		//注意: '' "" ""的区别
		string(const char* str = "")
		{
			//对空指针不能strlen
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity   1];
			strcpy(_str, str);
		}
		void swap(string& s)
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}
		/*string()
		{
			_str = new char[1];
			_str[0] = '';
			_capacity = _size = 0;
		}*/
		//拷贝构造传统写法
		//s2(s1)
		string(const string& s)
		{
			_str = new char[s._capacity   1];
			_capacity = s.capacity();
			_size = s._size;
			strcpy(_str, s._str);
		}
		//拷贝构造现代写法
		//s2(s1)
		string(const string& s)
			:_str(nullptr)
			,_size(0)
			,_capacity(0)
		{
			string tmp(s._str);//构造函数
			//交换s2和tmp
			//this->swap(tmp);
			swap(tmp);
		}
		//赋值重载传统写法:
		//s1=s3
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* tmp = new char[s._capacity   1];
				strcpy(tmp, s._str);
				//释放s1的旧空间
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}
		//赋值重载现代写法:
		//s1=s3
		//string& operator=(const string& s)
		//{
		//	//string tmp(s._str);
		//	string tmp(s);
		//	swap(tmp);
		//	return *this;
		//}
		//s1=s3
		string& operator=(string s)
		{
			//不用传引用传参 就用传值传参 s是s3的拷贝构造
			swap(s);
			return *this;
		}
		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
		const char* c_str() const
		{
			return _str;
		}
		size_t size() const
		{
			return _size;
		}
		size_t capacity() const
		{
			return _capacity;
		}
		//普通对象可读可写
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		//const对象:只读
		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];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}
		void resize(size_t n, char ch = '')
		{
			if (n > _size)
			{
				reserve(n);
				for (size_t i = _size; i < n;   i)
				{
					_str[i] = ch;
				}
				_size = n;
				_str[_size] = '';
			}
			else
			{
				_str[n] = '';
				_size = n;
			}
		}
		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newCapacity);
			}
			_str[_size] = ch;
			  _size;
			_str[_size] = '';
		}
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size   len > _capacity)
			{
				reserve(_size   len);
				strcpy(_str   _size, str);
				_size  = len;
			}
		}
		string& operator =(char ch)
		{
			push_back(ch);
			return *this;
		}
		string& operator =(const char* str)
		{
			append(str);
			return *this;
		}
		string& insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newCapacity);
			}
			//挪动数据
			//int end = _size;
			//操作符两边的操作数类型不一样时会发生隐式类型的提升 解决办法1:将pos强转为int
			//注意: >= 一定要强转 如果想用无符号 判断部分就不能是>=
			/*while (end >= (int)pos)
			{
				_str[end   1] = _str[end];
				--end;
			}*/
			//解决方法2:将_str[end-1]赋值给_str[end]
			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)
		{
			size_t len = strlen(str);
			if (_size   len > _capacity)
			{
				reserve(_size   len);
			}
			/*int end = _size;
			while (end >= (int)pos)
			{
				_str[end   len] = _str[end];
				--end;
			}*/
			size_t end = _size   len;
			//问题:当end < len _str[end - len]存在越界 
			//while (end > pos)
			while(end >= pos   len)
			{
				_str[end] = _str[end - len];
				--end;
			}
			//使用strcpy(_str   pos,str)会拷贝使字符串提前结束
			strncpy(_str   pos, str, len);
			_size  = len;
			return *this;
		}
		string& erase(size_t pos, size_t len = npos)
		{
			assert(pos < _size);
			if (len == npos || pos   len >= _size)
			{
				_str[pos] = '';
				_size = pos;
			}
			else
			{
				strcpy(_str   pos, _str   pos   len);
				_size -= len;
			}
			return *this;
		}
		size_t find(char ch, size_t pos = 0) const
		{
			assert(pos < _size);
			while (pos < _size)
			{
				if (_str[pos] == ch)
				{
					return pos;
				}
				  pos;
			}
			return npos;
		}
		size_t find(const char* str, size_t pos = 0) const
		{
			assert(pos < _size);
			const char* ptr = strstr(_str   pos, str);
			if (ptr == nullptr)
			{
				return npos;
			}
			else
			{
				return ptr -> _str;
			}
		}	
		void clear()
		{
			_size = 0;
			_str[0] = '';
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		//const的静态整型变量可以在类中进行初始化
		const static size_t 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, const string& s)
	{
		/*char ch;
		cin >> ch;
		while (ch != ' ' && ch != 'n')
		{
			s  = ch;
			cin >> ch;
		}*/
		/*char ch = in.get();
		while (ch != ' ' && ch != 'n')
		{
			s  = ch;
			ch = in.get();
		}*/
		//该写法不需要频繁扩容
		s.clear();
		char buff[128] = { '' };
		size_t i = 0;
		char ch = in.get();
		while (ch != ' ' && ch != 'n')
		{
			if (i == 127)
			{
				//满了
				s  = buff;
				i = 0;
			}
			buff[i  ] = ch;
			ch = in.get();
		}
		if (i >= 0)
		{
			buff[i] = '';
			s  = buff;
		}
		return in;
	}
	void test_string1()
	{
		string s1("hello world");
		cout << s1.c_str() << endl;
		for (size_t i = 0; i < s1.size();   i)
		{
			s1[i]  ;
		}
		cout << s1.c_str() << endl;
		string::iterator it1 = s1.begin();
		while (it1 != s1.end())
		{
			(*it1)--;
			  it1;
		}
		cout << s1.c_str() << endl;
		//范围for的原理就是迭代器
		for (auto ch : s1)
		{
			cout << ch << " ";
		}
		cout << endl;
	}
	void test_string2()
	{
		string s1("hello");
		s1  = ' ';
		s1  = "world hello world";
		cout << s1.c_str() << endl;
		string s2;
		s2  = 'x';
		cout << s2.c_str() << endl;
	}
	void test_string3()
	{
		string s1("helloworld");
		s1.insert(5, ' ');
		cout << s1.c_str() << endl;
		s1.insert(0, 'x');
		cout << s1.c_str() << endl;
		string s2("helloworld");
		cout << s2.c_str() << endl;
		s2.insert(5, "   ");
		s2.insert(0, "hello");
		cout << s2.c_str() << endl;
	}
	void test_string4()
	{
		string s1("hello hello world");
		s1.erase(0, 6);
		cout << s1.c_str() << endl;
		s1.erase(5);
		cout << s1.c_str() << endl;
	}
	void test_string5()
	{
		string s1("hello world");
		s1.resize(5);
		cout << s1.size() << endl;
		cout << s1.capacity() << endl;
		cout << s1.c_str() << endl << endl;

		string s2("hello world");
		s2.resize(15, 'x');
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;
		cout << s2.c_str() << endl << endl;

		string s3("hello world");
		s3.resize(20, 'x');
		cout << s3.size() << endl;
		cout << s3.capacity() << endl;
		cout << s3.c_str() << endl << endl;
	}
	void test_string6()
	{
		string s1("hello world");
		cout << s1 << endl;
		cout << s1.c_str() << endl;

		s1.insert(5,'');
		cout << s1.size() << endl;
		cout << s1.capacity() << endl;

		cout << s1 << endl;
		cout << s1.c_str() << endl;

		cin >> s1;
		cout << s1 << endl;
	}
	void test_string7()
	{
		string s1("hello world");
		string s2(s1);
		cout << s1 << endl;
		cout << s2 << endl;
		string s3("xxxxxxxxxxxxxxxxxxxxxxxx");
		s1 = s3;
		cout << s1 << endl;
		cout << s3 << endl;
		s1.swap(s2);
		swap(s1, s2);
		//内置类型因为模板的存在 也有了构造与析构函数 
		int i(10);
		int j = int();
	}
}

0 人点赞