首页 > 代码库 > 【足迹C++primer】33、再探迭代器

【足迹C++primer】33、再探迭代器

再探迭代器

这里有插入迭代器,有流迭代器,反向迭代器,移动迭代器。

插入迭代器

这是一种迭代器适配器,接受一个容器,生成一个迭代器,实现向给定容器添加元素。

插入迭代器有三种类型,差异在于元素插入的位置
back_inserter创建一个使用push_back的迭代器。
front_inserter创建一个使用push_front的迭代器。
inserter创建一个使用insert的迭代器。

void fun1()
{
    list<int> lst={1,2,3,4};
    list<int> lst2, lst3;   //空list
    //拷贝完成之后,lst2包含4,3,2,1
    copy(lst.cbegin(), lst.cend(), front_inserter(lst2));
    //拷贝完成之后,lst3包含1 2 3 4
    copy(lst.cbegin(), lst.cend(), inserter(lst3, lst3.begin()));

    for(list<int>::iterator t=lst.begin(); t != lst.end(); ++t)
    {
        cout<<*t<<"\t";
    }
    cout<<endl;

    for(list<int>::iterator t=lst2.begin(); t != lst2.end(); ++t)
    {
        cout<<*t<<"\t";
    }
    cout<<endl;

    for(list<int>::iterator t=lst3.begin(); t != lst3.end(); ++t)
    {
        cout<<*t<<"\t";
    }
    cout<<endl;


}

全都是代码,哦哦哦哦哦哦,全都是代码!!!!!哦哦哦哦哦,不是泡沫!!!!
void fun2()
{
    //10.27
    //用unique_copy将vector中不重复的元素拷贝到一个初始值为空的list中
    vector<int> v1={1,2,3,3,4,5,5,7,7,8,9,10};
    list<int> l1(13);   //空list
    list<int>::iterator it1=unique_copy(v1.begin(), v1.end(), l1.begin());

    cout<<"调用unique_copy得到list的值是:"<<endl;
    for(list<int>::iterator it=l1.begin() ; it != l1.end() ; ++it)
    {
        cout<<*it<<"\t";    //输出结果:1 2 3 4 5 6 7 8 9 10 0 0 0 0
    }
}

iostream迭代器

istream_iterator读取输入流,ostream_iterator向输出流写数据。
这个好像是有点很新奇的样子,不过我不怕!!!!
专注点,特么别老走神啊!!!!
//可以用一对istream_iterator来调用accumulate
void fun3()
{
    istream_iterator<int> in(cin), eof;
    cout<<accumulate(in, eof, 0)<<endl;
}


istream_iterator允许使用懒惰求值

就是可以推迟从流中读取数据的时间。

ostream_iterator操作

这里使用了一个头文件!!!
Sales_item.h
#ifndef SALESITEM_H
// we're here only if SALESITEM_H has not yet been defined 
#define SALESITEM_H

// Definition of Sales_item class and related functions goes here
#include <iostream>
#include <string>

class Sales_item {
// these declarations are explained section 7.2.1, p. 270 
// and in chapter 14, pages 557, 558, 561
friend std::istream& operator>>(std::istream&, Sales_item&);
friend std::ostream& operator<<(std::ostream&, const Sales_item&);
friend bool operator<(const Sales_item&, const Sales_item&);
friend bool 
operator==(const Sales_item&, const Sales_item&);
public:
    // constructors are explained in section 7.1.4, pages 262 - 265
    // default constructor needed to initialize members of built-in type
    Sales_item(): units_sold(0), revenue(0.0) { }
    Sales_item(const std::string &book): 
                  bookNo(book), units_sold(0), revenue(0.0) { }
    Sales_item(std::istream &is) { is >> *this; }
public:
    // operations on Sales_item objects
    // member binary operator: left-hand operand bound to implicit this pointer
    Sales_item& operator+=(const Sales_item&);
    
