c++ string类(模拟实现)

#include <iostream>
#include <String>
#include<assert.h>
#pragma warning(disable:4996)
using namespace std;

namespace bit
{
	class string
	{
		friend ostream& operator<<(ostream& out, const string& s);
		friend istream& operator>>(istream& in, string& s);
	public:
		static const size_t npos = -1;
	public:
		string(const char* s = "") :m_str(nullptr)
		{
			m_capacity = m_size = strlen(s);
			m_str = new char[m_capacity + 1];
			strcpy(m_str, s);
		}
		string(const string& s) :m_str(nullptr), m_size(0), m_capacity(0)
		{
			string tmp(s.m_str);
			_swap(tmp, *this);
		}
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				string tmp(s);
				_swap(tmp, *this);
			}
			return *this;
		}
		~string()
		{
			if (m_str)
			{
				delete[]m_str;
				m_str = nullptr;
			}
			m_size = 0;
			m_capacity = 0;
		}
	public:
		int size()const
		{
			return m_size;
		}
		int capacity()const
		{
			return m_capacity;
		}
		bool empty()const
		{
			return m_size == 0;
		}
		void clear()
		{
			m_size = 0;
			m_str[0] = '\0';//第一个下标填入结束标志符
		}
		const char* c_str() const
		{
			return m_str;
		}
	public:
		typedef char* iterator; //模拟迭代器
		iterator begin()
		{
			return m_str;
		}
		iterator end()
		{
			return m_str + m_size;
		}
	public:
		void push_back(char x)
		{
			if (m_size >= m_capacity)
			{
				reserve(m_capacity * 2);
			}
			m_str[m_size++] = x;
			m_str[m_size] = '\0';
		}
		void reserve(int new_cpy)
		{
			if (new_cpy > m_capacity)//新容量>目前容量才会扩容
			{
				//扩容之后,m_str之前所存的内容仍要存在
				char* new_str = new char[new_cpy + 1];
				memcpy(new_str, m_str, m_size + 1);
				//mecpy(目标,要复制的数据源,要复制的大小个数(包括\0,所以加一));
				m_capacity = new_cpy;
				delete[]m_str;    //m_str[0]='\0';
				m_str = new_str;
			}
		}
	public:
		string& operator+=(char c) //追加一个字符
		{
			push_back(c); //插入一个字符
			return *this;
		}
		void append(const char* str) //追加字符串
		{
			int str_len = strlen(str);
			if (m_size + str_len > m_capacity)//容量不够追加时,扩容
			{
				reserve((m_size + str_len) * 2);
			}
			memcpy(m_str + m_size, str, sizeof(str));
			m_size = m_size + str_len;
			m_str[m_size] = '\0';
		}
		string& operator+=(const char* str)
		{
			append(str);
			return *this;
		}
		void resize(int newSize, char c = '\0')//调整大小为newSize,且填充字符c
		{
			if (newSize > m_size)  //调整后的大小>原大小时:
			{
				if (newSize > m_capacity) //(1)调整后的大小>容量时,需扩容
				{
					reserve(newSize * 2);
				}
				//将调整后相较于原大小多出的空间将其填充字符c,用memset进行初始化即可
				//memset(起始位置,字符c,size) :从起始位置开始初始化为字符c,共初始化size个大小
				memset(m_str + m_size, c, newSize - m_size);
			}
			m_size = newSize;
			m_str[m_size] = '\0';
		}
		char& operator[](int i)
		{
			assert(i < m_size && i >= 0);
			return m_str[i];
		}
		const char& operator[](int i)const
		{
			assert(i >= 0 && i < m_size);
			return m_str[i];
		}
		bool operator<(const string& s)
		{
			return (strcmp(m_str, s.m_str) < 0);
		}
		bool operator>(const string& s)
		{
			return (strcmp(m_str, s.m_str) > 0);
		}
		bool operator<=(const string& s)
		{
			return !(*this > s);
		}
		bool operator>=(const string& s)
		{
			return !(*this < s);
		}
		bool operator==(const string& s)
		{
			return (strcmp(m_str, s.m_str) == 0);
		}
		bool operator!=(const string& s)
		{
			return !(*this == s);
		}
	public:

		// 返回c在string中第一次出现的位置
		size_t find(char c, size_t pos = 0) const
		{
			for (size_t i = pos; i < m_size; i++)
			{
				if (m_str[i] == c)
				{
					return i;
				}
			}
			return npos;
		}
		// 返回子串s在string中第一次出现的位置
		size_t find(const char* s, size_t pos = 0) const
		{
			size_t i = pos, j = 0, s_len = strlen(s);
			while (i < m_size && j < s_len)
			{
				if (m_str[i] == s[j])
				{
					i++;
					j++;
				}
				else
				{
					i = i - j + 1; //回溯到查找的下一个位置
					j = 0;
				}
			}
			if (j >= s_len)
			{
				return i - j; //返回的是子串在主串中的第一个字符位置
			}
			return npos;
		}
		// 在pos位置上插入字符c/字符串str,并返回该字符的位置
		string& insert(size_t pos, char c)
		{
			if (m_size + 1 > m_capacity)
				reserve((m_size + 1) * 2);
			for (size_t i = m_size; i > pos; i--)
			{
				m_str[i] = m_str[i - 1];//右移
			}
			m_str[pos] = c;
			m_size = m_size + 1;
			m_str[m_size] = '\0';
			return *this;
		}
			// 删除从pos位置起的len个元素,并返回该元素的下一个位置
		string& erase(size_t pos, size_t len = 1)
		{
			for (size_t i = pos + len; i < m_size; i++)
			{
				m_str[i - len] = m_str[i]; //左移
			}
			m_size -= len;
			m_str[m_size] = '\0';
			return *this;
		}
	protected:
		static void _swap(string& s1, string& s2) //交换要用引用or指针!!!
		{
			std::swap(s1.m_str, s2.m_str);
			std::swap(s1.m_capacity, s2.m_capacity);
			std::swap(s1.m_size, s2.m_size);
		}

	private:
		char* m_str;
		int m_size;
		int m_capacity;
	};
	ostream& operator<<(ostream& out, const string& s)
	{
		out << s.m_str;
		return out;
	}
	istream& operator>>(istream& in, string& s)
	{
		static size_t default_buf_size = 5; //默认开辟大小为5的空间存放,当超过大小后自动增长
		int count = 0;//存入的字符数,
		int capacity = default_buf_size;
		char* str = (char*)malloc(sizeof(char) * capacity);
		char* buf = str;
		//getchar()获取一个字符,获取完会自动走向下一个、
		while((*buf = getchar()) == ' ' || *buf == '\n');//跳过最开始的空格和换行符
		for (;;)
		{
			if (*buf == ' ' || *buf == '\n')
			{
				*buf = '\0';
				break;
			}
			else if (count+1>= capacity)//当输入的字符数超过默认大小时,自动增长空间
			//由于先加加指针才存入内容,故当buf指针指向最后一个位置时,此时再想存入字符时,buf仍要先++,但此时越界
			//且当前count=capacity-1;所以当count+1>=capapcity时要扩容
			{
				capacity *= 2;
				str = (char*)realloc(str, capacity);//在str追加开辟capacity空间
				buf = str + count ;//重新定位buf位置
			}
			++buf;//先加加指针,
			*buf = getchar();//再存入字符
			count++;
		}
		s.m_capacity = capacity;
		s.m_size = count;
		delete[]s.m_str;
		s.m_str = str;
		return in;
	}
}
int main()
{
	bit::string s1;
	cout << "构造函数s1:" << s1 << endl;
	bit::string s2("C+");
	cout << "构造函数s2:" << s2 << endl;
	bit::string s3(s2);
	cout << "拷贝构造s3:";
	for (int i = 0; i < s3.size(); i++)
		cout << s3[i];
	cout << endl;
	const char* str = s3.c_str();

	bit::string s4;
	s4 = s3;
	cout << "赋值函数s4:" << s4 << endl;
	bit::string::iterator it = s4.begin();
	cout << "迭代器打印s4:";
	while (it != s4.end() - 1)
	{
		cout << *it;
		it++;
	}
	cout << endl;
	s4.clear();
	cout << "清理s4:" << s4 << endl;
	if (s4.empty())
	{
		cout << "s4为空" << endl;
	}
	else
	{
		cout << "s4不空" << endl;
	}
	s4.push_back('x');
	s4.push_back('t');
	s4.push_back('t');
	cout << "插入3个元素:" << s4 << "  s4.m_capacity:" << s4.capacity() << "  s4.m_size:" << s4.size() << endl;
	s4.reserve(5);
	cout << s4 << "  s4.m_capacity:" << s4.capacity() << "  s4.m_size:" << s4.size() << endl;
	s4.append("123");
	cout << "追加s4:" << s4 << "  s4.m_capacity:" << s4.capacity() << "  s4.m_size:" << s4.size() << endl;
	s4 += "56";
	cout << "+=(字符串) s4:" << s4 << "  s4.m_capacity:" << s4.capacity() << "  s4.m_size:" << s4.size() << endl;
	s4.resize(13, 'o');
	cout << "调整大小 s4:" << s4 << "  s4.m_capacity:" << s4.capacity() << "  s4.m_size:" << s4.size() << endl;
	bit::string s5 = ("helhlo");
	bit::string s6 = ("hellohel");
	if (s5 > s6)
		cout << "s5>s6" << endl;
	else if (s5 < s6)
		cout << "s5<s6" << endl;
	else
		cout << "s5==s6" << endl;
	size_t pos = s5.find('h', 1);
	cout << "查找字符 s5:" << pos << endl;
	size_t pos1 = s6.find("hel", 6);
	cout << "查找字符串(模式匹配) s6:" << pos1 << endl;
	bit::string s7 = "1234";
	cout << s7 << "  s7.m_capacity: " << s7.capacity() << "  s7.m_size:" << s7.size() << endl;
	s7.insert(0, '5');
	cout << "按位置插入1个字符 s7: " << s7 << "  s7.m_capacity: " << s7.capacity() << "  s7.m_size:" << s7.size() << endl;
	s7.erase(0, 2);
	cout << "按位置删除len个字符 s7: " << s7 << "  s7.m_capacity: " << s7.capacity() << "  s7.m_size:" << s7.size() << endl;
	bit::string s8;
	cin >> s8;
	cout <<"cin s8: "<< s8 << endl;
	return 0;
}


