istream_iterator和ostream_iterator学习体会

转载自fdl19881


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是我故意这样写的,只是为了让大家明白这个名字随便起都行)

istream_iterator<T> eoff ;
  
  

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

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


  
  
  1. ifstream infile("f:\\test.txt");
  2. istream_iterator< int> input(infile);

再用vs2008调试时查看:


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

现在在执行下一行代码:

	++input;
  
  

再用VS2008看看input的成员:


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

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

	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

完整程序如下:


  
  
  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)


  
  
  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了。那么是不说

	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为左值为:

例如:


  
  
  1. ostream_iterator< int> output( cout, " : ");
  2. *output = 5;
  3. *output = 6;

或者这样写


  
  
  1. ostream_iterator< int> output( cout, " : ");
  2. *output++ = 5;
  3. *output++ = 6;
其结果都是:5 : 6

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

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



总之:

这两句是最好用的了:


  
  
  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>());

这句更简洁.

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

转载请注明出处.


发布了222 篇原创文章 · 获赞 48 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_44116998/article/details/104596985
今日推荐