模拟实现string(v1)

Posted yumoz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟实现string(v1)相关的知识,希望对你有一定的参考价值。

string的模拟实现

1 先来介绍一下string

概述:string是C++标准库里面的一个重要部分,其主要工作是用于字符串处理。

2 常见用法

2.1 成员函数

具体实现原理详见此网站




3 模拟实现

class类的定义:

class string

public:
	//具体函数实现,见下面部分给出
	
	static const size_t npos;//类外定义
private:
	char* _str;
	size_t _size;
	size_t _capacity;//存储有效字符
;
const size_t string::npos = -1;

3.1 基础接口实现

构造函数+拷贝构造函数+析构函数+赋值构造函数

		//        基础接口
		//构造函数
		string(const char* str = "")
		
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		

		//现代写法的swap成员函数 简化程序代码
		void swap(string& s)
		
			/*std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);*/

			//域作用限定符,全局域
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		

		//s2(s1)拷贝构造
		string(const string &s)
			:_str(nullptr)
			, _capacity(0)
			, _size(0)
		
			string temp(s._str);
			// 多个交换
			/*swap(_str, temp._str);
			swap(_size, temp._size);
			swap(_capacity, temp._capacity);*/

			// 隐含 this->swap(temp);
			swap(temp);//就近原则,使用的是局部的swap,当前类域找
		

		string& operator=(string s)
		
			/*swap(_str, s._str);
			swap(_size, s._size);
			swap(_capacity, s._capacity);*/
			swap(s);

			return *this;
		

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

3.2 迭代器

//          迭代器
		typedef char* iterator;
		typedef const char* const_itertor;

		iterator begin()
		
			return _str;
		
		iterator end()
		
			return _str + _size; //end位置是\\0位置
		
		const iterator begin() const
		
			return _str;
		
		const iterator end() const
		
			return _str + _size;
		

3.3 operator[]实现

		// &保证了 可读可写,出了作用域对象还在
		char& operator[](size_t i) 
		
			assert(i < _size);//防止越界
			return _str[i];
		

		//只能读
		const char& operator[](size_t i) const
		
			assert(i < _size);
			return _str[i];
		

3.4 容量部分实现

此部分主要实现的是size,capacity,判断是否为空,reserve,resize接口
这里主要分析reserve接口和resize接口:

// capacity
		size_t size()
		
			return _size;
		
		size_t size() const
		
			return _size;
		
		size_t capacity()const
		
			return _capacity;
		
		bool empty()const
		
			return _size == 0;
		
		//开空间 改变容量
		void reserve(size_t n)
		
			if (n > _capacity)
			
				char* temp = new char[n + 1];
				//strcpy(temp, _str);
				strncpy(temp, _str,_size+1);
				delete[]_str;

				_str = temp;
				_capacity = n;
			
		

		//开空间,初始化,缩小,size也变换
		void resize(size_t n, char ch = '\\0')
		
			//空间足
			if (n < _size)
			
				//缩小,插入\\0,迫使其在n的位置终止
				_str[n] = '\\0';
				_size = n;
			
			else
			
				//容量不够,扩容
				if (n > _capacity)
				
					reserve(n);
				
				// n<capacity 
				for (size_t i = _size; i < n; ++i)
				
					_str[i] = ch;//插入字符
				
				_str[n] = '\\0';//末尾为结束标志
				_size = n;//记录容量
			
		

3.5 扩容(insert、push_back、append、+=)

首先分析如何insert一个字符:

其次,再次分析如何insert一个字符串:


string&  insert(size_t pos, char ch)
		
			assert(pos <= _size);
			//容量已满
			if (_size == _capacity)
			
				size_t newcapacity = _capacity == 0 ? 16 : _capacity * 2;
				reserve(newcapacity);//扩容
			

			//移动pos位置及之后字符
			//写法一 不推荐
			/*	int end = _size;
			while (end >= (int)pos) // 避免0 - 1加(int)
			
				_str[end+1] = _str[end];
				--end;
			
			_str[pos] = ch;
			_size++;

			return *this;
			*/

			//写法二 推荐
			int end = _size + 1;
			while (end > pos)
			
				_str[end] = _str[end - 1];
				--end;
			
				
			//写法3 someproblem
			/*char* end = _str + _size;
			while (end >= _str + pos)
			
				*(end + 1) = *end;
				--end;
			*/

			_str[pos] = ch;
			_size++;

			return *this;
		

		//pos位置之前 insert 字符串
		void insert(size_t pos, const char* str)
		
			assert(pos <= _size);
			size_t len = strlen(str);
			if (_size + len > _capacity)
			
				reserve(_size + len);
			

			//空间足 挪动  *****分析界限问题*****
			//分析实现办法 一
			/*	size_t end = _size + len;
			while (end >= (int)(pos + len))
			
			_str[end] = _str[end - len];
			--end;
			*/

			//实现办法 二
			/*	cout << "size: " << _size << endl;
			cout << "_str[4]: " << _str[4] << endl;
			cout << "_str[8]: " << _str[8] << endl;*/
			size_t end = _size + len + 1;
			//cout << "end:" << end << endl;
			while (end > pos + len)
			
				_str[end - 1] = _str[end - len - 1];//先从结束\\0 开始向后移动
				--end;
			
			//cout << "end: "<< end << endl;

			//指针办法解决
			/*char*end = _str + _size;
			while (end >= _str + pos)
			
				*(end + len) = *end;
				--end;
			*/			
			strncpy(_str + pos, str, len);
			_size += len;
		

		//*****************************
		//修改 
		void push_back(char ch)
		
			//if (_size == _capacity)
			//
			//	//扩容
			//	reserve(2 * _capacity);
			//
			//_str[_size] = ch;
			//++_size;
			//_str[_size] = '\\0';//保证字符串终止

			insert(_size, ch);
		
		void append(const char* str)
		
			//size_t len = _size + strlen(str);
			//if (len > _capacity)
			//
			//	//扩容
			//	reserve(len);
			//

			//strcpy(_str + _size, str);
			//_size = len;
			insert(_size, str);
		

		//this 指针处理 
		string&  operator+=(char ch)
		
			push_back(ch);
			return *this;//深拷贝
		

		//+= 字符串
		string&  operator+=(const  char*  str)
		
			append(str);
			return *this;//深拷贝
		

