STL实践与分析

--再谈迭代器【中】

二、iostream迭代【续】

3、ostream_iterator对象和ostream_iterator对象的使用

能够使用ostream_iterator对象将一个值序列写入流中,其操作过程与使用迭代器将一组值逐个赋值给容器中的元素同样:

    ostream_iterator<string> out_iter(cout,"\n");
istream_iterator<string> in_iter(cin),eof; while (in_iter != eof)
{
*out_iter++ = *in_iter++;
}

读取cin,并将每一个读入的值依次写入到cout中不同的行中。

4、在类类型上使用istream_iterator

提供了输入操作符>>不论什么类型都能够创建istream_iterator对象。

    istream_iterator<Sales_item> item_iter(cin),eof;
Sales_item sum;
sum = *item_iter ++; while (item_iter != eof)
{
if (item_iter -> same_isbn(sum))
{
sum += *item_iter;
}
else
{
cout << sum << endl;
sum = *item_iter;
}
++ item_iter;
}
cout << sum << endl;

5、流迭代器的限制

1)不可能从ostream_iterator对象读入,也不可能写到istream_iterator对象中。

2)一旦给ostream_iterator对象赋了一个值,写入就提交了。赋值后,没有办法再改变这个值。此外,ostream_iterator对象中每一个不同的值都仅仅能正好输出一次。

3)ostream_iterator没有 ->操作符。

6、与算法一起使用流迭代器

因为算法是基于迭代器操作实现的,而流迭代器定义了一些迭代器操作。因为流迭代器操作,因此,至少可在一些泛型算法上使用这类迭代器。

    //从文件里读取一些数,再将读取的不反复的数写到标准输出
ifstream inFile("input");
istream_iterator<int> in_iter(inFile),eof; vector<int> iVec(in_iter,eof);
sort(iVec.begin(),iVec.end()); ostream_iterator<int> out_iter(cout," ");
unique_copy(iVec.begin(),iVec.end(),out_iter);

    //另外一种方式输出
vector<int>::iterator end_unique = unique(iVec.begin(),iVec.end());
cout << endl;
for (vector<int>::iterator iter = iVec.begin(); iter != end_unique; ++iter)
{
*out_iter ++ = *iter;
}

//P353 习题11.16
int main()
{
ifstream inFile("input"); istream_iterator<string> in_iter(inFile),eof;
ostream_iterator<string> out_iter(cout," "); while (in_iter != eof)
{
*out_iter ++ = *in_iter ++;
}
}

//习题11.17
int main()
{
ifstream inFile("input"); istream_iterator<int> in_iter(inFile),eof;
vector<int> iVec(in_iter,eof); for (vector<int>::iterator iter = iVec.begin(); iter != iVec.end(); ++iter)
{
cout << *iter << endl;
}
}

//习题11.18 本题集合了iostream迭代器,文件流
int main()
{
istream_iterator<int> in_iter(cin),eof;
ofstream outFile1("output1"),outFile2("output2"); ostream_iterator<int> out_iter1(outFile1," "),out_iter2(outFile2,"\n"); while (in_iter != eof)
{
if (*in_iter % 2)
{
*out_iter1 ++ = *in_iter ++;
}
else
{
*out_iter2 ++ = *in_iter ++;
}
}
}

三、反向迭代器

反向迭代器是一种反向遍历容器的迭代器:从最后一个元素到第一个元素遍历容器。反向迭代器将自增/自减的含义反过来了:对于反向迭代器,++运算将訪问前一个元素,而—元素将訪问下一个元素。

容器定义的rbegin和rend成员,分别返回指向容器尾元素和首元素前一位置的反向迭代器。

    //逆序输出vector对象中的元素
vector<int> iVec;
for (vector<int>::size_type i = 0; i != 10; ++i)
{
iVec.push_back(i);
} for (vector<int>::reverse_iterator r_iter = iVec.rbegin(); r_iter != iVec.rend(); ++r_iter)
{
cout << *r_iter << endl;
}

尽管颠倒自增和自减这两个操作符的意义似乎easy使人迷惑,可是它让程序猿能够透明地向前或向后处理容器。比如,为了以降序排列vector,仅仅需向sort传递一对反向迭代器:

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

当然,假设不嫌麻烦,也能够这样:

    sort(iVec.begin(),iVec.end(),cmp);

cmp函数定义例如以下:

bool cmp(int a,int b)
{
return a > b;
}

1、反向迭代器须要使用自减操作符

从一个既支持--也支持++的迭代器就能够定义反向迭代器。毕竟,反向迭代器的目的是移动迭代器反向遍历序列。标准容器上的迭代器既支持自增运算,也支持自减运算。可是,流迭代器却不然,因为不能反向遍历流,因此流迭代器不能创建反向迭代器

2、反向迭代器与其它迭代器之间的关系

输出 string对象line中的第一个单词。使用find可非常easy地实现这个任务:

    string::iterator comma = find(line.begin(),line.end(),',');
cout << string(line.begin(),comma) << endl;

假设要输出列表中的最后一个单词,能够使用反向迭代器:

    string::reverse_iterator rcomma = find(line.rbegin(),line.rend(),',');
//以下的输出结果可能不能满足你的要求...
cout << string(line.rbegin(),rcomma) << endl;

假设line中的最后一个单词是Primer,那么,输出的结果为:remirP【是不是非常不可思议?】见下图:

使用反向迭代器时,以逆序从后向前处理string对象。为了得到正确的输出,必须将反向迭代器line.rbegin()和 rcomma转换为从前向后移动的普通迭代器。事实上不是必需转换line.rbegin(),因为我们知道转换的结果必然是line.end()。仅仅需调用全部反向迭代器类型都提供的成员函数base转换rcomma就可以:

    cout << string(rcomma.base(),line.end()) << endl;

    正如 line_rbegin()line.end()一样,rcommarcomma.base()也指向不同的元素。从技术上来说,设计普通迭代器与反向迭代器之间的关系是为了适应左闭合范围这个性质的,所以,[line.rbegin(),rcomma) 和[rcomma.base(),line.end()) 标记的是line中的同样元素。

