stream_iterator、ostream_iterator

http://www.xuebuyuan.com/686206.html

http://blog.csdn.net/rickliuxiao/article/details/6201835

http://www.cppblog.com/jinq0123/archive/2007/12/12/istream_iterator_ErrorMsg.html


STL定义了供输入及输出的iostream iterator类,称为 istream_iterator和ostream_iterator,分别支持单一型别的元素的读取和写入。 
使用方法: 
1.包含头文件: #include <iterator>  using namespace std;       
2.像使用其他iterator一样使用istream_iterator和 ostream_iterator。如:
  使用一对“连接至标准输入”的iterator用于标示元素范围: 
   // 将is定义为一个“连接至标准输入装置”的istream_iterator 
   istream_iterator<string> is(cin); 
   // 定义istream_iterator时不为它指定istream对象,它即代表了end-of-file。 
   istream_iterator<string> eof; 
   ostream_iterator<string> os(cout, " "); 
 除了“连接至标准输入”外,还可以连接至其他设备,如文件: 
 

#include <fstream> 
 using namespace std; 
 ifstream in_file("in.txt"); 
 ofstream out_file("in.txt"); 
 if ( !in_file || !out_file ) 
 { 
         cerr << "failed to open the necessary file! /n"; 
          return -1; 
 } 
 istream_iterator<string> is(in_file); 
 istream_iterator<string> eof; 
 ostream_iterator<string> os(out_file, " "); 

***********************************************************************************************

#include <iostream>   
#include <iterator>   
#include <string>   
#include <vector>   
#include <fstream>   
#include <algorithm>   
using namespace std;  
int main()  
{  
    // 1. 标准输入输出操作。   
    istream_iterator<string> is(cin);  
    istream_iterator<string> eof;  
    vector<string> text;  
    // 将标准输入的内容复制至text中。  由于使用的是vector,故使用back_inserter()   
    copy(is, eof, back_inserter(text));    
    // do something.   
    sort(text.begin(), text.end());  
    // 输出至标准输出。   
    ostream_iterator<string> os(cout, " ");  
    copy(text.begin(), text.end(), os);  
    // 2. 非标准输入输出操作:文件读写操作。   
    ifstream in_file("in.txt");  
    ofstream out_file("in.txt");  
    if ( !in_file || !out_file )  
    {  
        cerr << "failed to open the necessary file! /n";  
        return -1;  
    }  
    istream_iterator<string> is2(in_file);  
    istream_iterator<string> eof2;  
    vector<string> text2;  
    copy(is2, eof2, back_inserter(text2));  
sort(text2.begin(), text2.end());  
    ostream_iterator<string> os2(out_file, " ");  
    copy(text2.begin(), text2.end(), os2);  
    return 0;  
}  

************************************************************************************

istream_iterator常见错误

1. 错误原码

以下原代码不能通过编译:

    ifstream ifs("test.txt");
    istream_iterator<string> ibeg(ifs);
    istream_iterator<string> iend();
    vector<string> vec(ibeg, iend);

