string模拟实现

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string.h>
#include<assert.h>
using namespace std;
namespace xyt
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		string()
			:
			_size (0)
			,_capacity(4)
			,_str (new char[_capacity+1])
		{
			_str[0] = '\0';
		}
		string(const string& str)
		{
			_size = str._size;
			_capacity = str._capacity;
			_str=new char[_capacity + 1];
			memcpy(_str, str._str,str._size);
			_str[_size] = '\0';
		}
		string(const char* s)
		{
			if (s == nullptr)
			{
				s = " ";
			}
			size_t len = strlen(s);
			_size = len;
			_capacity = len;
			_str = new char[_capacity + 1];
			strcpy(_str, s);
			_str[_size] = '\0';
		}
		~string()
		{
			delete [] _str;
			_str = nullptr;
		}
		void reserve(size_t newcapacity)
		{
			if (newcapacity > _capacity)
			{
				char* tmp = new char[newcapacity + 1];//扩容
				// 替代循环的等价写法
				memcpy(tmp, _str, _size + 1); // 拷贝 _size+1 个字节(包括末尾的 '\0')
				_capacity = newcapacity;
				delete[] _str;
				_str = tmp;
			}
		}
		void push_back(char c)
		{
			if (_size >= _capacity)
			{
				reserve(_capacity * 2);
			}
			_str[_size++] = c;
			_str[_size] = '\0';
		}
		void append(const char* s)
		{
			assert(s);
			if (s == " ")
			{
				return;
			}
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			strcpy(_str + _size, s);
			_size += len;
		}
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		const_iterator begin()const
		{
			return _str;
		}
		const_iterator end()const
		{
			return _str + _size;
		}
		char& operator[](size_t pos)
		{
			if (pos >= _size)
			{
				// 抛 out_of_range 异常,上层可捕获
				throw std::out_of_range("xyt::string::operator[]: pos out of range");
			}
			return _str[pos];
		}
		const char& operator[](size_t pos)const
		{
			if (pos >= _size)
			{
				// 抛 out_of_range 异常,上层可捕获
				throw std::out_of_range("xyt::string::operator[]: pos out of range");
			}
			return _str[pos];
		}
		size_t size()
		{
			return _size;
		}
		string& operator+= (const char* s)
		{
			append(s);
			return *this;
		}
		string& operator+= (char c)
		{
			push_back(c);
			return *this;
		}
		string& insert( size_t n, char c,size_t pos = npos )
		{
			if (pos >= _size || pos == npos)
			{
				for (size_t i = 0; i < n; i++)
				{
					push_back(c);
				}
			}
			else
			{
				if (n + _size > _capacity)
				{
					reserve(n + _size);
				}
				for (size_t i = n + _size; i > pos+n; i--)
				{
					_str[i] = _str[i - n];
				}
				for (size_t i = 0; i < n; i++)
				{
					_str[pos + i] = c;
				}
			}
			_size += n;
			return *this;
		}
		string& insert( const char* s, size_t pos=npos )
		{
			size_t len = strlen(s);
			if (pos >= _size || pos == npos)
			{
				append(s);
			}
			else
			{
				if (len + _size > _capacity)
				{
					reserve(len + _size);
				}
				for (size_t i = _size + len; i > pos + len; i--)
				{
					_str[i] = _str[i - len];
				}
				for (size_t i = 0; i < len; i++)
				{
					_str[pos + i] = s[i];
				}
			}
			_size += len;
			return *this;
		}
		string& erase(size_t pos = 0, size_t len = npos)
		{
			if (pos >= _size) {
				return *this;
			}
			if (len==npos ||pos + len >= _size)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else
			{
				for (size_t i = 0; i < _size - pos - len; i++)
				{
					_str[pos + i] = _str[pos + i + len];
				}
				_size -= len;
				_str[_size]='\0';
			}
			return *this;
		}
		size_t find(const string& str, size_t pos = 0) const
		{
			const char* sub_str = str._str;
			if (sub_str == nullptr)
			{
				sub_str = "";
			}
		    size_t len = strlen(sub_str);
			if (len == 0)
			{
				return (pos <= _size) ? pos : npos;
			}
			if (pos >= _size || pos + len > _size)
			{
				return npos;
			}
			for (size_t i = pos; i <= _size - len; i++)
			{
				int tmp = 0;
				for (size_t j = 0; j < len; j++)
				{
					if (_str[i + j] != sub_str[j])
					{
						tmp = 1;
						break; 
					}
				}
				if (tmp == 0)
				{
					return i;
				}
			}
			return npos;
		}
		string substr(size_t pos = 0, size_t len = npos)const
		{
			string str;

			// 1. 检查起始位置是否有效
			if (pos >= _size)
			{
				// 返回空字符串
				str._size = 0;
				str._capacity = 0;
				str._str = new char[1];
				str._str[0] = '\0'; 
				return str;
			}

			// 2. 计算实际长度
			size_t actual_len = len;
			if (len == npos || pos + len > _size)
			{
				actual_len = _size - pos;
			}

			// 3. 处理长度为0的情况
			if (actual_len == 0)
			{
				str._size = 0;
				str._capacity = 0;
				str._str = new char[1];
				str._str[0] = '\0';  // 修正:应该是 str._str
				return str;
			}

			// 4. 分配内存并复制
			str._size = actual_len;
			str._capacity = actual_len;
			str._str = new char[actual_len + 1];

			if (len == npos || pos + actual_len == _size)
			{
				// 情况1:复制到字符串末尾,可以用 strcpy
				strcpy(str._str, _str + pos);
			}
			else
			{
				// 情况2:复制指定长度,需要用 strncpy 并手动添加 \0
				strncpy(str._str, _str + pos, actual_len);
				str._str[actual_len] = '\0';  // 必须手动添加结束符
			}

			return str;
		}
		void swap(string& tmp)
		{
			std::swap(this->_capacity,tmp._capacity);
			std::swap(this->_size, tmp._size);
			std::swap(this->_str, tmp._str);
		}
		string& operator=(string tmp)//非常屌的写法
		{
			swap(tmp);
			return *this;
		}
		bool operator==(const string& s)
		{
			return _size == s._size ? (memcmp(_str, s._str, _size)) == 0 : false;
		}
		bool operator<(const string& s)
		{
			size_t _size1 = _size;
			if (_size > s._size)
			{
				_size1 = s._size;
			}
			if (memcmp(_str, s._str, _size1) < 0)
			{
				return true;
			}
			else if ((memcmp(_str, s._str, _size1) == 0) && s._size > _size)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		bool operator<=(const string& s)
		{
			return (*this == s) || (*this < s);
		}
		bool operator>(const string& s)
		{
			return !(*this <= s);
		}
		bool operator>=(const string& s)
		{
			return !(*this < s);
		}
		friend ostream& operator<<(ostream& out, const string& s);
		friend istream& operator>>(istream& in, string& s);
		void clear()
		{
			_size = 0;
			_str[0] = '\0';
		}
	private:
		size_t _size;
		size_t _capacity;
		char* _str;
	public:
		static size_t npos;
		
	};
	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.get();
		int i = 0;
		while (ch!=EOF&&(ch=='\t'||ch=='\r'||ch == ' ' || ch == '\n'))
		{
			ch = in.get();
		}
		char buff[128] = { '\0' };
		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			if (i == 127)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}
			ch = in.get();
		}
		if (i != 0)
		{
			buff[i] = '\0';
			s += buff;
		}
		return in;
	}
	size_t  xyt::string::npos = -1;
}

