【C++ —— string的模拟实现】

string.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<string.h>
#include<assert.h>
using namespace std;




namespace goat
{
	
	//#define NUMS 16
	//char* Buffer[NUMS];
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;



		//迭代器
		iterator begin();

		iterator end();//最后一个数据下一个位置

		void Printf();

		const_iterator begin() const
		{
			return _str;
		}
		const_iterator end() const
		{
			return _str + _size;
		}
		//构造函数
		//无参
	
		//string()
		//	:_str(new char[1])//char*类型解引用遇到\0才会中止,所以这里不能直接给空指针,这里要给nullptr空指针会直接报错
		//	,_size(0)
		//	,_capacity(0)
		//{
		//	_str[0] = '\0';
		//}


		//有参

		//浅拷贝
		string(const char* str = "");//缺省值为\0因为空字符串默认结尾带\0,所以只有一个空间


		//深拷贝
		//1.
		string(const string& str);
		//2.
		//string(const string& str)
		//{
		//	string tmp(str);
		//	swap(tmp);

		//}


		
		//析构
		~string();

		//clear清理
		void clear();
		
		//[]重载和cons[]重载
		char& operator[](size_t pos);
		char& operator[](size_t pos) const;



		//获取私有成员变量
		size_t size() const;
		size_t capacity() const;
		const char* c_str();
		//resize和reserve
		void reserve(size_t n);
		void resize(size_t n);//没给字符就填空字符\0
		void resize(size_t n, char ch);
		

		//字符插入
		void push_back(char ch);
		void append(const char* ch);
		void append(size_t pos, const char* ch);
		string& insert(size_t pos, char ch);
		string& insert(size_t pos, const char* ch);
		
		

		//字符删除
		void erase(size_t pos, size_t len = npos);

		//swap交换
		void swap(string& str);



		//赋值重载
		//s1 = s2
		string& operator=( string str)
		{
			swap(str);
			return *this;
		}
		
		




		//运算符重载
		string& operator+=(char str)
		{
			push_back(str);
			return *this;
		}

		string& operator+=(const char* str)
		{
			append(str);
			return *this;
		}

		string& operator+=(const string& str)
		{
			append(str._str);
			return *this;
		}
		bool operator <(const string& str1) const
		{
			return strcmp(_str, str1._str) < 0;
		}
		bool operator ==(const string& str1) const
		{
			return strcmp(_str, str1._str) == 0;
		}

		//先实现小于和等于,后面就可以直接复用小于等于函数
		bool operator <=(const string& str1) const
		{
			return *this < str1 || *this == str1;
		}
		bool operator >(const string& str1) const
		{
			return !(*this <= str1);
		}
		bool operator >=(const string& str1) const
		{
			return !(*this < str1);
		}
		bool operator !=(const string& str1) const
		{
			return !(*this == str1);
		}

		size_t find(char ch, size_t pos = 0);
		size_t find(const char* ch, size_t pos = 0);

		//截取字符串
		string substr(size_t pos, size_t len = npos);
		
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	public:
		const static size_t npos = -1;

	};
	//const size_t string::npos = ;

	ostream& operator<<(ostream& out, const string& s);
	istream& operator>>(istream& in, string& s);
	istream& getline(istream& is, string& str);
}

string.cpp

#include"string.h"


//迭代器实现
goat::string::iterator goat::string::begin()
{
	return _str;
}
goat::string::iterator goat::string::end()//指向最后一个数据下一个位置
{
	return _str + _size;
}

goat::string::const_iterator goat::string::begin() const
{
	return _str;
}
goat::string::const_iterator goat::string::end() const
{
	return _str + _size;
}




void goat::string::Printf()
{
	std::cout << c_str() << std::endl;
	std::cout << std::endl;
}

//构造
//浅拷贝
goat::string::string(const char* str = "")//缺省值为\0因为空字符串默认结尾带\0,所以只有一个空间_size(strlen(str))
	, _capacity(_size)//不带\0
{
	_str = new char[_capacity + 1];
	strcpy(_str, str);
}
//深拷贝
goat::string::string(const string& str)
{
	_str = new char[str._capacity + 1];
	strcpy(_str, str._str);
	_size = str._size;
	_capacity = str._capacity;

}

//析构
goat::string::~string()
{
	delete[] _str;
	_str = nullptr;
	_capacity = _size = 0;
}
//清理
void goat::string::clear()
{
	_str[0] = '\0';
	_size = 0;


}
//[]重载和cons[]重载
char& goat::string::operator[](size_t pos)
{
	assert(pos < _size);

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

	return _str[pos];
}

//获取私有成员变量
size_t goat::string::size() const
{
	return _size;
}
size_t goat::string::capacity() const
{
	return _capacity;
}
const char* goat::string::c_str()
{
	return _str;
}


//resize和热serve
void goat::string::reserve(size_t n)
{
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];//可以存n个字符,多开一个空间留给\0
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;

		_capacity = n;

	}
}
void goat::string::resize(size_t n)//没给字符就填空字符\0
{
	if (n <= _size)
	{
		_str[n] = '\0';
		_size = n;
	}
	else
	{
		reserve(n);
		while (_size < n)
		{
			_str[_size] = '\0';
			++_size;
		}
		_str[_size] = '\0';
	}

}
void goat::string::resize(size_t n, char ch)
{
	if (n <= _size)
	{
		_str[n] = '\0';
		_size = n;
	}
	else
	{
		reserve(n);
		while (_size < n)
		{
			_str[_size] = ch;//ch有可能是\0有可能不是
			++_size;
		}
		_str[_size] = '\0';
	}
}

