stream_iterator、ostream_iterator 使用初探

STL定义了供输入及输出的iostream iterator类,称为
istream_iterator和ostream_iterator,分别支持单一型别的元素的读取和写入。 
使用方法: 
1.包含头文件:
#include <iterator>  using namespace std;    
  
2.像使用其他iterator一样使用istream_iterator和
ostream_iterator。如:
 
使用一对“连接至标准输入”的iterator用于标示元素范围: 
   //
将is定义为一个“连接至标准输入装置”的istream_iterator 
 
 istream_iterator<string> is(cin); 
 
 //
定义istream_iterator时不为它指定istream对象,它即代表了end-of-file。 
 
 istream_iterator<string> eof; 
 
 ostream_iterator<string> os(cout, "
"); 
 除了“连接至标准输入”外,还可以连接至其他设备,如文件:

[cpp] view plaincopy

  1. #include <fstream>

  2. using namespace std;

  3. ifstream in_file("in.txt");

  4. ofstream out_file("in.txt");

  5. if ( !in_file || !out_file )

  6. {

  7. cerr << "failed to open the necessary file! /n";

  8. return -1;

  9. }

  10. istream_iterator<string> is(in_file);

  11. istream_iterator<string> eof;

  12. ostream_iterator<string> os(out_file, " ");

***********************************************************************************************

[cpp] view plaincopy

  1. #include <iostream>

  2. #include <iterator>

  3. #include <string>

  4. #include <vector>

  5. #include <fstream>

  6. #include <algorithm>

  7. using namespace std;

  8. int main()

  9. {

  10. // 1. 标准输入输出操作。

  11. istream_iterator<string> is(cin);

  12. istream_iterator<string> eof;

  13. vector<string> text;

  14. // 将标准输入的内容复制至text中。  由于使用的是vector,故使用back_inserter()

  15. copy(is, eof, back_inserter(text));

  16. // do something.

  17. sort(text.begin(), text.end());

  18. // 输出至标准输出。

  19. ostream_iterator<string> os(cout, " ");

  20. copy(text.begin(), text.end(), os);

  21. // 2. 非标准输入输出操作:文件读写操作。

  22. ifstream in_file("in.txt");

  23. ofstream out_file("in.txt");

  24. if ( !in_file || !out_file )

  25. {

  26. cerr << "failed to open the necessary file! /n";

  27. return -1;

  28. }

  29. istream_iterator<string> is2(in_file);

  30. istream_iterator<string> eof2;

  31. vector<string> text2;

  32. copy(is2, eof2, back_inserter(text2));

  33. sort(text2.begin(), text2.end());

  34. ostream_iterator<string> os2(out_file, " ");

  35. copy(text2.begin(), text2.end(), os2);

  36. return 0;

  37. }

************************************************************************************

istream_iterator常见错误

1.
错误原码

以下原代码不能通过编译:

 
  ifstream ifs("test.txt");
   
istream_iterator<string> ibeg(ifs);
   
istream_iterator<string> iend();
   
vector<string> vec(ibeg,
iend);

对于vec的构造编译出错:
error: no matching
function for call to `std::vector<std::string,
std::allocator<std::string>
>::vector(std::istream_iterator<std::string, char,
std::char_traits<char>, ptrdiff_t>&,
std::istream_iterator<std::string, char, std::char_traits<char>,
ptrdiff_t>
(&)())‘

原来它把iend当作了一个函数。去掉iend后面的括号就行了:

2. 正确的完整代码

[cpp] view plaincopy

  1. #include <iostream>

  2. #include <iterator>

  3. #include <fstream>

  4. #include <vector>

  5. #include <algorithm>

  6. using namespace std;
  7. int main()

  8. {

  9. ifstream ifs("test.txt");

  10. istream_iterator<string> ibeg(ifs);

  11. istream_iterator<string> iend;

  12. vector<string> vec(ibeg, iend);
  13. copy(vec.begin(), vec.end(),ostream_iterator<string>(cout, "\n"));

  14. return 0;

  15. }

3. 直接内嵌出错

就像在copy函数中一样,并不需要定义ibeg, iend,
应该可以在vector的构造函数中嵌入,如下:

vector<string>
vec(istream_iterator<string>(ifs),istream_iterator<string>);
 
    
以上代码当在copy中调用vec.begin(), vec.end()时,就会编译报错:
     
error: request for member `begin‘ in `vec‘,
which is of non-class type `std::vector<std::string,
std::allocator<std::string> > ()(std::istream_iterator<std::string,
char, std::char_traits<char>, ptrdiff_t>,
std::istream_iterator<std::string, char, std::char_traits<char>,
ptrdiff_t>)‘
error: request for member `end‘ in `vec‘, which
is of non-class type `std::vector<std::string,
std::allocator<std::string> > ()(std::istream_iterator<std::string,
char, std::char_traits<char>, ptrdiff_t>,
std::istream_iterator<std::string, char, std::char_traits<char>,
ptrdiff_t>)‘

看来编译器将vec当作了一个函数,而不是一个vector类。
其中istream_iterator<string>(ifs)
的括号被编译器忽略了,成为
 
  vector<string> vec(istream_iterator<string>
ifs,
     
istream_iterator<string>);

等同于:
 
  vector<string> fun(istream_iterator<string>
x,
      istream_iterator<string>
y);

4.
访止编译器误解

就像在加减乘除中用括号指定运算顺序一样,这里也要用括号将构造的临时参数括起来,访止编译器将它们误解为函数中的参数声明。
同时还要修正一个错误,vec构造函数中的第二个参数构造是错误的,应该加个括号构造一个临时变量。不然对
 
   
istream_iterator<string>);
报错:
error:
expected primary-expression before ‘)‘
token
因为它只是一个类型声明,而不是一个基本表达式(primary-expression)。

正确的方法如下:
 
  vector<string>
vec((istream_iterator<string>(ifs)),
     
istream_iterator<string>());

 
  vector<string>
vec((istream_iterator<string>(ifs)),
     
(istream_iterator<string>()));

该种方法虽然可行,但还是不用为好,以免某些编译器不支持,同时也增加代码理解难度,而且在更复杂的情形中,这一招也无法解决问题。还是第5种简化方法比较合适
提示:不管需不需要,稍微复杂一点的表达式都用括号括起来。免得人阅读时出错,或者编译器理解时出错。

5.
另一种简化方法

ibeg,
iend的定义可以合为一行,可能比内嵌式表达方法更清晰:
   
istream_iterator<string> ibeg(ifs), iend;
   
vector<string> vec(ibeg,
iend); 

http://blog.csdn.net/rickliuxiao/article/details/6201835

http://www.cppblog.com/jinq0123/archive/2007/12/12/istream_iterator_ErrorMsg.html

istream_iterator 在<iterator>头文件的定义中

定义istream_iterator变量的方法为

istream_iterator<T> in(strm);    (其中T指明此istream_iterator的输入类型
, strm为istream_iterator指向的流)

提供了输入操作符(>>)和 输出操作符 (<<)的任何类型都可以创建 istream_iterator
对象和ostream_iteratorcfq对象,即对自己的类重载了这两个函数:

istream &operator >> (istream &is, &MyClass c);

和 ostream &operator << (ostream &os , const  &MyClass
c);

1. 若strm为空时,即比如istream<T> in();时,  此时变量in
就相当于指向EOF标志的iterator了

如图如下定义: (下文的eoff是我故意这样写的,只是为了让大家明白这个名字随便起都行)

[cpp] view plaincopy

  1. istream_iterator<T> eoff ;

发现eoff的私有变量中_Myistr为0x000000000;

再看看一个定义: (注意:test.txt的内容为10(EOF) )

[cpp] view plaincopy

  1. ifstream infile("f:\\test.txt");

  2. istream_iterator<int> input(infile);

再用vs2008调试时查看:

大家发现没有:input变量的私有成员_Myistr不为0了! 且私有成员_Myval正好为10(即文件中的第一个整型数)

现在在执行下一行代码:

[cpp] view plaincopy

  1. ++input;

再用VS2008看看input的成员:

++input后,其私有成员_Myistr变为0x00000000了!和之前定义的eoff变量一样了!

再执行下一行看看会输出什么:

[cpp] view plaincopy

  1. cout<<(in == eoff ? "EOF" : "others")<<endl;

显然此时的in == eoff 成立,结果输出的是 "EOF"

现在我们知道了copy(input,eoff,back_inserter(ivec)这么用法的原因了吧。
 因为copy函数是通过input先与eoff比较是否相等,若不等则将其解引用(*input)插入到ivec的最后

然后再自加1,再与eoff比较.   直到与eoff比较相等时结束! 所以用未用流初始化的istream_iterator作为哨兵.

copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(ivec)也是一样的情况。
需要结束时按下ctrl+z产生EOF标志  ^z

完整程序如下:

[cpp] view plaincopy

  1. #include <iostream>

  2. #include <vector>

  3. #include <fstream>

  4. #include <iterator> //istream_iterator,ostream_iterator,back_inserter

  5. #include <algorithm> //copy

  6. #include <Windows.h> //system

  7. using namespace std;

  8. int main()

  9. {

  10. istream_iterator<int> eoff;

  11. ifstream infile("f:\\test.txt"); //运行前,请让f:\\test.txt里面只有一个整数

  12. istream_iterator<int> input(infile);

  13. cout<<"the first element:"<<*input<<endl;

  14. ++input;

  15. cout<<(input == eoff ? "EOF" : "others")<<endl;
  16. cout<<"*******************"<<endl;

  17. cout<<"请输入整数,按ctrl+z结束输入:"<<endl;

  18. vector<int> ivec;

  19. copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(ivec));

  20. //下句为将ivec内容输出屏幕

  21. copy(ivec.begin(),ivec.end(),ostream_iterator<int>(cout,"\t"));

  22. system("pause");

  23. }

ps: istream_iterator 和 ostream_iterator 都没有定义自减运算,即 --input; 是错误的!

2. 注意了如果对于istream_iterator<int> 型,如果文件里面是为字母的话,input会如何呢?

在此之前,请把f:\test.txt的加一个字母看什么情况 即内容为: 10   sfd(EOF)

[cpp] view plaincopy

  1. istream_iterator<int> eoff;

  2. ifstream infile("f:\\test.txt"); //运行前,请让f:\\test.txt里面只有一个整数

  3. istream_iterator<int> input(infile);

  4. cout<<"the first element:"<<*input<<endl;

  5. ++input;

运行这几句后,istream_iterator<int>
input(infile)应该只能指向整型,但现在为字母了,会如何呢?

我们看看现在的input的成员:

input遇到字母时,_Myistr也变为0x00000000了。那么是不说

[cpp] view plaincopy

  1. cout<<(input == eoff ? "EOF" : "others")<<endl;

也会输入“EOF”,即input == eoff呢?  答案确实是肯定的!

其实此时的cin.good()也为false了. 大家可以加一行代码试试:cout<<cin.good()<<endl;

现在我们知道了,当只需要整型时,使用istream_iterator<int>
(cin)输入时,也可以输入一个非int型的字母来终结输入。

对于ostream_iterator<T> ouput(strm,"xxx");也是一样,只是现在的output为左值为:

例如:

[cpp] view plaincopy

  1. ostream_iterator<int> output(cout," : ");

  2. *output = 5;

  3. *output = 6;

或者这样写

[cpp] view plaincopy

  1. ostream_iterator<int> output(cout," : ");

  2. *output++ = 5;

  3. *output++ = 6;

其结果都是:5 : 6

output每次解引用 *output后赋值后,都会使自己自加1  。

也就是说不用自己使用 *output++ 的方法了。

总之:

这两句是最好用的了:

[cpp] view plaincopy

  1. copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(ivec));

  2. //下句为将ivec内容输出屏幕

  3. copy(ivec.begin(),ivec.end(),ostream_iterator<int>(cout,"\t"));

输入那句更好的是

vector<int>
ivec(istream_iterator<int>(cin),istream_iterator<int>());

这句更简洁.

若写的有问题,请各位大侠指教。

转载请注明出处.

stream_iterator、ostream_iterator 使用初探,布布扣,bubuko.com

时间: 2024-10-14 23:36:05

stream_iterator、ostream_iterator 使用初探的相关文章

进阶之初探nodeJS

一.前言 在"初探nodeJS"随笔中,我们对于node有了一个大致地了解,并在最后也通过一个示例,了解了如何快速地开启一个简单的服务器. 今儿,再次看了该篇随笔,发现该随笔理论知识稍多,适合初级入门node,固萌生一个想法--想在该篇随笔中,通过一步步编写一个稍大一点的node示例,让我们在整体上更加全面地了解node. so,该篇随笔是建立在"初探nodeJS"之上的,固取名为"进阶之初探nodeJS". 好了,侃了这多,那么我们即将实现一个

从273二手车的M站点初探js模块化编程

前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数据. 273这个M站点是产品推荐我看的.第一眼看这个产品时我就再想他们这个三次加载和翻页按钮的方式,那么小分页的pageIndex是怎么计算的.所以就顺便看了下源码. 提到看源码时用到了Chrome浏览器的格式化工具(还是朋友推荐我的,不过这个格式化按钮的确不明显,不会的话自行百度). 三次加载和分

[转载]HDFS初探之旅

转载自 http://www.cnblogs.com/xia520pi/archive/2012/05/28/2520813.html , 感谢虾皮工作室这一系列精彩的文章. Hadoop集群(第8期)_HDFS初探之旅 1.HDFS简介 HDFS(Hadoop Distributed File System)是Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开发的,可以运行于廉价的商用服务器上.它所具有的高容错.高可靠性.高可扩展性.高

MongoDB初探系列之二:认识MongoDB提供的一些常用工具

在初探一中,我们已经可以顺利的将MongoDB在我们自己的机器上跑起来了.但是在其bin目录下面还有一些我们不熟知的工具.接下来,将介绍一下各个小工具的用途以及初探一中MongoDB在data文件夹下创建的文件的用途. 1.bin目录下面的各种小工具简介及使用方式 bsondump.exe 用于将导出的BSON文件格式转换为JSON格式mongo.exe mongoDB的客户端 mongod.exe 用于启动mongoDB的Server mongodump.exe 用于从mongodb数据库中导

Asynchronous Pluggable Protocols 初探

Asynchronous Pluggable Protocols,异步可插入协议,允许开发者创建可插协议处理器,MIME过滤器,以及命名空间处理器工作在微软IE4.0浏览器以及更高版本或者URL moniker中.这涉及到Urlmon.dll动态链接库所公开(输出)的可插协议诸多功能,本文不进行深入的原理讲解,只对它其中之一的应用进行解析,那就是如何将一个应用程序注册为URL协议. 应用场景: tencent协议: 当我们打开"tencent://message/?uin=要链接的QQ号 &qu

重新认识HTML,CSS,Javascript 之node-webkit 初探

今天我们来系统的.全面的 了解一下前端的一些技术,将有助于我们写出 更优秀的 产品 出来. 什么是HTML? HTML 是用来描述网页的一种语言. HTML 包含一些根节点,子节点,文本节点,属性节点,组成, 它通过一系列预定义标签来描述网页结构,如: <title>This is title</title> ,这个表明该网页的标题是 This is title. 什么是CSS? CSS 指层叠样式表 (Cascading Style Sheets),它描述浏览器显示如何显示htm

java进阶06 线程初探

线程,程序和进程是经常容易混淆的概念. 程序:就是有序严谨的指令集 进程:是一个程序及其数据在处理机上顺序执行时所发生的活动 线程:程序中不同的执行路径,就是程序中多种处理或者方法. 线程有两种方法实现 一:继承Thread 覆盖run方法 package Thread; public class Thread1 { public static void main(String[] args){ MyThread1 thread1=new MyThread1(); thread1.setName

数据加密解密初探

在一次网络通信或者是进程通信中,如果传输数据采用明文的方式,那么很容易被第三方"窃听"到,安全性难以保障. 而所谓加密是让数据从明文变成密文,传输过程中是密文,传送过去之后对方接收到的也是密文.--可以理解为密文就是乱码,看不出内在的任何意义,通常也都是逐位对应的. 在接收方接收到密文之后只有把它还原为原来的样子才可以理解对方说的具体是什么,此过程就叫做解密. 所谓系统的安全要实现的目标应该包括:机密性-confidentiality,完整性-integrity 和可用性-availa

Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用

一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性,不得不说下Http协议.我们常常听到说,Http是一个无状态协议,同一个会话的连续两个请求互相不了解,他们由最新实例化的环境进行解析,除了应用本身可能已经存储在全局对象中的所有信息外,该环境不保存与会话有关的任何信息.之所以我们在使用ASP.NET WebForm开发中会感觉不到Http的无状态特