对于vec的构造编译出错:
error: no matching function for call to `std::vector<std::string, std::allocator<std::string> >::vector(std::istream_iterator<std::string, char, std::char_traits<char>, ptrdiff_t>&, std::istream_iterator<std::string, char, std::char_traits<char>, ptrdiff_t>
(&)())'

原来它把iend当作了一个函数。去掉iend后面的括号就行了:

2. 正确的完整代码

#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;


int main()
{
    ifstream ifs("test.txt");
    istream_iterator<string> ibeg(ifs);
    istream_iterator<string> iend;
    vector<string> vec(ibeg, iend);


    copy(vec.begin(), vec.end(),ostream_iterator<string>(cout, "\n"));
    return 0;
}

3. 直接内嵌出错

就像在copy函数中一样,并不需要定义ibeg, iend, 应该可以在vector的构造函数中嵌入,如下:

vector<string> vec(istream_iterator<string>(ifs),istream_iterator<string>);
      
以上代码当在copy中调用vec.begin(), vec.end()时,就会编译报错:      
error: request for member `begin' in `vec', which is of non-class type `std::vector<std::string, std::allocator<std::string> > ()(std::istream_iterator<std::string, char, std::char_traits<char>, ptrdiff_t>, std::istream_iterator<std::string, char, std::char_traits<char>,
ptrdiff_t>)'
error: request for member `end' in `vec', which is of non-class type `std::vector<std::string, std::allocator<std::string> > ()(std::istream_iterator<std::string, char, std::char_traits<char>, ptrdiff_t>, std::istream_iterator<std::string, char, std::char_traits<char>,
ptrdiff_t>)'

看来编译器将vec当作了一个函数,而不是一个vector类。
其中istream_iterator<string>(ifs)
的括号被编译器忽略了,成为
    vector<string> vec(istream_iterator<string> ifs,
      istream_iterator<string>);

等同于:
    vector<string> fun(istream_iterator<string> x,
      istream_iterator<string> y);

4. 访止编译器误解

就像在加减乘除中用括号指定运算顺序一样,这里也要用括号将构造的临时参数括起来,访止编译器将它们误解为函数中的参数声明。
同时还要修正一个错误,vec构造函数中的第二个参数构造是错误的,应该加个括号构造一个临时变量。不然对
      istream_iterator<string>);
报错:
error: expected primary-expression before ')' token
因为它只是一个类型声明,而不是一个基本表达式(primary-expression)。

正确的方法如下:
    vector<string> vec((istream_iterator<string>(ifs)),
      istream_iterator<string>());

    vector<string> vec((istream_iterator<string>(ifs)),
      (istream_iterator<string>()));

该种方法虽然可行,但还是不用为好,以免某些编译器不支持,同时也增加代码理解难度,而且在更复杂的情形中,这一招也无法解决问题。还是第5种简化方法比较合适
提示:不管需不需要,稍微复杂一点的表达式都用括号括起来。免得人阅读时出错,或者编译器理解时出错。

5. 另一种简化方法

ibeg, iend的定义可以合为一行,可能比内嵌式表达方法更清晰:
    istream_iterator<string> ibeg(ifs), iend;
    vector<string> vec(ibeg, iend); 

 ostream_iterator属于I/O流STL适配器,用于获取一个元素,同时保存在缓冲器中,可以供Cout输出。如果把cout看做成一个对 象,那么在Cout对象当中存在一片用于数据存储的区域。ostream_iterator在STL中一般配合copy函数一起使用,如下代码;

   ostream_iterator output(cout, " "); //关联cout,设置分隔符     copy(ivec.begin(), ivec.end(), output); //元素拷贝到ostream_iterator所指向的对象cout     cout; //显示cout的值

    ostream_iterator中,template如果是一个类名称的时候,那么这个类必须实现重载”<<”输出运算符号,用于数据的输出。如下代码;

class Person { public:         Person(const string& firstname,const string& lastname)         {                 this->firstname=firstname;                 this->lastname=lastname;         } //如果没有const,那么下面的copy()会报告一堆错误,重载为const是一个好习惯         friend ostream& operator <<(ostream& os,const Person& p)         {                 os<        } private:         string firstname ;         string lastname ;         friend class PersonSort; }; class PersonSort {   public:         bool operator()(const Person& p1,const Person& p2) const         {                 return (p1.lastname        } }; int main() {         typedef set PersonSet;         PersonSet ps;         ps.insert(Person("hongjian","chen"));         ps.insert(Person("lizhong","li"));         ps.insert(Person("xuan","liu")); copy(ps.begin(),ps.end(),ostream_iterator(cout,"/n")); return 0; }

      另外、

template    class _Tr = char_traits<_E> >     class ostream_iterator         : public iterator

  从这段代码中亦可以发现,ostream_iterator继承iterator,iterator通过output_iterator_tag来标记定义的iterator为ostream适配器。

 

ostream_iterator<int>(cout, " ")的解释

ostream_iterator是流迭代器。
流迭代器是标准模板库中的。因此是类模板。
ostream_iterator<int>
指定了类型,就是迭代器读写的类型。
通过这个流迭代器可以把你要输入的写入到指定的流中。
cout就是指定的流。就是标准输出。
可以改成一个输出流就可以,比如一个文件。
通俗的一点说,你把它看成一个指向输出流的指针。通过这个指针你可以把东西写的输出流中。
copy (v.begin(),v.end(),output);
这个意思就是说,把向量V中的数据放到cout输出流中,通过流迭代器output.
ostream_iterator<int> output(cout ,"*");
这个的意思说,放到输出流的时候,没放一个整数,就末尾添加一个*.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值