zoukankan      html  css  js  c++  java
  • STL_iterator迭代器(2)——几种迭代器对象的用法

    要学会使用迭代器和容器以及算法,需要学习下面的新技术。

    一、流和迭代器

    本书的很多例子程序使用I/O流语句来读写数据。例如:

    1 int value;
    2 cout << "Enter value: ";
    3 cin >> value;
    4 cout << "You entered " << value << endl;

    对于迭代器,有另一种方法使用流和标准函数。理解的要点是将输入/输出流作为容器看待。因此,任何接受迭代器参数的算法都可以和流一起工作。

     1 //outstrm.cpp
     2 #include <iostream>
     3 #include <cstdlib>        // Need rand(), srand()
     4 #include <ctime>          // Need time()
     5 #include <algorithm>       // Need sort(), copy()
     6 #include <vector>          // Need vector
     7 #include <iterator>        // 坑爹的教程!!,Need for ostream_iterator
     8 using namespace std;
     9  
    10 void Display(vector<int>& v, const char* s);
    11  
    12 int main()
    13 {
    14       // Seed the random number generator
    15       srand( time(NULL) );
    16  
    17       // Construct vector and fill with random integer values
    18       vector<int> collection(10);
    19       
    20       for (int i = 0; i < 10; i++)
    21       {
    22         collection[i] = rand() % 10000;
    23       }
    24  
    25       // Display, sort, and redisplay
    26       Display(collection, "Before sorting");
    27       sort(collection.begin(), collection.end());
    28       Display(collection, "After sorting");
    29       return 0;
    30 }
    31  
    32 // Display label s and contents of integer vector v
    33 void Display(vector<int>& v, const char* s)
    34 {
    35       cout << endl << s << endl;
    36       copy(v.begin(), v.end(), ostream_iterator<int>(cout, "	"));
    37       cout << endl;
    38 }

    函数Display()显示了如何使用一个输出流迭代器。下面的语句将容器中的值传输到cout输出流对象中:

    copy(v.begin(), v.end(),ostream_iterator<int>(cout, " "));

    第三个参数实例化了ostream_iterator<int>类型,并将它作为copy()函数的输出目标迭代器对象。“ ”字符串是作为分隔符。

    这是STL神奇的一面『确实神奇』。为定义输出流迭代器,STL提供了模板类ostream_iterator。这个类的构造函数有两个参数:一个ostream对象和一个string值

    因此可以象下面一样简单地创建一个迭代器对象:

    ostream_iterator<int>(cout, " ")

    该迭代器可以和任何接受一个输出迭代器的函数一起使用。

    二、插入迭代器

    插入迭代器用于将值插入到容器中。它们也叫做适配器,因为它们将容器适配或转化为一个迭代器,并用于copy()这样的算法中。例如,一个程序定义了一个链表和一个矢量容器:

    list<double> dList;

    vector<double> dVector;

    通过使用front_inserter迭代器对象,可以只用单个copy()语句就完成将矢量中的对象插入到链表前端的操作:

    copy(dVector.begin(), dVector.end(), front_inserter(dList));

    三种插入迭代器如下:

    • inserter 将对象插入到容器任何对象的前面。
    • front_inserter 将对象插入到数据集的前面——例如,链表表头。
    • back_inserter 将对象插入到集合的尾部——例如,矢量的尾部,导致矢量容器扩展。

    使用插入迭代器可能导致容器中的其他对象移动位置,因而使得现存的迭代器非法。例如,将一个对象插入到矢量容器将导致其他值移动位置以腾出空间。一般来说,插入到象链表这样的结构中更为有效,因为它们不会导致其他对象移动。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <list>
     4 #include <iterator>
     5  
     6 using namespace std;
     7  
     8 int iArray[5] = { 1, 2, 3, 4, 5 };
     9  
    10 void Display(list<int>& v, const char* s);
    11  
    12 int main()
    13 {
    14       list<int> iList;
    15  
    16     // Copy iArray backwards into iList
    17     
    18     copy(iArray, iArray + 5, front_inserter(iList));    //5 4 3 2 1
    19     //copy(iArray, iArray + 5, inserter(iList, iList.begin()));    //1 2 3 4 5
    20     //copy(iArray, iArray + 5, back_inserter(iList));    //1 2 3 4 5
    21     
    22     Display(iList, "Before find and copy");
    23      
    24     // Locate value 3 in iList
    25     list<int>::iterator p = find(iList.begin(), iList.end(), 3);
    26      
    27     // Copy first two iArray values to iList ahead of p
    28     copy(iArray, iArray + 2, inserter(iList, p));        //插入1 2到3的前面 
    29     Display(iList, "After find and copy");
    30      
    31     return 0;
    32 }
    33  
    34 void Display(list<int>& a, const char* s)
    35 {
    36       cout << s << endl;
    37       copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
    38       cout << endl;
    39 }

    使用front_inserter插入到链表的前端的时候,数据会倒过来- -

    使用普通插入器inserter指定插入到链表前端和使用back_inserter数据都是按照原顺序输出的。。

    三、混合迭代器函数

    在涉及到容器和算法的操作中,还有两个迭代器函数非常有用:

    • advance() 按指定的数目增减迭代器。
    • distance() 返回到达一个迭代器所需(递增)操作的数目。
     1 #include <iostream>
     2 #include <algorithm>
     3 #include <list>
     4 using namespace std;
     5  
     6 int iArray[5] = { 1, 2, 3, 4, 5 };
     7  
     8 int main()
     9 {
    10     list<int> iList;
    11     
    12     copy(iArray, iArray + 5, inserter(iList, iList.begin()));    //1 2 3 4 5
    13     
    14     list<int>::iterator p =find(iList.begin(), iList.end(), 2);
    15     
    16     cout << "before: p == " << *p << endl;
    17     advance(p, 3);  // same as p = p + 2;        向后移动3位 
    18     cout << "after : p == " << *p << endl;
    19      
    20     int k = distance(p, iList.end());            //起始位置在前,终止位置在后 
    21     cout << "k == " << k << endl;
    22     
    23     k = distance(p, iList.begin());        //2 STL中list是双向循环链表 
    24     cout << "k == " << k << endl;
    25     
    26     k = distance(iList.begin(), p);        //4 
    27     cout << "k == " << k << endl;
    28     
    29     //begin指向第一个位置,end指向最后一个位置的后一个位置 
    30     //cout << *iList.begin() << endl;
    31     //cout << *iList.end() << endl;
    32     return 0;    
    33 }

    advance()函数接受两个参数。第二个参数是向前推进的数目。对于前推迭代器,该值必须为正,而对于双向迭代器和随机访问迭代器,该值可以为负。

    (这不是往后推进的吗?呃。。。不知道作者有没有搞错- -以上是作者原话)

    使用 distance()函数来返回到达另一个迭代器所需要的步骤。

    前者到后者的步数

    ——现在的努力是为了小时候吹过的牛B!!
  • 相关阅读:
    SQL 游标使用实例 no
    C# DataTable 转换成JSON数据 no
    css设置滚动条的样式 no
    C# DataTable 转换成JSON数据 no
    springboot项目打包jar 并打包为exe启动
    springboot 项目启动自动打开浏览器访问网站设置
    springboot启动创建系统托盘及功能
    关于Web Service
    最近的我
    C++ wstring和string相互转换
  • 原文地址:https://www.cnblogs.com/pingge/p/3217086.html
Copyright © 2011-2022 走看看