虽然iostream类型不是容器,但标准库定义了可以用于这些IO类型对象的迭代器。
iostream_iterator读取输入流,ostream_iterator向一个输出流写数据。这些迭代器将它们对应的流当作一个特定类型的元素序列来处理,通过使用流迭代器,我们可以用泛型算法从流对象读取数据以及向其中写入数据。
istream_iterator操作
istream_iterator<int> in_iter(cin); // read ints from cin istream_iterator<int> eof; // istream "end" iterator
ifstream in("afile");
istream_iterator<string> str_it(in);
下面是一个用istream_iterator从标准输入读取数据,存入一个vector的例子。
循环从cin中读取int值,保存在vec中。在每个循环步中,循环体代码检查in_iter是否等于eof。eof被定义为空的istream_iterator,从而可以当作尾后迭代器来使用。对于一个绑定到流的迭代器,一旦关联的流遇到文件尾或遇到io错误,迭代器的值就与尾后迭代器相等。istream_iterator<int> in_iter(cin); // read ints from cin istream_iterator<int> eof; // istream "end" iterator // read until end of file, storing what was read in vec while (in_iter != eof) // increment advances the stream to the next value l// dereference reads next value from the istream vec.push_back(*in_iter++);
可以将程序改为如下形式
istream_iterator<int> in_iter(cin); // read ints from cin istream_iterator<int> eof; // istream "end" iterator vector<int> vec(in_iter, eof); // construct vec from an iterator range
iostream迭代器的构造函数 | ||
istream_iterator<T> in(strm); | 创建从输入流strm中读取T类型对象的istream_iterator对象 | |
istream_iterator<T> in; | istream_iterator 对象的超出末端迭代器 | |
ostream_iterator<T> in(strm); | 创建将T类型的对象写到输出流strm的ostream_iterator对象 | |
ostream_iterator<T> in(strm, delim); | 创建将 T 类型的对象写到输出流 strm 的ostream_iterator 对象,在写入过程中使用 delim作为元素的分隔符。delim 是以空字符结束的字符数组(C风格字符串)。 | |
istream_iterator 的操作 | ||
it1 == it2 it1 != it2 | 比较两上 istream_iterator 对象是否相等(不等)。迭代器读取的必须是相同的类型。如果两个迭代器都是 end 值,则它们相等。对于两个都不指向流结束位置的迭代器,如果它们使用同一个输入流构造 | |
*it | 返回从流中读取的值 | |
it->mem | 是 (*it).mem 的同义词。返回从流中读取的对象的 mem 成员 | |
++it it++ | 通过使用元素类型提供的 >> 操作从输入流中读取下一个元素值,使迭代器向前移动。通常,前缀版本使用迭代器在流中向前移动,并返回对加 1 后的迭代器的引用。而后缀版本使迭代器在流中向前移动后,返回原值 |
ostream_iterator操作
out =val 用<<运算符将val写入到out所绑定的ostream中,val的类型必须与out可写的类型兼容。
*out ++out out++ 这些运算符是存在的,但不对out做任何事,每个运算符都返回out。
我们可以用ostream_iterator来输出值的序列
ostream_iterator<int> out_iter(cout," ");
for(auto e: vec)
*out_iter++=e;
cout<<endl;
此程序将vec中的每个元素写的out,每个元素后加一个空格每次向out_iter赋值时,写操作就会被提交。
值得注意的,当我们向out_iter赋值时,可以忽略解引用和递增运算。因此,可以重写为下面的例子:
for(auto e: vec)
out_iter=e;
cout<<endl;
运算符*和++实际上对ostream_iterator对象不做任何事情,因此忽略它们对我们的程序没有影响。
可以通过调用copy来打印vec中的元素,这比编写循环更为简单
copy(vec.begin(),vec.end(),out_iter);
cout<<endl;
练习题例子
#include<iostream>
#include<vector>
using namespace std;
#include<iterator>
int main()
{
istream_iterator<int> cin_it(cin);
istream_iterator<int> end_of_stream;
vector<int> vec;
while(cin_it!=end_of_stream)
{
//注意++先引用后增值,不能写出前缀
vec.push_back(*cin_it++);
}
//也可以写成 vector<int> vec(cin_it,end_of_stream);
for(int i=0;i!=vec.size();i++)
cout<<vec[i];
return 0;
}
其中end_of_stream定义为空的迭代器对象,用作结束迭代器。绑定流上的迭代器在遇到文件结束或某个错误时,将等于结束迭代器的值。
int main(int argc, char **argv)
{
ostream_iterator<string> out_iter(cout, "\n");
istream_iterator<string> in_iter(cin), EndOfStream;
while(EndOfStream != in_iter)
{
*out_iter++ = *in_iter++;
}
return 0;
}
先iter++,返回iter,再*iter。
注意输出,输入 12 3 4 5,按 enter输出1 ,2 ,3 ,4,按ctrl+z输出5;
#include "map"
#include "set"
#include "vector"
#include "string"
#include "fstream"
#include "iostream"
#include "sstream"
#include "iterator"
#include "algorithm"
using namespace std;
int main(int argc, char **argv)
{
ifstream infile("C:\\1.txt");
istream_iterator<int> cin_it(infile);
istream_iterator<int> EndOfStream;
vector<int> vec(cin_it, EndOfStream);
sort(vec.begin(), vec.end());
ostream_iterator<int> output(cout, " ");
unique_copy(vec.begin(), vec.end(), output);
return 0;
}
copy输出的例子
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
int main()
{
ostream_iterator<int> intWriter(cout, "\n");
*intWriter = 42;
intWriter++;
*intWriter = 77;
intWriter++;
*intWriter = -5;
vector<int> coll;
for(int i = 1; i <= 9; ++i)
{
coll.push_back(i);
}
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout));
cout << endl;
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " < "));
cout << endl;
return 0;
}
3)流迭代器的限制
• 不可能从 ostream_iterator 对象读入,也不可能写到istream_iterator 对象中。
• 一旦给 ostream_iterator 对象赋了一个值,写入就提交了。赋值后,没有办法再改变这个值。此外,ostream_iterator 对象中每个不同的值都只能正好输出一次。
• ostream_iterator 没有 -> 操作符。