C++第十九弹---string模拟实现(下)

avatar
作者
猴君
阅读量:1

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

目录

1、修改操作

2、迭代器操作

3、字符串操作 

4、非成员函数重载操作

总结


1、修改操作

1、string& operator+= (const char* s);

//尾部插入字符串s
2、string& operator+= (char c);

//尾部插入字符c
3、void push_back (char c);

//尾部插入字符c
4、string& append (const char* s);

//尾部插入(追加)字符串s
5、void insert(size_t pos, char ch);

//在pos位置插入字符c
6、void insert(size_t pos, const char* str);

//在pos位置插入字符串str
7、void erase(size_t pos, size_t len = npos);

//从pos位置删除n个字符
8、void swap(string& s);

//把字符串数据进行交换

void push_back(char c) { 	// 扩容 容量为0则固定为4 其他则*2 	if (_size == _capacity) 	{ 		reserve(_capacity == 0 ? 4 : 2 * _capacity); 	} 	_str[_size] = c;//_size下标插入字符c 	++_size;//将大小+1 	_str[_size] = '\0';//字符串最后位置给标志结束的\0 } void append(const char* s) { 	//追加字符串首先得判断空间是否足够 	size_t len = strlen(s); 	if (len > _capacity - _size)//空间不够则扩容 	{ 		reserve(_size + len);//大小为原大小+插入字符串长度 	}  	strcpy(_str + _size, s);//将要追加的数据拷贝到原数据尾 	_size += len;//更新字符串大小 } string& operator+=(char c) { 	push_back(c);//调用尾插字符函数  	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 : 2 * _capacity); 	} 	// end=_size会有无符号与有符号比较问题,因为pos恒大于等于0,end回到-1 	// 无符号与有符号比较 会提升至无符号比较 即end = -1 还会大于pos 	size_t end = _size + 1; 	while (end > pos)//end==pos则循环停止 	{ 		_str[end] = _str[end - 1];//将前面的元素往后面一个位置移动 		--end; 	} 	_str[pos] = ch;//pos位置赋值字符ch 	++_size;//更新大小 }  void insert(size_t pos, const char* str) { 	assert(pos <= _size);//pos小于字符串大小才能进行插入操作  	size_t len = strlen(str); 	if (len > _capacity - _size)//容量不够则扩容 	{ 		reserve(_size + len); 	} 	size_t end = _size + len; 	while (end > pos + len - 1) 	{ 		_str[end] = _str[end - len];//将原数据向后移动len位置 		--end; 	} 	strncpy(_str + pos, str, len);//不需要拷贝\0因此使用strncpy拷贝len长度到原串 	_size += len;//更新大小 } void erase(size_t pos, size_t len = npos) { 	assert(pos < _size);  	if (len == npos || len >= _size - pos)//长度为npos或者大于等于字符串大小-pos即删除整个字符串 	{ 		_str[pos] = '\0';//直接在pos位置给\0即可 		_size = pos;//pos为\0下标,刚还为字符串大小 	} 	else//将pos+len位置后的数据拷贝到pos为止 	{ 		strcpy(_str + pos, _str + pos + len); 		_size -= len;//更新长度 	} } void swap(string& s)//交换类的成员变量即可, { 	std::swap(_str, s._str);//调用库函数的swap模板函数 	std::swap(_size, s._size); 	std::swap(_capacity, s._capacity); }

2、迭代器操作

注意:暂时我们理解的迭代器实质为指针,但不完全是指针,此处就通过指针来模拟实现。

typedef char* iterator;//将迭代器定义成char*类型
typedef const char* const_iterator;将迭代器定义成const char*类型


1、const char* begin() const;

//获取指向首元素的const迭代器
2、const char* end() const;

//获取指向尾元素的const迭代器
3、char* begin();

//获取指向首元素的迭代器
4、char* end();

//获取指向尾元素的迭代器

typedef char* iterator; typedef const char* const_iterator;  const char* begin() const { 	return (const char*)_str;//返回首元素地址,const修饰因此强转类型 } const char* end() const { 	return (const char*)_str + _size;//尾元素下一个位置地址,即\0位置地址 } char* begin() { 	return _str; } char* end() { 	return _str + _size; }

3、字符串操作 

1、const char* c_str() const;

//获取C字符串首元素地址

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

//从pos位置(默认从0位置)找字符ch,找到则返回下标,否则返回npos
3、size_t find(const char* sub, size_t pos = 0) const;

//从字符串sub的pos位置找是否有匹配的字符串,找到则返回第一个元素下标,否则返回npos
4、string substr(size_t pos = 0, size_t len = npos);

//从pos位置截取len长度(默认截取整个字符串)的子串

const char* c_str() const { 	return _str;//返回首地址 } size_t find(char ch, size_t pos = 0) const { 	assert(pos < _size);//小于字符串大小才能进行查找 	for (size_t i = 0; i < _size; i++)//遍历字符串 	{ 		if (_str[i] == ch) 			return i;//找到字符则返回下标 	} 	return npos; } size_t find(const char* sub, size_t pos = 0) const { 	assert(pos < _size); 	const char* p = strstr(sub + pos, _str);//从sub+pos位置找,调用C语言库的找子串函数,找到则返回该值的地址,否则返回NULL 	if (p)//不为空则返回下标,指针相减即为相差个数,即下标 	{ 		return p - _str; 	} 	else//为空返回npos 	{ 		return npos; 	} } string substr(size_t pos = 0, size_t len = npos) { 	assert(pos < _size); 	string sub; 	if (len >= _size - pos)//长度大于_size-pos即将整个字符串截取,也包括len==npos 	{ 		for (size_t i = pos; i < _size; i++) 		{ 			sub += _str[i];//追加给sub 		} 	} 	else//否则截取len长度 	{ 		for (size_t i = pos; i < len + pos; i++) 		{ 			sub += _str[i]; 		} 	} 	return sub; }

4、非成员函数重载操作

1、void swap(string& s1, string& s2);

//将类s1数据与类s2数据交换
2、bool operator==(const string& s1, const string& s2);

//比较s1与s2是否相等
3、bool operator<(const string& s1, const string& s2);

//比较s1是否小于s2
4、ostream& operator<<(ostream& out, const string& s);

//流插入,即打印字符串s
5、istream& operator>>(istream& in, string& s);

//流提取,即将输入的内容给s
6、istream& getline(istream& in, string& s);

//获取一行信息,即将输入中回车之前的信息给s

void swap(string& s1, string& s2) { 	s1.swap(s2);//调用类成员交换函数,跟库函数中交换函数重载,先调用类成员函数 } bool operator==(const string& s1, const string& s2) { 	int ret = strcmp(s1.c_str(), s2.c_str());//调用C语言比较字符串函数,等于0则相等 	return ret == 0; } bool operator<(const string& s1, const string& s2) { 	int ret = strcmp(s1.c_str(), s2.c_str()); 	return ret < 0; }  ostream& operator<<(ostream& out, const string& s) { 	for (auto ch : s) 	{ 		out << ch;//用范围for变量类 	} 	return out; }  istream& operator>>(istream& in, string& s) { 	s.clear();//清空串s 	char ch = in.get();//C++库中输入函数,读取一个字符给ch 	char buff[128];//先开辟一个128字节空间,减少频繁扩容 	size_t i = 0; 	while (ch != '\n' && ch != ' ')//流提取不识别空格回车 	{ 		buff[i++] = ch;//将字符赋值给buff数组 		if (i == 127)//字符串满了则追加给串s 		{ 			buff[127] = '\0';//末尾追加标志符\0 			s += buff; 			i = 0;//再重新赋值字符给buff数组 		} 		ch = in.get(); 	} 	if (i > 0)//i>0则再追加数据给s 	{ 		buff[i] = '\0'; 		s += buff; 	} 	return in; } istream& getline(istream& in, string& s) { 	s.clear(); 	char ch = in.get(); 	char buff[128]; 	size_t i = 0; 	while (ch != '\n')//不识别回车,其他原理同流插入 	{ 		buff[i++] = ch; 		if (i == 127) 		{ 			buff[127] = '\0'; 			s += buff; 			i = 0; 		} 		ch = in.get(); 	} 	if (i > 0) 	{ 		buff[i] = '\0'; 		s += buff; 	} 	return in; }

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!