10.4 再探迭代器

除了为每个容器定义的迭代器之外,标准库在头文件iterator中还定义了额外几种迭代器。这些迭代器包括以下几种:

  1. 插入迭代器:这些迭代器被绑定到一个容器上,可用来向容器插入元素。
  2. 流迭代器: 这些迭代器被绑定到输入或输出流上,可用来遍历所关联的I0流。
  3. 反向迭代器: 这些迭代器向后而不是向前移动。除了forward_ list之外的标准库容器都有反向迭代器。
  4. 移动迭代器: 这些专用的迭代器不是拷贝其中的元素,而是移动它们。我们将在后面的13.6.2处进行详细介绍。

插入迭代器

绑定到容器中,用来向容器插入元素;

插入迭代器是一种迭代器适配器,接受一个容器生成迭代器,实现向给定容器添加元素。

相关的操作:

it= t; //在it指定位置插入值t
*it,++it,it++ //返回it

插入迭代器的三种模式

插入迭代器说明
back_inserter类似于使用c.push_back(val);
front_inserter类似于使用c.push_front(val);
inserter类似于使用 it = c.inserter(it,val);++it;元素被插入到给定迭代器之前的元素的地方

只有在容器支持push_ front(forward_list、list、deque)的情况下,我们才可以使用front_ inserter。类似的,只有在容器支持push_back(vector deque string)的情况下,我们才能使用back_ inserter.

样例:

	vector<string> strs = { "hhdy","ssssdfg","asdcfgd","hh","xx","hhdyzwhy" };
	auto it = inserter(strs, strs.begin()+1);
	it = "abs";
	//hhdy abs ssssdfg asdcfgd hh xx hhdyzwhy
	
	auto it1 = back_inserter(strs);
	*it1 = "hhh";  //it和*it=val都可以
	//hhdy abs ssssdfg asdcfgd hh xx hhdyzwhy hhh
	
	vector<string> strs1;
	copy(strs.begin(), strs.end(), inserter(strs1, strs1.begin()));
	//hhdy abs ssssdfg asdcfgd hh xx hhdyzwhy hhh
	
	list<string> strs2;
	copy(strs.begin(), strs.end(), front_inserter(strs2));
	//hhh hhdyzwhy xx hh asdcfgd ssssdfg abs hhdy
	
	vector<string> strs3;
	copy(strs.begin(), strs.end(), back_inserter(strs3));
	//hhdy abs ssssdfg asdcfgd hh xx hhdyzwhy hhh
	
	vector<string> strs4;
	copy(strs.begin(), strs.end(), inserter(strs1, strs4.begin()));
	//hhdy abs ssssdfg asdcfgd hh xx hhdyzwhy hhh
	//此处和strs2进行对比,看看有什么不同。
	

iostream迭代器(流迭代器)

虽然iostream类型不是容器,但标准库定义了可以用于这些IO类型对象的迭代器。istream_iterator 读取输入流,ostream_ iterator 向一个输出流写数据。这些迭代器将它们对应的流当作一个特定类型的元素序列来处理。通过使用流迭代器,我们可以用泛型算法从流对象读取数据以及向其写入数据。

istream_iterator 操作

操作说明
istream_iterator<T> in(is);in从输入流is中读取T类型的数据,in实际上相当于此段迭代器中的begin
istream_iterator<T> end;读取类型为T的istream_iterator尾后迭代器,相当于此段迭代器中的end
in1 == in2in1和in2都是尾后迭代器或者绑定到相同的输入(前提二者都是读取T类型的数据)
in1 != in2非上面的描述即此描述
*in返回从流中读取的数据
in->mem等效于(*in).mem
++in,in++使用元素类型所定义的>>运算符从输入流中读取的下一个值。

常见用法1:
从cin读取int值存入vec

//从cin读取int值存入vec
	vector<int> vec;
	istream_iterator<int> int_it(cin),int_eof;
	while (int_it != int_eof) {
		vec.push_back(*int_it++);
	}

//相当于下方代码
	istream_iterator<int> in_iter(cin), eof;
	vector<int> vec(in_iter, eof);

常见用法2:
从文件流读取string存入vecstr

	ifstream in("文件地址");
	istream_iterator<string> str_int(in),str_eof;
	vector<string> vecstr;
	while (str_int != str_eof) {
		vecstr.push_back(*str_int++);
	}

常见用法3:
使用泛型算法操作流迭代器

	istream_iterator<int> intit(cin), inteof;
	cout<<accumulate(intit, inteof, 0)<<endl;

ostream_iterator 操作

可以对任何具有输出运算符(<<)的类型定义ostream_iterator。

ostream_iterator必须绑定到一个指定的流,不允许空的或表示尾后位置的ostream_iterator。

ostream_iterator 操作说明
ostream_iterator<T> out(os);out将类型T的值写入输出流os中
ostream_iterator out(os,d);out将类型T的值写入输出流os中,每个值后都输出一个d。d指向一个空字符结尾字符数组。
out = val用<<运算符将val写入到out绑定输出流os中。
*out,++out,out++不对out做任何事,返回out

常用用法1:
输出

	vector<int> vec{ 1,2,3,4,5 };
	ostream_iterator<int> out(cout, " ");
	for (int i : vec)
	{
		out = i;
		//*out++ = i;//功能和上面的一致。
	}
	cout << endl;

常用用法2:
通过泛型函数打印输出

	ostream_iterator<int> out_iter(cout, " ");
	copy(vec.begin(), vec.end(), out_iter);
	cout << endl;

常用用法3:
使用流迭代器处理类:
待补。

反向迭代器

反向迭代器是在容器从尾元素向首元素反向移动的迭代器。反向迭代器++it会移动到前一个元素,- -it会移动到后一个元素。
由于反向迭代器需要递减运算符,所以除单向链表和流迭代器外可以使用。

c.rbegin(),c.crbegin(),c.rend(),c.crend()

常用的方式1:
逆序输出:

	vector<int> vec = { 1,2,3,4,5 };
	ostream_iterator<int> outer_vec(cout, " ");
	copy(vec.rbegin(), vec.rend(), outer_vec);  //5,4,3,2,1
	cout<<endl;
	
	for (auto iter = vec.rbegin(); iter != vec.rend(); ++iter) {
		cout << *iter << " "; //5,4,3,2,1
	}
	cout << endl;

常用的方式2:
逆序排序:

sort(vec.rbegin(),vec.rend());

常用的方式3:
输出逗号分割列表中倒数第一个单词

由于普通迭代器是左闭右开,反向迭代器是左开右闭。二者不能混合使用。从一个普通迭代器初始化一个反向迭代器,或是给一个反向迭代器赋值时,结果迭代器和原迭代器指向的不是同一个元素。
可以使用reverse_iterator的base函数,使反向迭代器返回对应的普通迭代器。

	string words = "hhdy,zwhy,hhdyzwhy";
	auto lword_iter = find(words.rbegin(), words.rend(), ',');
	cout << string(words.rbegin(),lword_iter) << endl; //yhwzydhh 
	//为什么不用下面的那个格式呢?
	//原因在于lword_iter是从逆向过来的,所以他是一个反向迭代器,意味着他会反向的处理string,导致无限循环,在此处卡住。
	cout << string(lword_iter,words.rbegin())<<endl;

	//正确格式,使用base函数进行再次反过来。
	cout << string(lword_iter.base(),words.end()) << endl;//hhdyzwhy

移动迭代器

不拷贝其中元素,而是移动他们。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值