虽然iostream类型不是容器,但标准库定义了可以用于这些IO类型对象的迭代器。
istream_iterator读取输入流,ostream_iterator向一个输入流写数据.这些迭代器将它们对应的流当做一个特定类型的元素序列来处理.通过使用流迭代器,我们可以用泛型算法从流对象读取数据以及向其写入数据.
注意: 当创建一个流迭代器时,必须指定迭代器将要读写的对象类型。
代码如下:
istream_iterator<int> int_it(cin);//从cin读取int
istream_iterator<int> int_eof;//尾后迭代器
ifstream in("afile");//打开一个aflie的文件
istream_iterator<string> str_it(in);//从"afile"读取字符串
下面是一个用istream_iterator从标准输入读取数据,存入一个vector的例子:
istream_iterator<int> int_iter(cin);//从cin读取int
istream_iterator<int> eof;//istream尾后迭代器
vector<int> vec;
while (int_iter != eof)//当有数据可供读取时
{
//后置递增运算符,返回迭代器的旧值
//解引用迭代器,获得从流读取的前一个值
vec.push_back(*int_iter++);
}
此循环从cin读取int值,保存在vec中.
在每个循环步中,循环体代码检查in_iter是否等于eof.
eof被定义为空的istream_iterator,从而可以当做尾后迭代器来使用.
对于一个绑定到流的迭代器,一旦其关联的流遇到文件尾或遇到IO错误,迭代器的值就与尾后迭代器相等
对于传递给push_back的参数,其中用到了解引用运算符和后置递增运算符。
后置递增运算会从流中读取下一个值,向前推进,但返回的迭代器时迭代器的旧值。迭代器的旧值包含了从流中读取的前一个值,对迭代器进行解引用就能获得此值
注意: 后置递增运算会从流中读取下一个值
istream_iterator<int> int_iter(cin), eof;//从cin中读取int
vector<int> vec(int_iter,eof);//从迭代器范围构造vec
istream_iterator操作 | |
---|---|
istream_iterator< T > in(is) | in从输入流is读取类型为T的值 |
istream_iterator< T > end | 读取类型为T的值的istream_iterator迭代器,表示尾后的位置 |
in1==in2 | in1和in2必须读取相同的类型。如果他们都是尾后迭代器,或绑定到相同的输入,则两者相等 |
in1!=in2 | 相等的条件不满足则为不等 |
*in | 返回从流中读取的值 |
in->mem | 与(*in).mem的含义相同 |
++in,in++ | 使用元素类型所定义的>>运算符从输入流中读取下一个值。与以往一样,前置版本返回一个指向递增后的迭代器的引用,后置版本返回旧值 |
使用算法操作流迭代器
istream_iterator<int> in(cin), eof;
cout << accumulate(in, eof, 0) << endl;
istream_iterator可以使用懒惰求值
ostream_iterator操作 | |
---|---|
ostream_iterator< T > out(os) | out将类型为T的值写到输出流os中 |
ostream_iterator< T > out(os,d) | out将类型为T的值写到输出流os中,每个值后面都输出一个d。d指向一个空字符结尾的字符数组 |
out=val | 用<<运算符将val写入到out所绑定的ostream中,val的类型必须与out可写的类型兼容 |
*out,++out,out++ | 这些运算符是存在的,但不对out做任何事。每个运算符都返回out |
代码如下:
vector<int> vec(10, 1);
ostream_iterator<int> out_iter(cout, " ");
for (auto e : vec)
*out_iter++ = e;//赋值语句实际上将元素写到cout
cout << endl;
vector<int> vec(10, 1);
ostream_iterator<int> out_iter(cout, " ");
for (auto e : vec)
out_iter= e;//赋值语句实际上将元素写到cout
cout << endl;
注意: 运算符*和++实际上对ostream_iterator对象不做任何事情,因此忽略它们对我们的程序没有任何影响。
但是,推荐第一种写法,在这种写法中,流迭代器的使用和其他迭代器的使用保持一致。如果想要将此循环改为操作其他迭代器的类型,修改起来非常容易.而且,对于读者来说,此循环的行为也更为清晰。
vector<int> vec(10, 1);
ostream_iterator<int> out_iter(cout, " ");
copy(vec.begin(), vec.end(), out_iter);
cout << endl;
以上就是今天要讲的内容,但是额外补充一点,我们还可以使用流迭代器处理类类型,前提是类型定义了>>和<<运算符。