使用普通的迭代器对反向迭代器进行初始化或赋值时,所得到的迭代器并非指向原迭代器所指向的元素!!!

C++ Primer 学习笔记_43_STL实践与分析(17)--再谈迭代器【中】的更多相关文章

  1. C++ Primer 学习笔记_44_STL实践与分析(18)--再谈迭代器【下】

    STL实践与分析 --再谈迭代器[下] 三.反向迭代器[续:习题] //P355 习题11.19 int main() { vector<int> iVec; for (vector< ...

  2. C++ Primer 学习笔记_32_STL实践与分析(6) --再谈string类型(下)

    STL实践与分析 --再谈string类型(下) 四.string类型的查找操作 string类型提供了6种查找函数,每种函数以不同形式的find命名.这些操作所有返回string::size_typ ...

  3. C++ Primer 学习笔记_35_STL实践与分析(9)--map种类(在)

    STL实践与分析 --map类型(上) 引: map是键-值对的集合. map类型通常能够理解为关联数组:能够通过使用键作为下标来获取一个值,正如内置数组类型一样:而关联的本质在于元素的值与某个特定的 ...

  4. C++ Primer 学习笔记_46_STL实践与分析(20)--容器特有的算法

    STL实践与分析 --容器特有的算法 与其它顺序容器所支持的操作相比,标准库为list容器定义了更精细的操作集合,使它不必仅仅依赖于泛型操作.当中非常大的一个原因就是list容器不是依照内存中的顺序进 ...

  5. C++ Primer 学习笔记_40_STL实践与分析(14)--概要、先来看看算法【上】

    STL实践与分析 --概述.初窥算法[上]     标准库容器定义的操作很少.并没有给容器加入大量的功能函数.而是选择提供一组算法,这些算法大都不依赖特定的容器类型,是"泛型"的. ...

  6. C++ Primer 学习笔记_45_STL实践与分析(19)--建筑常规算法

    STL实践与分析 --泛型算法的结构 引言: 正如全部的容器都建立在一致的设计模式上一样,算法也具有共同的设计基础. 算法最主要的性质是须要使用的迭代器种类.全部算法都指定了它的每一个迭代器形參可使用 ...

  7. C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器

    STL实践与分析 --容器适配器 引: 除了顺序容器.标准库还提供了三种顺序容器适配器:queue,priority_queue和stack.适配器是标准库中的概念.包含容器适配器,迭代器适配器和函数 ...

  8. C++ Primer 学习笔记_41_STL实践与分析(15)--先来看看算法【下一个】

    STL实践与分析 --初窥算法[下] 一.写容器元素的算法 一些算法写入元素值.在使用这些算法写元素时一定要当心.必须.写入输入序列的元素 写入到输入序列的算法本质上是安全的--仅仅会写入与指定输入范 ...

  9. C++ Primer 学习笔记_38_STL实践与分析(12)--集成的应用程序容器:文本查询程序

    STL实践与分析 --容器的综合应用:文本查询程序 引言: 本章中最重点的实例.由于不须要用到multiset与multimap的内容.于是将这一小节提到了前面.通过这个实例程序,大师分析问题的智慧, ...

随机推荐

  1. u-boot TFTP: &#39;Access violation&#39; (2)

    今天做tftp下载时间会遇到以下问题. --->8--- Load address: 0x20000000 Loading: * TFTP error: 'Access violation' ( ...

  2. NET MVC运行机制

    [图解ASP.NET MVC运行机制理解-简易版]   很多盆友咨询ASP.NET MVC的机制.网上也有好多.但是都是相当深奥.看的云里雾里的.我今天抽空,整理个简易版本.把处理流程走一遍. 当然, ...

  3. 理解RESTful架构(转)

    越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高 ...

  4. 数学思想方法-分布式计算-linux/unix技术基础(5)

    shell命令行参数 -bash-4.2$ cat test1.sh#!/bin/shecho "$0  "echo "$1  "echo "$2   ...

  5. Sqlserver中Over函数

    Over函数不能单独使用,要和分析函数:rank(),dense_rank(),row_number()等一起使用.  其参数:over(partition by columnname1 order ...

  6. WCF 部署时,soap:address location 显示的是电脑名,而不是ip地址

    部署WCF服务时,发现soap:address location 和wsdl:import location 显示是电脑名,而不是ip地址,这样外面公司的人就无法下载剩下的wsdl,post也会往错误 ...

  7. 透过浏览器看HTTP缓存(转)

    作为前端开发人员,对于我们的站点或应用的缓存机制我们能做的似乎不多,但这些却是与我们关注的性能息息相关的部分,站点没有做任何缓存机制,我们的页面可能会因为资源的下载和渲染变得很慢,但大家都知道去找前端 ...

  8. ZOJ 3728 Collision

    ---恢复内容开始--- 今天无事水一水,结果就看到这个水题了! 题意思是 有俩个区域如图 求在俩个圆之间的运动时间 给出 初始的开始点和速度的矢量式;而且这个点 不再俩个圆之间的区域,且碰到内测园会 ...

  9. IT忍者神龟之使用 PowerDesigner

    1. 启动 PowerDesigner 新建物理数据模型 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdmlweWhk/font/5a6L5L2T/fon ...

  10. ExtJS4 根据分配不同的树形菜单在不同的角色登录后

    继续我的最后.建立cookie后,带他们出去 var userName = Ext.util.Cookies.get('userName'); var userAuthority = Ext.util ...