程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> 自定義一個簡單的迭代器(line_iterator)

自定義一個簡單的迭代器(line_iterator)

編輯:關於C

STL是容器、迭代器、算法三位一體的好東西,使用STL編寫的程序看起來非常簡潔。比如從cin輸入若干字符串,每一字符串占一行,然後將這些字符串按字典序排序並輸出到cout中,相關的代碼如下所示:
/* 迭代器的使用
 * created: ume
 * date: 2011-12-17
 *
 */ 
#include<iostream> 
#include<vector> 
#include<string> 
#include<iterator> 
#include<algorithm> 
using namespace std; 
int main() 

    vector<string> v; 
    string temp; 
    while(getline(cin,temp)) 
    { 
        v.push_back(temp); 
    } 
    sort(v.begin(),v.end()); 
    copy(v.begin(),v.end(),ostream_iterator<string>(cout," ")); 
    system("pause"); 
    return 0; 

包含的頭文件非常:
主函數中用到cin/cout以及getline,因此必須包含iostream;
主函數中用到vector<string>,因此必須包含vector和string;
主函數中用到ostream_iterator,因此必須包含iterator;
主函數還調用了sort和copy函數,因此必須包含algorithm。
除了iostream外,其它頭文件都是STL頭文件。vector和string是容器,iterator是迭代器,algorithm是算法。
編譯運行此程序,結果如下所示:
you 
are 
the 
apple 
of 
my 
eye 
^Z 
apple are eye my of the you 請按任意鍵繼續. . . 
如果想倒過來排,只要在把sort(v.begin(),v.end())改寫成sort(v.begin(),sort.end(),greater<string>())即可。
現在我們提出一個稍微高一點的要求,上面的程序不是將cout包裝到迭代器裡了嗎,能不能將cin也包裝到迭代器裡面呢?當然是可以,我們定義一個類來實現:
/* line_iterator.h
 * created: ume
 * date: 2011-12-17
 *
 */ 
class line_iterator 

    istream* in; 
    string line; 
    bool is_valid; 
    void read() 
    { 
        if(*in) 
            getline(*in,line); 
        is_valid = (*in) ? true : false; 
    } 
 
public: 
    typedef input_iterator_tag iterator_category; 
    typedef string value_type; 
    typedef ptrdiff_t difference_type; 
    typedef const string* pointer; 
    typedef const string& reference; 
 
    reference operator*() 
    { 
        return line; 
    } 
    pointer operator->() 
    { 
        return &line; 
    } 
    line_iterator():in(&cin),is_valid(false) 
    { 
    } 
    line_iterator(istream& s):in(&s) 
    { 
        read(); 
    } 
    line_iterator operator++() 
    { 
        read(); 
        return *this; 
    } 
    line_iterator operator++(int) 
    { 
        line_iterator temp = *this; 
        read(); 
        return temp; 
    } 
    bool operator==(const line_iterator& rhs) 
    { 
        if(in == rhs.in && is_valid == rhs.is_valid) 
            return true; 
        if(is_valid == false && rhs.is_valid == false) 
            return true; 
        return false; 
    } 
    bool operator!= (const line_iterator& rhs) 
    { 
        return !(*this == rhs); 
    } 
}; 
代碼比較長,看似很復雜,在解釋它之前先看看它怎麼使用:
/* 迭代器的使用 版本2
 * created: ume
 * date: 2011-12-17
 *
 */ 
#include<iostream> 
#include<vector> 
#include<string> 
#include<iterator> 
#include<algorithm> 
using namespace std; 
#include"line_iterator.h" 
int main() 

    line_iterator iter(cin); 
    line_iterator end_of_file; 
    vector<string> v(iter,end_of_file); 
    sort(v.begin(),v.end()); 
    copy(v.begin(),v.end(),ostream_iterator<string>(cout," ")); 
    system("pause"); 
    return 0; 

毫不意外,運行這個新版的程序,結果與舊程序是一樣的。比較起來,新版的程序中看不到明顯地輸入語句。顯然這是我們自定義的line_iterator帶來的妙處。
新程序中的輸入是在哪裡實現的呢?請看vector<string> v(iter,end_of_file),用迭代器區間來構造vector,在這個構造方法內部隱含的一定有一個while循環,就是將字符串從iter開始到end_of_file一個接一個的拷貝到vector v中。必然的,它將調用line_iterator的operator++、operator!=等操作符方法。而end_of_file看起來不跟任何變量相關,但是回頭看line_iterator的無參構造方法,你會發現它實際上還是跟標准輸入cin掛上了鉤。所以,在判斷有沒有到達輸入的尾端時,將比較is_valid標記。
line_iterator定義內部的其它成員同樣不可或缺,那些看似沒用的typedef,實際在於vector以及sort、copy等聯合工作的時候被頻繁使用到。想要搞懂它們就需要對iterator進行更深一步的學習了。

摘自 ume's blog - Hope is a good thing
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved