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. Connecting Docker for Cloud Services using SDN and Network Virtualization

     Abstract The explosive scale of container CPUs needs highly efficient network virtualization Chal ...

  2. IOS设计模式学习(20)命令

    1 前言 在面向对象中,把指令封装在各种命令对象中.命令对象可以被传递而且在指定时刻被不同的客户端复用.这一概念精心设计而来的设计模式叫做命令(Command)模式. 2 详述 2.1 简述 命令对象 ...

  3. 初步C++类模板学习笔记

    类模板 实现:在上课时间的定义给它的一个或多个参数,这些参数代表了不同的数据类型.                              -->抽象的类. 在调用类模板时, 指定參数, 由编 ...

  4. HTML5 在canvas绘制一个矩形

    笔者:本笃庆军 原文地址:http://blog.csdn.net/qingdujun/article/details/32930501 一.绘制矩形 canvas使用原点(0,0)在左上角的坐标系统 ...

  5. AutoFac使用方法总结:Part I

    注册部分 使用RegisterType进行注册 [Fact] public void can_resolve_myclass() { var builder = new ContainerBuilde ...

  6. 【leetCode百题成就】Gas Station解题报告

    题目: There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. ...

  7. js多物体任意值运动

    假如有两个div,一个div要变宽,一个div要变高,你怎么写呢? 哎呀,写2个方法啊,一个控制div1变宽,一个控制div2变高啊 那么你的代码,是不是下面这样的呢! 示例:Div变宽和变高 现象: ...

  8. Android自带样式

    Android系统自带样式: android:theme="@android:style/Theme.Dialog" 将一个Activity显示为对话框模式 android:the ...

  9. Android client和服务器JSP互传中国

    出于兼容性简化.传统中国等多国语言.推荐使用UTF-8编码. 首选.我们期待Android到底应该怎么办: 在发送前,应该对參数值要进行UTF-8编码,我写了一个static的 转换函数.在做发送动作 ...

  10. Windows 8 键盘上推自定义处理

    原文:Windows 8 键盘上推自定义处理 在Windows 8 应用程序中,当TextBox控件获得焦点时,输入面板会弹出,如果TextBox控件处于页面下半部分,则系统会将页面上推是的TextB ...