3.6 清理

		void clear()
		
			_size = 0;
			_str[_size] = '\\0';
		
		
		void erase(size_t pos, size_t len = npos)
		
			assert(pos < _size);
			//删完、删的len超过_size
			if (len == npos || pos+len >= _size)
			
				_str[pos] = '\\0';//直接设为字符串终止
				_size = pos;//修改大小
			
			else//删除一小段
			
				strcpy(_str + pos, _str + pos + len);//字符串向前覆盖移动
				_size -= len;
			

		

		//找一个字符
		size_t find(char ch, size_t pos = 0)
		
			for (size_t i = pos; i < _size; ++i)
			
				if (_str[i] == ch)
				
					return i;
				
			
			return npos;
		

		//找一个字符串
		size_t find(const char* sub, size_t pos = 0)
		
			const char* ret = strstr(_str + pos, sub);
			if (ret == nullptr)
			
				return npos;
			
			else
			
				return ret - _str;
			
		

3.7 关系运算

类内实现:

// 类内实现关系运算
		//relational operators
		bool operator<(const string& s)const
		
			int res = strcmp(_str, s._str);
			if (res < 0)
				return true;
			return false;
		
		bool operator<=(const string& s)const
		
			return !(*this > s);
		
		bool operator>(const string& s)const
		
			int res = strcmp(_str, s._str);
			if (res > 0)
				return true;
			return false;
		
		bool operator>=(const string& s)const
		
			return !(*this < s);
		
		bool operator==(const string& s)const
		
			int res = strcmp(_str, s._str);
			if (res == 0)
				return true;
			return false;
		
		bool operator!=(const string& s)const
		
			return !(*this == s);
		

类外实现:

实现办法一:利用strcmp函数实现

bool operator ==(const string&s1, string &s2)
	
		return strcmp(s1.c_str(), s2.c_str()) == 0;
	
	bool operator !=(const string&s1, string &s2)
	
		return !(s1 == s2);
	
	bool operator <(const string&s1, string &s2)
	
		return strcmp(s1.c_str(), s2.c_str()) < 0;
	

	bool operator <=(const string&s1, string &s2)
	
		return s1<s2 || s1 == s2;
	

	bool operator >(const string&s1, string &s2)
	
		return !(s1 <= s2);
	

	bool operator >=(const string&s1, string &s2)
	
		return !(s1 < s2);
	

实现办法二:自己模拟实现比大小

bool operator>(const string&s1, const string&s2)
	
		size_t i1 = 0, i2 = 0;
		while (i1 < s1.size() && i2 < s2.size())
		
			if (s1[i1] > s2[i2])
			
				return true;
			
			else if (s1[i1] < s2[i2])
			
				return false;
			
			else
			
				++i1;
				++i2;
			
		

		if (i1 < s1.size())
		
			return true;
		
		else if (i2<s2.size())
		
			return false;
		
		else
		
			return false;
		
	

	bool operator==(const string& s1, const string& s2)
	
		size_t i1 = 0, i2 = 0;
		while (i1 < s1.size() && i2 < s2.size())
		
			if (s1[i1] > s2[i2])
			
				return false;
			
			else if (s1[i1] < s2[i2])
			
				return false;
			
			else
			
				++i1;
				++i2;
			
		

		if (i1 == s1.size() && i2 == s2.size())
		
			return true;
		
		else
		
			return false;
		
	

3.8 流运算(>>,<<,getline)

ostream& operator<<(ostream& out, const string& s)
	
		//方法一 :范围for解决
		for (auto ch : s)
		
			out << ch;
		

		//方法二
		/*for (size_t i = 0; i < s.size(); ++i)
		
			out << s[i];
		*/
		return out;
	

	istream& operator>>(istream& in, string&s)
	
		s.clear();
		//s.resize(0);//清理 == clear
		char ch;
		ch = in.get();
		while (ch != ' ' && ch != '\\n')
		
			s += ch;
			//in>>ch;
			in.get(ch); //获取
		
		return in;
	

	//Getline 操作
	istream& getline(istream& in, string& s)
	
		s.clear();
		//s.resize(0);//清理 == clear
		char ch;
		ch = in.get();
		while (ch != '\\n')
		
			s += ch;
			//in>>ch;
			in.get(ch); //获取
		
		return in;
	

4 总结

整体实

以上是关于模拟实现string(v1)的主要内容,如果未能解决你的问题,请参考以下文章

开源1句代码搞定图片批量上传,无需什么代码功底无语言界限

CodeForce-797C Minimal string(贪心模拟)

Linux:TCP粘包问题的模拟实现以及解决方法

Linux:TCP粘包问题的模拟实现以及解决方法

在 std::string 末尾附近插入换行符 [重复]

C++STL第一篇:string类介绍及模拟实现