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. 深度分析 Java 的枚举类型:枚举的线程安全性及序列化问题(转)

    写在前面: Java SE5 提供了一种新的类型 Java的枚举类型,关键字 enum 可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是一种非常有用的功能 ...

  2. Sliverlight之 画刷

    1,5种画刷 (见Project15) (1)TextBlock控件中的Forground和BackGround属性是一个什么对象?它在前台的完整的写法是什么?(实际是.net做了一个转换,可以直接写 ...

  3. improper Advertising identifier [IDFA] Usage. Your app contains the Advertising Identifier [IDFA] AP

    找到答案了.随便传个包上去.然后拒绝掉,又一次prepare to upload.就会出现选项. 相应选择就好了.

  4. [Eclipse]代码已被写入关于如何切换到unix在新行

    切换换行符的显示格式, 一般的设置是这种: 可是这样仅仅能对新文件起作用,原来已经写好的还是那熊样.(怎么办呢,得吃懊悔药啊,谁让你開始没准备好呢?!T_T) 以下就是懊悔药: 这样就OK了. 附:有 ...

  5. asp.net使用mysql数据库

    Asp.net连接mysql 不推荐使用ODBC,推荐是用mysql官网提供的组件MySQL.Data.Dll,放在bin下面,添加引用即可 下面是封装的几个常用操作 using System; us ...

  6. 制作简易计算器处理过程Servlet

    CalculationServlet.java: package com.you.servlet; import java.io.IOException; import java.io.PrintWr ...

  7. JComboBox

    package swing.combox; import java.awt.FlowLayout; import javax.swing.DefaultComboBoxModel; import ja ...

  8. android看不见main函数怎么办?程序异常了,能够不提示“xxx软件停止执行”吗?

    今天遇到了这个问题,分享一下解决方式. android没有main 函数,自然也就不存在main里面加入异常处理来实现全局异常捕获的方案.那android程序有全局异常补货的解决方式吗? 答案是有的: ...

  9. MarkdownPad怎么显示表格

    工具 >选项 > Markdown >Markdown处理器 改为 “Markdown(扩展)”即可. 下载地址 http://www.xdowns.com/soft/1/95/20 ...

  10. lua、groovy嵌入到java中的性能对比(转)

    lua和groovy都是可以嵌入到java中的脚本语言.lua以高性能著称,与C/C++在游戏开放中有较多使用,groovy是一个基于Java虚拟机(JVM)的敏捷动态语言,在jvm下有着不错的性能. ...