iostream Iterator本质上也是迭代器,所以在使用的时候,把它想象成能自动写入输出的迭代器就行,其他普通迭代器有的功能,它都有。
先看代码
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
istream_iterator<string> is(cin);//将is绑定到标准输入设备上
istream_iterator<string> eof;//标识输入流的结尾
vector<string> text;
copy(is, eof, back_inserter(text));//将数据输入text
sort(text.begin(), text.end());//排序
ostream_iterator<string> os(cout, " ");//将os绑定到标准输出设备上
copy(text.begin(), text.end(), os);//输出
}
就像我们使用其他的迭代器一样,istream Iterator迭代器也需要一组两个,用来分别表示操作的起点和终点。
由于istream_terator使用>>来读取流,所以所读取的流的类型必须是定义了输入运算符的,可以是已定义的或者自定义重载的输入运算符,都可以。
注意此处不一定要用这种方式定义流的结尾// istream_iterator eof;//标识输入流的结尾 //
也可以用不匹配的数据来定义结尾,例如指定了输入流为int类型(istream_iterator< int > is(cin))但是在流中出现了字符类型,此时就会判断成到达尾,输入流停止。
观察最上面的这段代码,可以发现我用了算法来操作流迭代器,这样是合法的吗?答案是肯定的。语法是允许用算法来操作流迭代器的,这样我们就可以直接使用流迭代器来对流中的数据来进行处理,无论是存储、算术运算,还是直接输出。
一个小注意点,标准库并不会保证在我们将istream_iterator绑定到流之后,迭代器立即读取流中的数据,它会在我们使用流迭代器的时候读取数据。但是标准库一定会保证我们第一次解引用迭代器之前读取流中的数据。这种情况下,如果有两个对象同时对一个流进行读取,不同的读取时间可能会造成读取的流的数据有差异,即另一对象可能对数据进行了篡改。
ostream_iterator
输出流迭代器的用法与输入流大同小异,将迭代器与标准输出设备绑定即可。
ostream_iterator<string> os(cout, " ");
for (auto i : text)
*os++ = i;
//os = i;
cout << endl;
这里将os绑定到标准输出设备,下面的赋值语句,实际上是将元素写到cout,其实这里可以不用自增和解引用,这两个操作都不会对输出流迭代器造成影响,这样写是为了程序的复用性和可读性。
文件操作
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int main()
{
ifstream in_file("D:\\input_file.txt");
ofstream out_file("D:\\output_file.txt");
if (!in_file || !out_file)
{
cerr << "no open files\n";
return -1;
}
istream_iterator<string> is(in_file);
istream_iterator<string> eof;
vector<string> text;
copy(is, eof, back_inserter(text));
sort(text.begin(), text.end());
ostream_iterator<string> os(out_file, " ");
copy(text.begin(), text.end(), os);
}
这是文件流迭代器操作,和标准设备大同小异,看看即可。
总结:流迭代器的操作简单,可以理解为将数据与迭代器绑定,而迭代器又与标准输入输出设备绑定,从而可以对数据进行输入输出,而具体输入输出形式,就由迭代器+算法决定,文件操作也是如此。