    // operations on Sales_item objects
    std::string isbn() const { return bookNo; }
    double avg_price() const;
// private members as before
private:
    std::string bookNo;      // implicitly initialized to the empty string
    unsigned units_sold;
    double revenue;
};

// used in chapter 10
inline
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs) 
{ return lhs.isbn() == rhs.isbn(); }

// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);

inline bool 
operator==(const Sales_item &lhs, const Sales_item &rhs)
{
    // must be made a friend of Sales_item
    return lhs.units_sold == rhs.units_sold &&
           lhs.revenue == rhs.revenue &&
           lhs.isbn() == rhs.isbn();
}

inline bool 
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
    return !(lhs == rhs); // != defined in terms of operator==
}

// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs) 
{
    units_sold += rhs.units_sold; 
    revenue += rhs.revenue; 
    return *this;
}

// assumes that both objects refer to the same ISBN
Sales_item 
operator+(const Sales_item& lhs, const Sales_item& rhs) 
{
    Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return
    ret += rhs;           // add in the contents of (|rhs|) 
    return ret;           // return (|ret|) by value
}

std::istream& 
operator>>(std::istream& in, Sales_item& s)
{
    double price;
    in >> s.bookNo >> s.units_sold >> price;
    // check that the inputs succeeded
    if (in)
        s.revenue = s.units_sold * price;
    else 
        s = Sales_item();  // input failed: reset object to default state
    return in;
}

std::ostream& 
operator<<(std::ostream& out, const Sales_item& s)
{
    out << s.isbn() << " " << s.units_sold << " "
        << s.revenue << " " << s.avg_price();
    return out;
}

double Sales_item::avg_price() const
{
    if (units_sold) 
        return revenue/units_sold; 
    else 
        return 0;
}
#endif

然后这才是正文!!

//使用流迭代器处理类类型
void fun4()
{
    istream_iterator<Sales_item> item_iter(cin), eof;
    ostream_iterator<Sales_item> out_iter(cout, "\n");
    //将第一笔交易记录在sum中,并读取下一条记录
    Sales_item sum=*item_iter++;
    while(item_iter != eof)
    {
        //如果当前交易记录(存在item_it中)有着相同的ISBN号
        if(item_iter->isbn() == sum.isbn())
            sum+=*item_iter++;      //将其加到sum上并读取下一条记录
        else
        {
            out_iter=sum;   //输出当前sum的值
            sum=*item_iter++;   //读取下一条记录
        }
    }
    
    out_iter=sum;       //记得打印最后一组记录的和
}

反向迭代器

就是从尾元素向首元素移动的意思,这个时候++就是向首元素移动一个单位。
除了forward_list外,其余容器都支持这个玩意!!!
void fun5()
{
    //下面的循环是一个使用反向迭代器的例子,按逆序打印vec中的元素
    vector<int> vec={0,1,2,3,4,5,6,7,8,9};
    //从尾元素到首元素的反向迭代器
    for(auto r_iter=vec.crbegin() ; r_iter != vec.crend() ; ++r_iter)
    {
        //将r_iter绑定到尾元素,crend指向首元素的位置,实际上是递减移动到抢一个元素
        cout<<*r_iter<<endl;    //打印9,8,7,6,5,4,3,2,1,0
    }

}

这里有一个细节注意一下,for循环里面那个r_iter的类型不是vector<int>::iterator类型的,所以不要搞错了,别学哥得意!!!
但是如果这是个反向的迭代器,我又不想用,我想要一个正向的!!!
那么这里还有一个好办法!!!
调用reverse_iterator的base成员函数来完成这个转换。

这里从技术层面上讲啊!!!这都越来越像咆哮体了- -#

普通迭代器和反向迭代器的关系反映了左闭合区间的特性,
[line.crbegin(), rcomma)[rcomma.base(), line.cend())指向line中相同的元素范围。

PS:越来越难了,感觉这书是不是排版有问题 啊!!!怎么有些地方讲得莫名其妙啊!!难道非要逼我看英文版????