void goat::string::push_back(char ch)
{
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
		//reserve(_capacity * 2);

	}
	_str[_size] = ch;
	++_size;
	_str[_size] = '\0';
}

void goat::string::append(const char* ch)
{
	size_t size = strlen(ch);
	if (_size + size > _capacity)
	{
		reserve(_size + size);


	}
	strcpy(_str + _size, ch);//strcpy也会拷贝'\0'
	_size += size;
}

void goat::string::append(size_t pos, const char* ch)
{
	assert(pos < _size);

	size_t size = strlen(ch);
	if (_size + size > _capacity)
	{
		reserve(_size + size);


	}
	strcpy(_str + _size, ch);//strcpy也会拷贝'\0'
	_size += size;
}

goat::string& goat::string::insert(size_t pos, char ch)
{
	assert(pos <= _size);

	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);

	}
	//当pos为0时end<0才会结束,这里当pos为-1时“(int)end >= (size_t)pos”会发生整形提升end转换成size_t类型

	//方法一:强转避免提升
	// 
	// size_t end = _size;
	//while (end >= (int)pos)
	//{
	//	_str[end + 1] = _str[end];
	//	--end;
	//}
	//_str[pos] = ch;
	//++_size;

	//方法二:
	size_t end = _size + 1;
	while (end > pos)
	{
		_str[end] = _str[end - 1];
		--end;
	}
	_str[pos] = ch;
	++_size;
	return *this;

}

goat::string& goat::string::insert(size_t pos, const char* ch)
{
	assert(pos <= _size);
	size_t len = strlen(ch);
	reserve(_size + len);
	size_t end = _size + len + 1;
	while (end < pos)
	{
		_str[end] = _str[end - len];
		--end;
	}

	//插入方法一
	strncpy(_str + pos, ch, len);

	//方法二
	//size_t j = 0;
	//for (size_t i = pos; i < pos + len; i++)
	//{
	//	_str[pos] = ch[j];
	//	j++;
	//}

	_size += len;
	_str[_size] = '\0';

	return *this;

}


//字符删除
void goat::string::erase(size_t pos, size_t len = npos)
{
	assert(pos < _size);

	if (len == npos || len + pos >= _size)
	{
		_str[_size] = '\0';
		_size = pos;
	}
	else
	{
		strcpy(_str + pos, _str + pos + len);
		_size -= len;

	}
}

//swap交换
void goat::string::swap(string& str)
{
	std::swap(_str, str._str);
	std::swap(_size, str._size);
	std::swap(_capacity, str._capacity);
}


//赋值重载
//s1 = s2
//方法一
goat::string& goat::string::operator=(string str)
{
	swap(str);
	return *this;
}

//方法二
/*string& operator=(const string& str)
{
	if (this != &str)
	{
		char* tmp = new char[str._capacity + 1];
		strcpy(tmp, str._str);
		delete[] _str;
		_str = tmp;
		_size = str._size;
		_capacity = str._capacity;


	}
	return *this;

}*/
/*string& operator=(const string& s)
{
	char* tmp = new char[s._capacity + 1];
	strcpy(tmp, s._str);
	delete[] _str;
	_str = tmp;
	_size = s._size;
	_capacity = s._capacity;

	return *this;
}*/


//查找
size_t goat::string::find(char ch, size_t pos = 0)
{
	assert(pos < _size);
	for (size_t i = pos; i < _size; i++)
	{
		if (_str[i] == ch)
		{
			return i;
		}
	}
	return npos;
}
size_t find(const char* ch, size_t pos = 0)
{
	const char* p = strstr(_str, ch);//没找到返回NULL
	if (p)
	{
		return p - _str;
	}
	else
	{
		return npos;
	}

	return npos;
}
goat::string goat::string::substr(size_t pos, size_t len = npos)
{
	string s;
	size_t end = pos + _size;
	if (len == npos || pos + len >= _size)//有多少取多少
	{
		len = _size - pos;
		s.reserve(len);
		for (size_t i = pos; i < end; i++)
		{
			s += _str[i];
		}
	}
	else
	{
		for (size_t i = pos; i < _size + len; i++)
		{
			s += _str[i];
		}
	}
	return s;
}
ostream& goat::operator<<(ostream& out, const string& s)
{
	/*for (size_t i = 0; i < s.size(); i++)
	{
		out << s[i];
	}*/

	for (auto ch : s)
	{
		out << ch;
	}
	return out;
}
istream& goat::operator>>(istream& in, string& s)
{
	//char ch;
	//in >> ch;//流提取遇到空格和换行结束,但是这边cin拿不到空格——scanf和cin把空格和换行作为分隔符所以拿不到
	//while (ch != ' ' && ch != '\n')
	//{
	//	s += ch;
	//	in >> ch;
	//}
	s.clear();
	char ch;
	ch = in.get();//get时,这时就不管是什么字符都会一个一个拿
	while (ch != ' ' && ch != '\n')
	{

		s += ch;
		//in >> ch;
		ch = in.get();
	}
	return in;

}
istream& goat::getline(istream& is, string& str)
{
	str.clear();
	char ch;
	ch = in.get();
	char buff[128];
	size_t i = 0;
	while (ch != '\0')
	{
		buff[i++] = ch;
		if (i == 127)//当buff缓冲区满时,写入数据
		{
			buff[127] = '\0';
			str += buff;
			i = 0;
		}
		ch = in.get();

	}

	if (i > 0)//循环完后buff缓冲区还有数据,补上
	{
		buff[i] = '\0';
		str += buff;
	}
	return in;

}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值