//=====================================================================================================================
//现代写法模拟string类
利用了临时对象的思想,进行原有空间的释放
/*class String
{
	friend ostream& operator<<(ostream& out, const String& s);
public:
	String(const char* s = "")
	{
		m_str = new char[strlen(s) + 1];
		strcpy(m_str, s);
	}
	String(const String &s):m_str(nullptr)//拷贝构造先把要拷贝的初始化
	{
		String tmp(s.m_str);
		//申请一个临时类空间,由字符串(要复制的类的字符串指针)构造类tmp,
		//然后把要复制的类内容与这个临时类内容交换,
		//拿到复制内容与临时类的地址,这是为了防止多次释放同一空间所造成运行崩溃
		std::swap(tmp.m_str, m_str);
	}
	String& operator=(const String s)
	{
		if (&s != this) //判断两个类是否相等,可判断首地址是否相等
		{
			String tmp(s);
			std::swap(tmp.m_str, m_str);
		}
		return *this;
	}
	~String()
	{
		if (m_str != nullptr)
		{
			delete[]m_str;
			m_str = nullptr;
		}
	}
private:
	char* m_str;
};
ostream& operator<<(ostream& out, const String& s)
{
	out << s.m_str;
	return out;
}
int main()
{
	String s1="123"; //由字符串创建对象,即用构造函数
	cout << s1 << endl;
	String s2("hello"); //由字符串创建对象,即用构造函数
	cout << s2 << endl;
	String s3(s2);     //调用拷贝构造创建对象
	cout << s3 << endl;
	String s4 = s3;   //调用拷贝构造创建对象
	cout << s4 << endl;
	String s5;
	s5 = s4; //调用赋值函数
	cout << s5 << endl;
	return 0;
}*/

