2014-09-10 157 views
4

請原諒我,如果這是一個微不足道的問題,我只是在學習C++,並試圖圍繞某些概念來包裝我的頭。特別是當涉及迭代器時,我完全失去了。C++迭代器在向量中的某些元素

說我有一個自定義類表示一些數據結構,其中一個成員是一個整數向量。我想爲該類編寫一個雙向迭代器,該向量只輸出偶數。有一種簡單而有益的方法嗎?我不喜歡使用STL以外的庫。

+4

爲什麼你不告訴我們你到目前爲止? – lordjeb 2014-09-10 18:48:54

+4

我知道你不想使用其他庫,但是如果其他人閱讀這個問題並不介意使用它們,Boost已經[filter iterator](http://www.boost.org/doc/libs/1_56_0) /libs/iterator/doc/filter_iterator.html)。 – cdhowie 2014-09-10 18:50:19

+1

您是否想要在偶數索引處輸出偶數或數字? – dlf 2014-09-10 19:23:54

回答

1

#include <vector> 
#include <iostream> 

class X { 

public: 

    class EvenIterator { 
    public: 
    EvenIterator(std::vector<int>::iterator it, std::vector&ltint>::iterator end) : it(it), end(end) { 
     while (true) { 
     if (isEven(*it)) { 
      break; 
     } else if (it == end) { 
      break; 
     } 
     it++; 
     } 
    } 

    bool operator != (const EvenIterator& evenIt) { 
     return evenIt.it != this->it; 
    } 

    int operator *() { 
     return *it; 
    } 

    EvenIterator operator ++() { 
     while (true) { 
     it++; 
     if (isEven(*it)) { 
      return EvenIterator(it, end); 
     } else if (it == end) { 
      return EvenIterator(it, end); 
     } 
     } 
    } 
    private: 
    std::vector&ltint>::iterator it;  
    std::vector&ltint>::iterator end;  
    }; 

    static bool isEven(int number) { 
    return number % 2 == 0; 
    } 

    void add(int number) { 
    v.push_back(number); 
    } 

    EvenIterator evenBegin() { 
    return EvenIterator(v.begin(), v.end()); 
    } 

    EvenIterator evenEnd() { 
    return EvenIterator(v.end(), v.end()); 
    } 

private: 
    std::vector&ltint> v; 

}; 

int main() { 
    X x; 
    x.add(1); 
    x.add(2); 
    x.add(3); 
    x.add(2); 
    x.add(2); 
    x.add(31); 
    x.add(56); 
    x.add(101); 

    for (X::EvenIterator it = x.evenBegin(); it != x.evenEnd(); ++it){ 
    std::cout << *it << std::endl; // only prints the even numbers 
    } 
} 

+0

太棒了,這看起來非常像我期望我的代碼看起來像是如果我知道如何去做的;-)它應該是數字%2 == 0,但是: - ) – user32849 2014-09-10 19:46:15

+0

你真的想檢查結束條件,然後去引用迭代器... – jrok 2014-09-10 19:48:58

+0

該版本獲取第一個元素,即使它是奇數。應該是'iterator evenBegin(){ \t \t std :: vector :: iterator i = data.begin(); (* isEven(* i)){ \t \t \t \t} \t \t return iterator(i,data.end()); \t}' – user32849 2014-09-10 21:17:17

3

不確定讓自己的迭代器很容易。但可能最好的是使用條件for_each函數。

std::for_each對每個元素進行操作。創建一個for_each_if對某些特定元素進行操作非常簡單。例如,下面的程序只打印矢量中的偶數(4,6和8)。

#include <iostream> 
#include <vector> 

using namespace std; 

struct is_even { 
    typedef bool return_type; 
    bool operator() (const int& value) {return (value%2)==0; } 
}; 

struct doprint { 
    bool operator() (const int& value) { std::cout << value << std::endl; } 
}; 

template <class InputIterator, class Predicate, class Function> 
void for_each_if(InputIterator first, InputIterator last, Function f, Predicate pred) 
{ 
    while (first != last) 
    { 
     if (pred (*first)) 
      f(*first++); 
     else 
      first ++; 
    } 
} 

int main() 
{ 
    std::vector<int> v; 
    v.push_back(4); 
    v.push_back(5); 
    v.push_back(6); 
    v.push_back(8); 

    for_each_if(v.begin(), v.end(), doprint(), is_even()); 

    return 0; 
} 
3

你的要求去,從vector::iterator獲得很可能是最簡單的:

class my_iterator : private std::vector<int>::iterator { 
    typedef std::vector<int>::iterator base; 
    base m_base_end; // Stores the real end iterator of the internal vector. 
         // We need it so that the even/odd checking code 
         // doesn't run off the end of the vector 
         // (initialize it in a constructor, omitted here for 
         // brevity). 
public: 

    using base::operator*; 
    using base::operator->; 
    // etc. for other members... 

    // except for increment: 

    my_iterator& operator++() 
    { 
     do { 
      base::operator++(); 
     } while(static_cast<base&>(*this) != m_base_end 
       && base::operator*() % 2); 
     return *this; 
    } 

    my_iterator operator++(int) 
    { 
     my_iterator temp; 
     operator++(); 
     return temp; 
    } 

    // TODO: decrement and other arithmetic operators 
}; 

它仍然是相當多的樣板,你還需要爲const_iterator做同樣的(我'd可能會讓上面的類變得更容易)。

考慮提高這一點 - 它有filter_iterator只是爲了這個目的。如果那不適合你,也有iterator_adaptor

+0

此解決方案是非常危險,可能有太多其他代碼出現。例如,這個循環很可能會崩潰,因爲'erase'也應該被覆蓋:'my_iterator iter = v.begin(); while(iter!= v.end()){if(cond)++ iter; else iter = v.erase(); }'。而且,是'vector :: operator ++''virtual'?因爲非虛函數不應該被覆蓋...... – jpo38 2014-09-13 15:54:23