string类的模拟实现

头文件

#include<iostream>
#include<assert.h>

using namespace std;


namespace bit
{
	class string
	{
	public:
		string(const char* str="");              //构造

		string(const string& str);            //拷贝构造
		 
		char* c_str()const;                   //转换成为字符串

		size_t size()const;                   //元素个数

		char operator[](size_t pos)const;

		string& operator=(const string& str);

		void reserve(size_t n);               //reserve:预留,为string预留n的容量

		void push_back(const char ch);

		void push_back(const char* str);

		void insert(size_t pos, const char ch);

		void operator+=(const char*str);

		void operator+=(const char ch);

		void erase(size_t pos, int len);

		size_t find(size_t pos, char ch);

		string substr(size_t pos, int len);

		void clear();

		void swap(string &s);

	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	};
	ostream& operator<<(ostream& os, const string& str);
	istream& operator>> (istream& is, string& str);
}

源文件

#include"string.h"

namespace bit
{
	string::string(const char* str)
		:_size(strlen(str))
	{
		_str = new char[_size+1];
		_capacity = _size;
		strcpy(_str, str);
	}

	string::string(const string& str)
	{
		_str = new char[str._size];
		_size = str._size;
		_capacity = str._capacity;
		strcpy(_str, str._str);
	}

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

	size_t string::size()const
	{
		return _size;
	}

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

	string& string::operator=(const string& str)
	{
		if (this!= &str)
		{
			_capacity = str._capacity;
			_size = str._size;
			char* temp = new char[str._size + 1];
			strcpy(temp, str._str);
			delete[]_str;
			_str = temp;
		}
		return *this;
	}


	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* temp = new char[n + 1];
			delete _str;
			_str = temp;
			_capacity = n;
			
		}
	}


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


	void string::push_back(const char* str)
	{
		size_t n = strlen(str);
		if (_size == _capacity)
		{
			_capacity = (_capacity == 0 ? 4 : 2 * _capacity)+n;
			reserve(_capacity);
		}
		
		for (int i = 0; i < n; i++)
		{
			_str[_size + i] = str[i];
		}
		_size += n;
		_str[_size + 1] = '\0';
	}

	
	void string::insert(size_t pos, const char ch)
	{
		if (_size == _capacity)
		{
			_capacity = (_capacity == 0 ? 4 : 2 * _capacity);
			reserve(_capacity);
		}

		for (size_t i = _size; i > pos; i--)   //
		{
			_str[i] = _str[i - 1];
		}
		_str[pos] = ch;
		_size++;
		_str[_size] = '\0';

		
	}

	void string::operator+=(const char*str)
	{
		if (_size == _capacity)
		{
			_capacity = (_capacity == 0 ? 4 : 2 * _capacity);
			reserve(_capacity);
		}
		push_back(str);
		
	}

	void string::operator+=(const char ch)
	{

		if (_size == _capacity)
		{
			_capacity = (_capacity == 0 ? 4 : 2 * _capacity);
			reserve(_capacity);
		}
		push_back(ch);
	}
	
	void string::erase(size_t pos, int len)
	{
		assert(pos < _size);
		if (pos+len>_size)
		{
			_str[pos + 1] = '\0';
		}
		else
		{
			for (int i = 0; i <pos+len; i++)
			{
				_str[pos + i] = _str[pos + len + i];
			}
		}
		_size -= len;
	}

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

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

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

		return os;
	}

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

	istream& bit::operator>> (istream& is, string& str)
	{
		str.clear();
		char ch = is.get();
		while (ch != ' ' && ch != '\n')
		{
			str += ch;
			ch = is.get();
		}

		return is;
	}

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

测试文件

#include"string.h"



void test01()
{
	bit::string s1("hello world");
	const bit::string s2(s1);

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

	cout << s2.size() << endl;

	cout << s2[1] << endl;

}


void test02()
{
	bit::string s1("hello world");
	bit::string s2 = s1;
	cout << s1.c_str() << endl;


}

void test03()
{
	bit::string s1("hello world");
	s1.push_back('x');
	cout << s1.c_str() << endl;

	bit::string s2;
	for (int i = 0; i < 10; i++)
	{
		s2.push_back('x');
	}
	cout << s2.c_str() << endl;

	bit::string s3("hello world");
	s3.push_back("hello world");
	cout << s3.c_str() << endl;
}

void test04()
{
	bit::string s1("hello world");
	s1.insert(5, 'x');
	cout << s1.c_str() << endl;

	bit::string s2("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
	//s2.insert(0, 'h');
	cout << s2.c_str() << endl;
}


void test05()
{
	bit::string s1("hello world");
	s1 += " hello world";
	cout << s1.c_str() << endl;

	s1 += 'x';
	cout << s1.c_str() << endl;
}

void test06()
{
	bit::string s1("One day I will be a successful person");
	s1.erase(0, 8);
	cout << s1.c_str() << endl;
}

void test07()
{
	bit::string s1("One day I will be a successful person");
	cout << s1.find(0, 'I') << endl;

	cout << s1.find(0, 'z')<<endl;
}


void test08()
{
	bit::string s1("One day I will be a successful person");
	cout << s1.substr(8, 100).c_str()<<endl;
	cout << s1 << endl;
}

void test09()
{
	bit::string s1("hello world");
	cin >> s1;
	cout << s1 << endl;
}
int main()
{
	test09();
	return 0;
}

几点说明

swap()函数

其实对于上面的swap()函数,可以调用标准库里面的函数

使用的话,就像下面的那样使用

 这也成功的交换了

但是这里有一个问题,就是你没有发现这样的代价有点大吗

这里需要创建一个临时的对象,特别是对于这里自定义类型,需要临时开辟一块空间,将_str里面的东西拷贝到这个临时对象里面去,太麻烦了

所以这里我们可以从重新写一个,只需要交换指向,指针变量交换指向,整形变量交换值

 但是凡是不要慌,C++的string类里面是有swap()函数的

直接向下面的这样用就可以了

关于提取流函数

 这里用的是istream里面get函数,这里是不能用cin或者scanf函数的

就是这里用cin的话,是不能提取到空格的,下面的程序输入了5个x,但是实际输出的只有一个,说明cin在这里,遇到了空格就停止了

scanf函数同样是如此

关于拷贝构造函数

上面有两种写法,一种是传统写法,使用的是深拷贝,另外一种是借助他人的力量,两种写法在消耗上面没有任何差别,在string优点很少,目前发现的就是干净简洁,安全,因为是借助编译器自动调用构造和析构函数,而不需要手动的去开辟和释放资源,所以安全,但是在链表部分会有很大的帮助,在链表部分如果你要拷贝构造,你一个一个的拷贝就有些麻烦,直接像下面这样不是更好(具体我们在链表部分再说)

上面需要注意的是,swap函数必须要使用引用传值,使用传值传参的话会诱发无穷递归

这个会在2,3步之间无限循环 

赋值重载的现代写法

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值