第十一章

11.1

关键概念:算法永不执行容器提供的操作
        泛型算法本身从不执行容器操作,只是单独依赖迭代器和迭代器操作实现。算法基于迭代器及其操作实现,而并非基于容器操作。这个事实也许比较意外,但本质上暗示了:使用“普通”的迭代器时,算法从不修改基础容器的大小。正如我们所看到的,算法也许会改变存储在容器中的元素的值,也许会在容器内移动元素,但是,算法从不直接添加或删除元素。第 11.3.1 节将介绍标准库提供的另一种特殊的迭代器类:插入器(inserter),除了用于遍历其所绑定的序列之外,还可实现更多的功能。在给这类迭代器赋值时,在基础容器上将执行插入运算。如果算法操纵这类迭代器,迭代器将可能导致在容器中添加元素。但是,算法本身从不这么做。 

find_first_of的使用

        这个算法带有两对迭代器参数来标记两段元素范围,在第一段范围内查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到元素,则返回第一个范围的 end 迭代器。假设 roster1 和 roster2 是两个存放名字的 list 对象,可使用 find_first_of 统计有多少个名字同时出现在这两个列表中:

size_t cnt = 0;
list<string>::iterator it = roster1.begin();
// look in roster1 for any name also in roster2
while ((it = find_first_of(it, roster1.end(),roster2.begin(), roster2.end()))!= roster1.end()) {
++cnt;
// we got a match, increment it to look in the rest of roster1
++it;
}
cout << "Found " << cnt<< " names on both rosters" << endl;
11.2.2
算法的 _copy 版本

        replace 算法就是一个很好的例子。该算法对输入序列做读写操作,将序列中特定的值替换为新的值。该算法带有四个形参:一对指定输入范围的迭代器和两个值。每一个等于第一值的元素替换成第二个值。

replace(ilst.begin(), ilst.end(), 0, 42);

        这个调用将所有值为 0 的实例替换成 42。如果不想改变原来的序列,则调用 replace_copy。这个算法接受第三个迭代器实参,指定保存调整后序列的目标位置

// create empty vector to hold the replacement
vector<int> ivec;
// use back_inserter to grow destination as needed
replace_copy (ilst.begin(), ilst.end(),back_inserter(ivec), 0, 42);

        调用该函数后,ilst 没有改变,ivec 存储 ilst 一份副本,而 ilst 内所有的 0 在 ivec 中都变成了 42。

11.2.3
unique的使用

        它带有两个指定元素范围的迭代器参数。该算法删除相邻的重复元素,然后重新排列输入范围内的元素,并且返回一个迭代器,表示无重复的值范围的结束。

stable_sort

        sort 和 stable_sort 都是重载函数。其中一个版本使用元素类型提供的小于(<)操作符实现比较。在查找重复元素之前,我们就是用这个 sort 版本对元素排序。第二个重载版本带有第三个形参: 比较元素所使用的谓词函数的名字。这个谓词函数必须接受两个实参,实参的类型必须与元素类型相同,并返回一个可用作条件检测的值。stable_sort 保留相等元素的原始相对位置

11.3.1

        inserter 适配器提供更普通的插入形式。这种适配器带有两个实参:所关联的容器指示起始插入位置的迭代器

// position an iterator into ilst
list<int>::iterator it =find (ilst.begin(), ilst.end(), 42);
// insert replaced copies of ivec at that point in ilst
replace_copy (ivec.begin(), ivec.end(),inserter (ilst, it), 100, 0);

        首先用 find 定位 ilst 中的某个元素。使用 inserter 作为实参调用replace_copy,inserter 将会在 ilst 中由 find 返回的迭代器所指向的元素前面插入新元素。而调用 replace_copy 的效果是从 ivec 中复制元素,并将其中值为 100 的元素替换为 0 值。ilst 的新元素在 it 所标明的元素前面插入。

        在创建 inserter 时,应指明新元素在何处插入。inserter 函数总是在它的迭代器实参所标明的位置前面插入新元素

11.3.2 iostream 迭代器
istream_iterator<T>in(strm);创建从输入流 strm 中读取 T 类型对象的 istream_iterator 对象
istream_iterator<T>in;istream_iterator 对象的超出末端迭代器
ostream_iterator<T>in(strm);              创建将 T 类型的对象写到输出流 strm 的 ostream_iterator 对象
ostream_iterator<T> in(strm, delim);创建将 T 类型的对象写到输出流 strm 的 ostream_iterator 对象,在写入过程中使用 delim 作为元素的分隔符。delim 是以空字符结束的字符数 组
// write one string per line to the standard output
ostream_iterator<string> out_iter(cout, "\n");
// read strings from standard input and the end iterator
istream_iterator<string> in_iter(cin), eof;
// read until eof and write what was read to the standard output
while (in_iter != eof)
// write value of in_iter to standard output
// and then increment the iterator to get the next value from cin
*out_iter++ = *in_iter++;

        首先,定义一个 ostream_iterator 对象,用于将 string 类型的数据写到cout 中,每个 string 对象后跟一个换行符。定义两个 istream_iterator 对象,用于从 cin 中读取 string 对象。while 循环类似前一个例子。但是这一次不是将读取的数据存储在 vector 对象中, 而是将读取的数据赋给 out_iter,从而输出到 cout 上。

Exercise 11.18:
        编写程序使用 istream_iterator 对象从标准输入读入一系列整数。使用 ostream_iterator 对象将其中的奇数写到一个文件中, 并在每个写入的值后面加一个空格。同样使用 ostream_iterator 对象将偶数写到第二个文件,每个写入的值都存放在单独的行中。
#include<iostream>
#include<iterator>
#include<fstream>

using namespace std;

bool GT6(const string &s)
{
	return s.size()>=6;
}

int main()
{
	ofstream out_file1("text1.txt");
	ofstream out_file2("text2.txt");
	if(!out_file1||!out_file2)
	{
		cout<<"can't open file!"<<endl;
		return 0;
	}
	istream_iterator<int> in(cin),end;
	ostream_iterator<int> out1(out_file1," ");
	ostream_iterator<int> out2(out_file2,"\n");
	while(in!=end)
	{
		if(*in%2!=0)
		{
			*out1=*in;
			out1++;
		}
		else
		{
			*out2=*in;
			out2++;
		}
		in++;
	}
	getchar();
	getchar();
	return 0;
}

        所有反向迭代器类型都提供的成员函数 base ,riter.base( )=iter++

11.3.5
Input iterator(输入迭代器)读,不能写;只支持自增运算
Output iterator(输出迭代器)写,不能读;只支持自增运算
Forward iterator(前向迭代器)读和写;只支持自增运算
Bidirectional iterator(双向迭代器)读和写;支持自增和自减运算
Random access iterator(随机访问迭代器)读和写;支持完整的迭代器算术运算

        map、set 和 list 类型提供双向迭代器,而 string、vector 和 deque 容器上定义的迭代器都是随机访问迭代器都是随机访问迭代器, 用作访问内置数组元素的指针也是随机访问迭代器。istream_iterator 是输入迭代器,而ostream_iterator 则是输出迭代器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值