String类的模拟实现和思路

本文详细介绍了如何模拟C++中的String类,包括成员变量的设计、构造函数、析构函数、拷贝构造、赋值拷贝、迭代器实现以及各种运算符重载和成员方法,如size(),capacity(),和字符串操作等。
摘要由CSDN通过智能技术生成


模拟String类所需的成员变量

class string
{
public:
//实现string类的四种默认构造函数
//1.构造函数
string(char* str="")
:_size(strlen(str))
,_capacity(_size+1)//_capacity空间至少要比_size大一个用来存放‘/0’
{
	_str=new char[_capacity+1];//这里大一点无所谓滴
	strcpy(_str,str);//将str指向内容拷贝到_str中去
}

//2.析构函数
~string()
{
	//delete清理_str指向的空间并让_str指向空
	delete[] _str;
	_str=nullptr;
	//把_size和_capacity置0,因为这两是空间属性
	_size=_capacity=0;
}

//3.拷贝构造
//拷贝构造各有各的写法,我这里仅代表个人写法和思路
string(const string& s)
:_str(nullptr)
,_size(0)
,_capacity(0)
{
	//复用一下构造函数,用s的_str构造一个对象
	string tmp(s._str);
	swap(tmp);
	//可以发现tmp因为是临时构造,最终会在拷贝构造作用域结束析构
	//我们在tmp析构之前将它的成员变量交换给this指向的对象,完成拷贝构造
	//现在再回头看看我们的初始化列表,交换后的tmp因为指向nullptr,析构也不会产生野指针问题
}
void swap(string& s)
{
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

//4.赋值拷贝
string& operator=(const string tmp)
{
	//赋值拷贝也可以复用一下拷贝构造
	//在传值时,就将要拷贝对象传给临时对象tmp
	
	//交换一下this和tmp成员变量完成交换
	swap(tmp);
	return *this;
}
private:
	//string的本质就是一串字符串
	char* _str;
	//记录这个字符串的最大空间
	size_t _capacity;
	//记录这个字符串大小
	size_t _size;
};

string类的迭代器

class string
{
public:
typedef char* iterator;
typedef const char* const_iterator;

iterator begin()
{
	//_str指向一个字符串,但是*(_str)是字符串的第一个字符
	return _str;
}

iterator end()
{
	//返回的是字符串最后一个字符的位置的后一个位置,即'/0'的位置
	return _str+size();
}

//因为const对象只能调用const迭代器,所以要再写一遍const迭代器
const_iterator begin() const
{
	//const迭代器表示指向的内容不能发生修改
	return _str;
}

const_iterator end() const
{
	return _str+size();
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
//具体实现请结合构造函数代码
void test()
{
	s("halo shijie");
	string::iterator it=s.begin();
	while(it!=s.begin())
	{
		cout<<*it<<" ";
	}
	//或者
	for(auto e:s)
	{
		cout<<e<<" ";
	}
}

string类的运算符重载

class string
{
public:
char& operator[](size_t pos)
{
	//检查越界
	assert(pos<size());
	return *(_str+pos);
	//或者复用自定义类型如:
	//return _str[pos];
}
bool operator<(const string& s)
        {
            return strcmp(_str, s._str) < 0;
        }

        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);
        }

        bool operator==(const string& s)
        {
            return strcmp(_str, s._str) == 0;
        }

        bool operator!=(const string& s) {
            return !(*this == s);
        }
//写到这儿就要想到其实调用'[]'的可能也有const对象
const char& operator[](size_t pos)
{
	assert(pos<size());
	return *(_str+pos);
	//或者复用自定义类型如:
	//return _str[pos];
}
private:
char* _str;
size_t _size;
size_t _capacity;
}

string类的一些成员方法和接口

class string
{
public:
size_t size()
{
	return _size;
}
size_t capacity()
{
	return _capacity();
}
const char* c_str() const
{
	return _str;
}
//扩容
void reserve(size_t n)
{
	//判断n是否大于capacity 大则扩
	if(n>_capacity)
	{
		//购买新房
		char *tmp=new char[n];
		//转移家具
		strcpy(tmp,_str);
		delete[] _str;
		//搬入新家
		_str=tmp;

		_capacity=n;
	}
}


void resize(size_t n,char ch='\0')
{
	if(n<size())
	{
		_str[n]='\0';
		_size=n;
	}
	else
	{
		reserve(n);
		while(_size<n)
		{
			_str[_size]=ch;
			_size++;
		}
		_str[_size]='\0';
	}
}

size_t find(char ch,size_t pos=0)
{
	assert(pos<size());
	while(pos<size())
	{
		if(ch==_str[pos])
		{
			return pos;
		}
		pos++;
	}
	return npos;
}

//查找子串
size_t find(char* str,size_t pos=0)
{
	assert(pos<size());
	//复用strstr
	const char* p=strstr(_str+pos,str);
	if(p)
	{
		return p-_str;
	}
	else
	{
		return npos;
	}
}

//粘接字符串
string substr(size_t pos,size_t len=npos)
{
	string s;
	//如果len过长,调整len长度
	if(len==npos || pos+len>=_size)
	{
		//有多少取夺少
		for(size_t i=pos;i<_size;i++)
		{
			s+=_str[i];
		}
	}
	else
	{
		int i=pos;
		while(i<pos+len)
		{
			s+=_str[i++];
		}
		return s;
	}
}
void push_back(char ch)
{
	if (_size == _capacity)
		{
			reserve(_capacity == 0 ? 4 : _capacity * 2);
		}

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

void append(const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}

	strcpy(_str + _size, str);
	_size += len;
}

string& operator+=(char ch)
{
	push_back(ch);
	return *this;
}

string& operator+=(const char* str)
{
	append(str);
	return *this;
}
void insert(size_t pos, char ch)
{
	assert(pos <= _size);
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}

			
	size_t end = _size + 1;
	while (end > pos)
	{
		_str[end] = _str[end - 1];
		--end;
	}

	_str[pos] = ch;
	_size++;
}
 string& insert(size_t pos, const char* str)
        {
            assert(pos < _size);
            size_t len = strlen(str);
            if (_size +len  > _capacity)
            {
                reserve(_size + len);
            }
            int end = _size;
            while (end >= (int)pos)
            {
                _str[end + len] = _str[end];
                --end;
            }

            strncpy(_str + pos, str, len);
            _size += len;
        }



        // 删除pos位置上的元素,并返回该元素的下一个位置

        string& erase(size_t pos, size_t len)
        {
            assert(pos < _size);

            if (len == npos || pos + len >= _size)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                size_t begin = pos + len;
                while (begin <= _size)
                {
                    _str[begin - len] = _str[begin];
                    ++begin;
                }
                _size -= len;
            }
        }
        
private:
char* _str;
size_t _size;
size_t _capacity;
};
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值