istream_iterator和ostream_iterator学习体会

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

	ifstream infile("f:\\test.txt");
	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

完整程序如下:

#include <iostream>
#include <vector>
#include <fstream>
#include <iterator> //istream_iterator,ostream_iterator,back_inserter
#include <algorithm> //copy
#include <Windows.h> //system
using namespace std;
int main()
{
	istream_iterator<int> eoff;
	ifstream infile("f:\\test.txt"); //运行前,请让f:\\test.txt里面只有一个整数
	istream_iterator<int> input(infile);
	cout<<"the first element:"<<*input<<endl;
	++input;
	cout<<(input == eoff ? "EOF" : "others")<<endl;

	cout<<"*******************"<<endl;
	cout<<"请输入整数,按ctrl+z结束输入:"<<endl;
	vector<int> ivec;
	copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(ivec));
	//下句为将ivec内容输出屏幕
	copy(ivec.begin(),ivec.end(),ostream_iterator<int>(cout,"\t"));
	system("pause");
}


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

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

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

	istream_iterator<int> eoff;
	ifstream infile("f:\\test.txt"); //运行前,请让f:\\test.txt里面只有一个整数
	istream_iterator<int> input(infile);
	cout<<"the first element:"<<*input<<endl;
	++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为左值为:

例如:

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

或者这样写

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

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

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



总之:

这两句是最好用的了:

	copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(ivec));
	//下句为将ivec内容输出屏幕
	copy(ivec.begin(),ivec.end(),ostream_iterator<int>(cout,"\t"));

输入那句更好的是

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

这句更简洁.

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

转载请注明出处.


你可能感兴趣的:(Algorithm,OS,iterator,System,input,output)