//====================================================================================================================
//传统模拟string类
/*class String
{
public:
	friend ostream& operator<<(ostream &out,const String &s);
public:
	String(const char* str = " ")
	{
		m_str = new char[strlen(str) + 1];//加一加的是最后的/0
		strcpy(m_str, str);
	}
	String& operator=(String s)
	{
		if (this != &s)
		{
			char* p = new char[strlen(s.m_str) + 1];
			//重新申请一块空间复制s,这是为了防止浅赋值所造成的对一块空间多次释放的问题。
			strcpy(p, s.m_str);
			delete[]m_str;
			m_str = p;
		}
		return *this;
	}
	String(const String& s)
	{
		m_str = (new char[strlen(s.m_str) + 1]);
		strcpy(m_str, s.m_str);
	}
	~String()
	{
		delete[]m_str;
		m_str = nullptr;
	}
private:
	char* m_str;
};
ostream& operator<<(ostream& out, const String &s)
{
	out << s.m_str;
	return out;
}
int main()
{
	String s1="hello";
	cout << s1 << endl;
	String s2(s1);
	cout << s2 << endl;
	String s3=s2;
	cout << s3 << endl;
	return 0;
}*/

/*---------------------------------------------------------------------------------------------------------------------/*
int main()
{
	String str = "Hello Bit.";
	String::iterator it = str.begin();
	while (it != str.end())
	{
		if (*it != ' ')
			cout << *it;
		else
			str.erase(it);
		it++;
	}*/


	/*String strText = "How are you?";
	String strSeparator = " ";
	String strResult;
	int size_pos = 0;
	int size_prev_pos = 0;
	while ((size_pos = strText.find_first_of(strSeparator, size_pos)) != String::npos)
	{
		strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos);
		cout << strResult << " ";
		size_prev_pos = ++size_pos;
	}
	if (size_prev_pos != strText.size())
	{
		strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos);
		cout << strResult << " ";
	}
	cout << endl;*/

	/*String a = "hello world";
	String b = a;
	if (a.c_str() == b.c_str())
	{
		cout << "true" << endl;
	}
	else
		cout << "false" << endl;
	String c = b;
	c = "";
	if (a.c_str() == b.c_str())
	{
		cout << "true" << endl;
	}
	else
		cout << "false" << endl;
	a = "";
	if (a.c_str() == b.c_str())
	{
		cout << "true" << endl;
	}
	else
		cout << "false" << endl;
	return 0;
}*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值