2011-03-13 4 views
0

필자는 필자에게 테스트 메인 프로그램과 함께 작동하는 list 구현을 만들었습니다. 나는 목록의 모든 적절한 기능이 프로그램에서 구현되는 것은 아니며 나는 그 점에 대해 잘 알고 있습니다.리스트 함수 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; 
    } 
} 

, 목록의 첫 번째 세 가지 요소가 터미널에 표시되는은과 그 이유를 나는 확신입니다. 누구든지 나를위한 이유를 지적 할 수 있습니까?

또한 연산자 []를 추가하려고하면 목록의 특정 요소가 표시됩니다. 어떻게 처리합니까? 예 :

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

제가 사용하는 교과서에는 예제가 없으므로 도움이 될 것입니다.

+0

변수에 소문자 'L'을 사용하지 마십시오. 그것은 1 (1)과 매우 흡사합니다. 조금 혼란 스럽습니다. –

+0

@ John Gordon - 네 말이 맞아. 나는 그걸 명심 할거야. – UndefinedReference

+0

@Mikhailovich : 복사/이동 생성자와 할당 연산자에 대한 좋은 규칙은 변수를 'const List & other'로 명명하는 것입니다. :) – Xeo

답변

2

당신이 첫 번째 세 가지 요소를보고있는 이유는 "리스트의 끝을지나"뭔가를 반환해야하는 반면 List_iterator::end 반환 목록의 마지막 노드를 것입니다.

원하는 작업을 수행하는 연산자는 주어진 횟수만큼 포인터 next_link을 따라야합니다.

+0

목록의 마지막을 지나서 무엇을 의미합니까? – UndefinedReference

+0

"끝"인 모든 생성 된 목록에 항상 마지막 노드 인 기본 노드를 추가 할 수 있습니다. "while (itr! = m.end())"체크를하면 m.end()의 값은 실제로 22가있는 노드이지만이 경우 블록을 실행하지 않습니다. – Brandon

+0

@Mikhailovich : 목록에 요소가 4 개있는 경우 반복기는 해당 목록과 관련된 * 5 * 다른 값을 지원해야합니다. 'begin()'에 의해 반환 된 값은 첫 번째 요소를 가리 킵니다. 그것을 증가 시키면 두 번째 요소를 가리키는 반복자 값을 얻게됩니다. 다시 세 번째 요소, 다시 4 번째로 증가시킵니다. 다시 한 번 증가 시키면,'end()'에 의해 리턴 된 값을 얻는다. 'end()'iterator는 아무 것도 가리 키지 않으므로 ("past-the-end"),이 값을 증가시키는 것은 유효하지 않습니다. 이것이 반복자가 작동하는 방식이고,'main' 함수의 코드는이 함수에 의존합니다. –

1

C++ 표준 라이브러리에서 end()은 항상 첫 번째 요소 인 에 반복자를 반환하며 목록에 없습니다. 이렇게하면 메인에서 수행하는 것처럼 수행 할 수 있습니다. while (itr != m.end()) - 컨테이너의 마지막 요소를 넘어서 자마자 루프 조건은 거짓이며 루프가 완료됩니다.

예 : 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'

당신은 "한 과거의 끝"의 개념을 지원하기 위해 반복자를 변경하려면, 다음 중 하나를해야합니다, 또는으로 수행 할 후에 얻을 때 당신은 당신의 루프 구성을 바꾸어서, 완전히 그렇지 않은 반복자를 설명 할 필요가 있습니다.

+0

'Link * end = last_link + 1;'을 사용했고 네 개의 요소를 모두 표시했지만 요소가 표시된 후에'segmentation fault'라고 표시되는 이유가 있습니까? – UndefinedReference