2011-03-13 6 views
0

私は与えられたテストメインプログラムで機能するリストの実装を作成しました。私はリストの適切な機能のすべてがプログラムに実装されているわけではないことを認識しており、私はそれで大丈夫です。ここでリスト関数C++で

は、私が作成したコードは次のとおりです。

#include <iostream> 
#include <algorithm> 

using namespace std; 

template <class T> class Link; 
template <class T> class List_iterator; 

template <class T> 
class List 
{ 
public: 
    typedef List_iterator<T> iterator; 

    List(); 
    List(const List<T> & l); 
    ~List(); 

    bool empty() const; 
    unsigned int size() const; 
    T & back() const; 
    T & front() const; 
    void push_front(const T & x); 
    void push_back(const T & x); 
    void pop_front(); 
    void pop_back(); 
    iterator begin() const; 
    iterator end() const; 
    void insert(iterator pos, const T & x); 
    void erase(iterator & pos); 
    List<T> & operator=(const List<T> & l); 

protected: 
    Link<T> * first_link; 
    Link<T> * last_link; 
    unsigned int my_size; 
}; 

template <class T> 
List<T>::List() 
{ 
     first_link = 0; 
     last_link = 0; 
     my_size = 0; 
} 

template <class T> 
List<T>::List(const List & l) 
{ 
     first_link = 0; 
     last_link = 0; 
     my_size = 0; 
     for (Link<T> * current = l.first_link; current != 0; current = current -> next_link) 
       push_back(current -> value); 
} 

template <class T> 
typename List<T>::iterator List<T>::begin() const 
{ 
     return iterator(first_link); 
} 

template <class T> 
class Link 
{ 
private: 
    Link(const T & x): value(x), next_link(0), prev_link(0) {}//pg. 204 

    T value;  
    Link<T> * next_link; 
    Link<T> * prev_link; 

    friend class List<T>; 
    friend class List_iterator<T>; 
}; 

template <class T> class List_iterator//pg.207 
{ 
public: 
    typedef List_iterator<T> iterator; 

    List_iterator(Link<T> * source_link): current_link(source_link) { } 
    List_iterator(): current_link(0) { } 
    List_iterator(List_iterator<T> * source_iterator): current_link(source_iterator.current_link) { } 

    T & operator*(); // dereferencing operator 
    iterator & operator=(const iterator & rhs); 
    bool operator==(const iterator & rhs) const; 
    bool operator!=(const iterator & rhs) const; 
    iterator & operator++(); 
    iterator operator++(int); 
    iterator & operator--(); 
    iterator operator--(int); 

protected: 
    Link<T> * current_link; 

    friend class List<T>; 
}; 

template <class T> 
T & List_iterator<T>::operator*() 
{ 
     return current_link -> value; 
} 

template <class T> 
List_iterator<T> & List_iterator<T>::operator++() 
{ 
     current_link = current_link -> next_link; 
     return *this; 
} 

template <class T> 
void List<T>::push_back(const T & x) 
{ 
    Link<T> * new_link = new Link<T> (x); 
    if (first_link == 0) 
    first_link = last_link = new_link; 
    else 
    { 
    new_link->prev_link = last_link; 
     last_link->next_link = new_link;  
     last_link = new_link; 
    } 
    my_size++; 
} 

template <class T> 
typename List<T>::iterator List<T>::end() const 
{ 
     return iterator(last_link); 
} 

template <class T> 
List <T>::~List() 
{ 
    Link <T> * first = first_link; 
    while (first != 0) 
    { 
    Link <T> * next = first->next_link; 
     delete first; 
    first = next; 
    } 
} 

template<class T> 
bool List_iterator<T>::operator==(const iterator & rhs) const 
{ 
    return (this->current_link == rhs.current_link); 
} 

template <class T> 
bool List_iterator<T>::operator!=(const iterator & rhs) const 
{ 
    return !(*this == rhs); 
} 

int main() 
{ 
    List<int> l; 

    l.push_back(44); // list = 44 
    l.push_back(33); // list = 44, 33 
    l.push_back(11); // list = 44, 33, 11 
    l.push_back(22); // list = 44, 33, 11, 22 

    List<int> m(l); 

    List<int>::iterator itr(m.begin()); 
    while (itr != m.end()) { 
     cout << *itr << endl; 
     ++itr; 
    } 
} 

プログラムが実行されると、リスト内の唯一の最初の3つの要素は、端末に表示され、それは、なぜ私はわかりませんよ。誰かが私の理由を指摘できますか?

また、演算子[]を追加すると、リスト内の特定の要素が表示されますが、どのようにすればよいでしょうか?例:

cout << l[2]; // would display 33 

私が使用している教科書には例はありません。だから助けとなるでしょう。

+0

変数に小文字の「L」を使用しないでください。 1(1)と似ているように見えますが、ちょっと混乱しています。 –

+0

@ John Gordon - そうです、それを覚えておきます。 – UndefinedReference

+0

@Mikhailovich:コピー/移動コンストラクタと代入演算子の良いコンベンションは、変数に 'const List &other'という名前を付けることです。 :) – Xeo

答えて

2

あなたが唯一の最初の3つの要素を見ている理由は、それは、「リストの末尾を越えて」何かを返す必要があるのに対し、List_iterator::end戻ると、リストで最後のノードをということです。

オペレータ[]は、指定された回数だけポインタnext_linkに従う必要があります。

+0

リストの最後を過ぎるとどういう意味ですか? – UndefinedReference

+0

作成された各リストには、常に最後のノードである「終わり」であるデフォルトノードを追加できます。 「while(itr!= m.end())」チェックを行うと、m.end()の値は実際には22のノードですが、その場合はブロックを実行していません。 – Brandon

+0

@Mikhailovich:リストに4つの要素がある場合、イテレータはそのリストに関連する* 5 *異なる値をサポートする必要があります。 'begin()'が返す値は最初の要素を指します。それをインクリメントし、2番目の要素を指すイテレータ値を取得します。 3番目の要素、もう一度、4番目に増分します。インクリメントすると、 'end()'によって返された値が返されます。 'end()'イテレータは何も指していません(したがって "過去の最後")、この値をインクリメントするのは有効ではありません。これがイテレータの仕組みで、 'main'関数のコードはそれに依存しています。 –

1

C++標準ライブラリでは、end()は、常に最初の要素には反復子を返します。リストにはがありません。これは、メインで行うのと同じように行うことができます。while (itr != m.end()) - コンテナ内の最後の要素を超えて増やすと、ループ条件はfalseになり、ループが完了します。

charの単純な配列。

char a[3] = { '1', '2', '3' }; 

char * begin = a; // First element in a 
char * end = a + 3; // First element **after** a 
char * current = begin; 
while (current != end) { 
    cout << *current; 
    ++current; 
} 

'3' へcurrentポイントは、あなたがそれを出力し、インクリメント

currentは、の配列の後の最初の要素を指し、ループが完了します。

あなた「末端()」関数は、最後の要素にイテレータを返す - ので、あなたのループはすべて除いて最後の要素のために実行されます - これはchar * end = a + 2; // Last element in aを言うように、上記のスニペットの変化に対応し、それがつながりますそれは「3」

で行われた後、それはへの「3」代わりのなったときにループがを停止するには、「1つの過去の終わり」の概念をサポートするために、あなたのイテレータを変更、またはいずれかする必要があります完全ではないイテレータのためにループ構造を変更する必要があります。

+0

'Link * end = last_link + 1;'を使用しましたが、4つの要素すべてが表示されるようになりましたが、要素が表示された後に 'segmentation fault'と表示されました。 – UndefinedReference