以上代码是string类的模拟实现,实现了string的最常用最基本的成员函数。

这里有一个点:string类的结束条件并不在于'\0',而是在于size的大小,所以,在遇到string的拷贝或扩容时,我们不能用strcpy或strncpy,因为这两个函数的结束条件都是遇到'\0'为之,所以,我们要使用memcpy。

相关推荐
FAFU_kyp2 小时前
RISC0_ZERO项目在macOs上生成链上证明避坑
开发语言·后端·学习·macos·rust
xuedingbue2 小时前
数据结构与顺序表:高效数据管理秘籍
数据结构·算法·链表
萧曵 丶2 小时前
JavaScript 函数各种写法和场景
开发语言·javascript·ecmascript
雪域迷影2 小时前
C++17中使用inline修饰类的静态成员变量
开发语言·c++·inline static·类静态成员变量
星火开发设计2 小时前
共用体 union:节省内存的特殊数据类型
java·开发语言·数据库·c++·算法·内存
求梦8202 小时前
【力扣hot100题】合并两个有序链表(22)
算法·leetcode·链表
仰望星空_Star2 小时前
Java证书操作
java·开发语言
女王大人万岁2 小时前
Go语言time库核心用法与实战避坑
服务器·开发语言·后端·golang
云游云记2 小时前
php Token 主流实现方案详解
开发语言·php·token