String类的功能模拟实现

string类的学习目的

在字符串OJ中,为了简单、方便、快捷,基本都使用string类。

string类的一些特性

  1. string是表示字符串的字符串类

  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>
    string;

     basic_string是一个模板类,它接受三个参数:char表示字符类型,char_traits表示字符特性,allocator表示内存分配器。通过这三个参数的组合,我们可以实例化出不同类型的字符串类。
    
     这句代码总而言之就是将basic_string<char, char_traits, allocator>定义为string类型的别名,这样在后续的代码中,我们就可以直接使用string来表示这个特定的字符串类型,而无需再写出完整的模板参数列表。
    
  4. 不能操作多字节或者变长字符的序列。
    在使用string类时,必须包含#include头文件以及using namespace std;

string类的常用接口

1.string类对象的常见构造,模拟实现

	class string
	{
	public:
		//构造函数
		//为了使得private中的char* _str能够不使用const,写出构造函数,在初始化中
		//如果我们使用直接赋值,如主函数中为string s1; 构造函数中是_str = str;那么就
		//会出现权限放大的现象,即将const变量赋值给普通变量,这是不允许的,故我们在初始
		//化列表中进行开空间,以及拷贝字符串,避免了直接赋值权限放大的情况
		string(const char* str = "")
			: _size(strlen(str))
		{
			_capacity = _size== 0 ? 3 : _size;
			_str = new char[_capacity + 1];
			strcpy_s(_str, _capacity + 1, str);
		}
		
		//拷贝构造函数
		string(const string& s)
			:_size(s._size)
			, _capacity(s._capacity)
		{
			_str = new char[s._capacity + 1];
			strcpy_s(_str, s._capacity + 1, s._str);
		}
		
	private:
		char* _str;
		size_t _size;
		size_t _capacity;

	};

2. string类对象的容量操作,模拟实现

//对字符串空间进行扩容操作

void reserve(size_t n)
{
	//防止缩容
	if(n > _capacity)
	{
		char* tmp = new char[n + 1];//开辟新空间
		strcpy_s(tmp, n + 1, _str);//将旧空间的字符串赋值到新空间
		delete[] _str;//删除旧空间内容,释放旧空间
		_str = tmp;//将指向旧空间的指针重新指向新的空间
	
		_capacity = n;//将新的空间的大小给_capacity变量
	}

}

3. string类对象的访问及遍历操作,模拟实现

//对字符串进行访问对应位置数据
//有以下几种方法
1.operator[]运算符重载:返回pos位置的字符,const string类对象调用

//非const变量调用
char& operator[](size_t pos)
{
	assert(pos < _size);
	return _str[pos];
}

//const变量调用
const char& operator[](size_t pos) const
{
	assert(pos < _size);
	return _str[pos];
}

2.iterator迭代器访问对应位置字符:begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭
代器
typedef char* iterator;
typedef const char* const_iterator;

iterator begin()
{
	return _str;
}

iterator end()
{
	return _str + _size;
}

iterator begin() const 
{
	return _str;
}

iterator end() const
{
	return _str + _size;
}

//在主函数中可以这样来遍历字符串
int main()
{
	string s1("hello world");
	string::iterator it = s1.begin();
	while(it != s1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}
3.范围for
//底层实现就是iterator迭代器
//接着上面的main函数,可以这样使用
for(auto ch : s1)
{
	cout << ch << " ";	
}
cout << endl;

4.string类对象的修改操作,模拟实现

//在字符串后尾插字符c
void push_back(char ch)
{
	if(_size + 1 > _capacity)//扩容操作
	{
		reserve(_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_s(_str + _size, _capacity - _size, str);
	_size += len;
}

//运算符重载+=
//后面加字符
string& operator+=(char ch)
{
	push_back(ch);
	return *this;
}

//后面加字符串
string& operator+=(const char* str)
{
	append(str);
	return *this;
}

5.string类对象的比较操作,模拟实现

//不改变的变量最好加上const
bool operator>(const string&s) const
{
	return strcmp(_str, s._str)>0;
}

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

//复用操作
bool operator>=(const string& s) const
{
	return *this > s || *this == s;
}

bool operator<(const string& s) const
{
	return !(*this >= s);
}

bool operator<=(const string& s) const
{
	return !(*this > s);
}

bool operator!=(const string& s) const
{
	return !(*this == s);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值