string类对象的访问及遍历操作

举报
跳动的bit 发表于 2022/06/12 07:57:13 2022/06/12
【摘要】 3、string类对象的访问及遍历操作函数名称功能说明operator[] —— 重点返回 pos 位置的字符,const string 类对象调用begin + endbegin 获取一个字符的迭代器,end 获取最后一个字符下一个位置的迭代器rbegin + rendbegin 获取一个字符的迭代器,end 获取最后一个字符下一个位置的迭代器范围 forC++11 支持更简洁的范围 f...
3、string类对象的访问及遍历操作
函数名称 功能说明
operator[] —— 重点 返回 pos 位置的字符,const string 类对象调用
begin + end begin 获取一个字符的迭代器,end 获取最后一个字符下一个位置的迭代器
rbegin + rend begin 获取一个字符的迭代器,end 获取最后一个字符下一个位置的迭代器
范围 for C++11 支持更简洁的范围 for 的新遍历方式

在这里插入图片描述

#include<assert.h>
#include<string>
#include<iostream>
using namespace std;   
//大概原理
template<class T>
class basic_string
{
public:
	char& operator[](size_t pos)
	{
		assert(pos < _size);//检查越界:s2[20] -> err
		return _arr[pos];	
	}
private:
	T* _arr;
	int _size;
	int _capacity;
};
//typedef basic_string<char> string;
int main()
{
	//逐一遍历字符串
		//1、operator[]
	string s1("hello world");
	for(size_t i = 0; i < s1.size(); ++i)
	{
		s1[i] += 1;//写
	}
	for(size_t i = 0; i < s1.size(); ++i)
	{
		cout << s1[i] << " ";//读
	}
	cout << endl;
	
		//2、范围for
	string s2("hello world");
	for(auto& e : s2)
	{
		e += 1;//写	
	}
	for(auto e : s2)
	{
		cout << e << " ";//读
	}
	cout << endl;
	
		//3、迭代器
	string s3("hello world");
	string::iterator it = s3.begin();
	while(it != s3.end())
	{
		*it += 1;//写
		++it;
	}
	it = s3.begin();
	while(it != s3.end())
	{
		cout << *it << " ";//读
		++it;
	}
	cout << endl;
	
	return 0;
}

📝说明

operator [] | at ❗

operator[] 和 at 的价值是一样的,但是不一样的地方是对于越界:operator[] 直接使用断言报错,比较粗暴;而 at 则会抛异常。
在这里插入图片描述
在这里插入图片描述

范围 for ❗

这是 C++11 中提出的新语法,比较抽象,对于它的原理,后面会再模拟实现它。

注意 auto e : s3 只能读,不能写;auto& e : s3 可读可写。

迭代器 ❗

它是 STL 中六大组件中的核心组件,这里先见个面。
在这里插入图片描述

begin() 返回第一个有效数据位置的迭代器;

end() 返回最后一个有效数据的下一个位置的迭代器;

目前可以认为它类似于指针,—— 有可能是指针,有可能不是指针,因为不仅仅 string 有迭代器,其它容器里也有迭代器。

while(it != s3.end()) 也可以 while(it < s3.end()),但不建议。这里是数组,换成小于它依然没问题,但是如果是链表,小于就不行了。所以这里统一就用不等于。

迭代器的好处是可以用统一类似的方式去访问修改容器 (也就意味着会了 string 的迭代器就等于会了其它容器的迭代器):
在这里插入图片描述
为什么这里要提供三种遍历方式 ❓

其实只提供了两种,因为范围 for 本质是迭代器,也就是说一个容器支持迭代器才会支持范围 for,后面会演示。

operator [] 可以像数组一样去访问,这种方式对于 vector 连续的数据结构是支持的,但是不支持 list。

迭代器这种方式是任何容器都支持的方式,所以迭代器才是容器通用的访问方式。

再简单了解迭代器 ❗

#include<string>
#include<iostream>
using namespace std;
void Print1(const string& s)//不需要写
{
	string::iterator it = s.begin();//err,普通迭代器
	//string::const_iterator it = s.begin();//ok,const迭代器
	//string::const_iterator it = s.cbegin();//ok,C++11提供的cbegin
	while(it != s.end())
	{
		cout << *it << " ";
		++it;	
	}
	cout << endl;
}
void Print2(const string& s)
{
	string::reverse_iterator rit = s.rbegin();//err,普通反向迭代器
	//string::const_reverse_iterator rit = s.rbegin();//ok,const反向迭代器
	//auto rit = s.rbegin();//ok,auto的体现
	while(rit != s.rend())
	{
		cout << *rit << " ";
		++rit;//注意这里不是--
	}
	cout << endl;
}
void test_string()
{
	string s1("hello");
	Print1(s1);

	string s2("hello");
	Print2(s2);	
}
int main()
{
	test_string();
	return 0;
}

📝说明

这里利用迭代器打印 s1:
在这里插入图片描述
查文档:begin 有两个版本
在这里插入图片描述

所以报错的原因是:s 是 const 对象,返回的是 const 迭代器,而这里使用普通迭代器来接收。解决方法就是用 const 迭代器接收。

在文档中看到 C++11 中又提供了一个 cbegin ???
在这里插入图片描述
为什么 C++11 把 const 迭代器单独拎出来,大概原因应该是 begin 里有普通 / const 迭代器不太明确,容易误导。不知道大家是怎么想的,我是觉得有点画蛇添足了。

rbegin:

rbegin 就是反向迭代器,顾名思义就是反向遍历。
在这里插入图片描述
在这里插入图片描述
auto 的价值 ❗

到了迭代器这里我们就可以用 auto 来替代比较长的类型,auto 的价值得以体现。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。