C++ Primer 第十章 10.4 再探迭代器 练习和总结

10.4 再探迭代器

标准库的头文件iterator,除了定义了容器的迭代器之外,还定义了一些额外的迭代器。

  1. 插入迭代器 insert iterator
  2. 流迭代器 stream ierator
  3. 反向迭代器 reverse iterator
  4. 移动迭代器

接下来总结每个迭代器具体是做什么的

10.4.1插入迭代器

插入迭代器是一种迭代器适配器,其接受一个容器,生成一个迭代器,对该迭代器赋值时,这个迭代器将调用容器操作将赋值的元素添加进容器

插入迭代器有三个。
1.back_inserter
2.front_inserter
3.inserter

backi_inserter调用容器的push_back()操作,前提是容器有push_back()操作,添加之后的元素为顺序

front_inserter()调用容器的push_front()操作,前提是容器有push_front()操作,添加之后的元素位逆序

inserter()需要指定容器和插入的位置,指向insert操作,inserter将元素插入到指定的元素之前,所以添加之后的元素为顺序

插入迭代器支持的操作:
在这里插入图片描述
其实只有赋值有用,其余的操作返回的都是插入迭代器自己。

练习

10.26
有什么不同指出,已经在上面写出来了

10.27

vector<string> vec = { "a","c","a","e123","1ca","aaa","aaa","z123","q","casd123","asdas" };
	deque<string> dq;
	
	std::sort(vec.begin(),vec.end());
	std::unique_copy(vec.begin(),vec.end(),std::back_inserter(dq));
	for (const auto& item:dq) {
		cout << item << endl;
	}

	cout << "size:" << dq.size() << endl;

10.28
错误记录:这里我犯了一个错误就是,认为传给算法的迭代器在每次赋值的使用都调用一次,所以inserter传入begin(),每次都在首元素之前插入,那插入的元素不就是逆序吗,但是其实是只在调用时begin()指的还是首元素或者最后一个元素的下一位置,在插入了其他的元素之后,它就不再是首元素了。

vector<int> vec = {1,2,3,4,5,6,7,8,9};
	vector<int> vec_1;
	list<int> lst_1;
	deque<int> dq_1;
	//顺序
	std::copy(vec.begin(), vec.end(), std::back_inserter(vec_1));
	//逆序
	std::copy(vec.begin(), vec.end(), std::front_inserter(lst_1));
	//这是顺序。。。= =
	std::copy(vec.begin(),vec.end(),std::inserter(dq_1,dq_1.begin()));

	for (const auto& item:vec_1) {
		cout << item << std::ends;
	}
	cout << endl;
	for (const auto& item : lst_1) {
		cout << item << std::ends;
	}
	cout << endl;
	for (const auto& item : dq_1) {
		cout << item << std::ends;
	}
	cout << endl;

10.4.2 iostream迭代器

标准库定义了用于IO类型的迭代器。
1.istream_iterator
2.ostream_iterator

istream_iterator操作

在这里插入图片描述
创建istream_iterator需要指定迭代器类型,在初始化时,可以传入流对象,也可以使用默认初始化,如果是默认初始化则表示尾后迭代器。如果传入了流对象,则从该流中读取数据。

对istream_iterator的操作流程一般是:

std::istream_iterator<int> int_input(cin);
	std::istream_iterator<int> eof;
	vector<int> vec;
	while (int_input!=eof) {
		 vec.push_back(*int_input++);
	}

使用*iter来获取流中的元素,使用iter++,从迭代器中读取下一个元素。

怎么用
我们可以在一些算法中使用istream_iterator.

istream_iterator<int> in(cin),eof;
cout<<accumulate(in,eof,9)<<endl;

该算法将从标准输入中读取值。

当我们使用一个流迭代器绑定到一个流上时,迭代器不一定立刻从流中读取数据,也可以在调用时,再读取。
这里没有给出实际的代码,我也不好理解这句话的意思

ostream_iterator

在这里插入图片描述
ostream_iterator在初始化时,必须绑定对象,同时可以添加一个C风格字符串,在每次输出时都会添加这么一个字符串。

直接使用iter=value,就可以向绑定的流中输出数据。
*iter,++iter,iter++,都返回的是自己。

虽然这三个操作没用,但是一般还是建议用上,一个是保持风格的统一,一个是如果迭代器变了,程序的修改程度也不大。

具体的操作,看练习

对于流迭代器,只要类类型,重载了>>就能够使用istream_iterator,只要重载了<<就能够使用ostream_iterator.

练习

10.29

std::ifstream fin("phone.txt");
	//需要指定对象的类型
	std::istream_iterator<string> in_iter(fin);
	// 尾后迭代器
	std::istream_iterator<string> eof;
	vector<string> str_vec;
	while (in_iter!=eof) {
		str_vec.push_back(*in_iter++);
	}
	std::ostream_iterator<string> out_iter(cout," ");
	for (const auto& item:str_vec) {
		*out_iter++ = item;
	}

10.30

vector<string> vec = { "a","c","a","e123","1ca","aaa","aaa","z123","q","casd123","asdas" };
	std::istream_iterator<int> int_input(cin);
	std::istream_iterator<int> eof;
	//std::sort();
	vector<int> vec;
	while (int_input!=eof) {
		 vec.push_back(*int_input++);
	}
	std::ostream_iterator<int> int_output(cout," ");
	std::sort(vec.begin(),vec.end());
	std::copy(vec.begin(), vec.end(), int_output);
	//std::unique_copy(vec.begin(), vec.end(), int_output);

10.31

	std::unique_copy(vec.begin(), vec.end(), int_output);

10.32

没有1.6节的源码,后续学习到重载运算符再补上



10.33

std::ifstream f("data.txt");
	std::istream_iterator<int> f_input(f),eof;
	std::ofstream file1("jishu.txt"), file2("oushu.txt");
	std::ostream_iterator<int> out_iter_1(file1," "),out_iter_2(file2,"\n");
	while (f_input!=eof) {
		if (*f_input%2==1) {
			*out_iter_1++ = *f_input;
		}
		else {
			*out_iter_2++ = *f_input;
		}
		f_input++;
	}
发布了38 篇原创文章 · 获赞 6 · 访问量 2694

猜你喜欢

转载自blog.csdn.net/zengqi12138/article/details/104316536