130 likes | 290 Views
# ifndef __LIST_H_ // '{' // Send errors to Yechiel Kimchi (June 1998) #define __LIST_H_ // Do NOT enter again // yechiel@cs.technion.ac.il #include < iostream.h > #include < stdlib.h > #define DBG (0) // Set to (1) to see all function calls #if DBG
E N D
#ifndef __LIST_H_// '{' // Send errors to YechielKimchi (June 1998) #define __LIST_H_// Do NOT enter again // yechiel@cs.technion.ac.il #include <iostream.h> #include <stdlib.h> #define DBG (0)// Set to (1) to see all function calls #if DBG #define SHOW(str) Show(str) #else #define SHOW(str) #endif #define MANUAL_EXCEPTIONS (1)// If your compiler has no exceptions #if MANUAL_EXCEPTIONS #define MY_EXCEPTION(exp, val) \ {if (!(exp)) { \ cerr << "MY_EXCEPTION: Expression " #exp " failed," \ << " for " #val " = " << val << endl \ << "\tline: " << __LINE__ << "File: " __FILE__ << endl; \ abort(); \ { { #else #define MY_EXCEPTION(exp, val) #endif List.h
class List { public: typedef int Data; // Not a template, yet static void Scope() { cerr << "List::"; return;} static void Show(const char *s) { Scope(); cerr << s << endl; return;} class Iterator; class ConstIterator; // Forward declaration private: class Node { // Everything is private - accessible to friends only Node *next; Data item; static void Scope() { List::Scope(); cerr << "Node::"; return; } static void Show(const char *s) { Scope(); cerr << s << endl; return; } friend class List; friend class Iterator; friend class ConstIterator; Node(const Data &d): next(0), item(d) { SHOW("Node(const Data&)"); } Node(const Node &n): next(0), item(n.item) { SHOW("Node(const Node&)"); } ~Node() { SHOW("~Node()"); } List.h (List & Node)
List.h (Node & List) Node *Next() const { SHOW("Next()"); return next; } const Data& Item() const { SHOW("Item() const"); return item; } Data& Item() { SHOW("Item()"); return item; } operator const Data&() const { SHOW("operator const Data&() const"); return item; } }; // End - class List::Node // Private services List& operator=(const List&); // No assignment List(const List&); // No copy Ctor const Node* Find(const Data &d) const; // Internal search // This is how List is built Node *first, *last; int num; // Number of nodes in the list
List.h public: List(): first(0), last(0), num(0) { SHOW("List()"); } List(const Data& d) : first(new Node(d)), last(first), num(1) { SHOW("List(const Data&) ended"); MY_EXCEPTION(first,d); } List(const List&, int /*dummy*/); // Dummy copy Ctor, for const List ~List(); // CONST services int size() const { SHOW("size()"); return num; } void print(ostream&) const; // Just printout the elements bool IsIn(const Data &d) const; const Data& ShowFirst() const { SHOW("ShowFirst()"); return *first; } //Implicit conversion // Modifiers List& InsertFirst(const Data &d); List& InsertLast (const Data &d); List& DeleteFirst();
List.h (Iterator) friend class Iterator; // The modifying iterator class Iterator { // An iterator that allows modifications to the list List &list; // Cannot iterate over const lists Node *curr, *prev; void next() { SHOW("next()"); if (curr != NULL) { prev = curr; curr = curr->Next(); } return; { static void Scope() { List::Scope(); cerr << "Iterator::"; return;} static void Show(const char *s) { Scope(); cerr << s << endl; return;} public: Iterator(List &l): list(l), curr(l.first), prev(0) { SHOW("Iterator(List &)"); } ~Iterator() { SHOW("~Iterator()"); }
List.h (Iterator) Data& operator*() { SHOW("operator*()"); return curr->Item(); // The right Node::Item() is chosen } Iterator& Delete(); // Removes current Node from List operator bool() { SHOW("operator bool()"); return curr != NULL; } // Prefix ++. ++(++i) is legal (since returns a reference) Iterator& operator++() { SHOW("operator++()"); next(); return *this; } // Postfix ++. (i++)++ is ILLEGAL (since returns a value) Iterator operator++(int) { SHOW("operator++(int)"); Iterator tmp(*this); next(); return tmp; { }; // End - class List::Iterator
List.h (ConstIterator) friend class ConstIterator; // A non-modifier iterator class ConstIterator { // An iterator that cannot be used to modify List const List &list; // It can work on both const and non-const lists const Node *curr, // `Node' is const (not `Node*') *prev; . . . }; // End - class List::ConstIterator }; // End - class List // Non-member, non-friend functions ostream& operator<<(ostream&, const List&); #endif // '}' __LIST_H_
List.cpp #include "List.h"// Send errors to Yechiel Kimchi (June 1998) // Non-member, non-friend services // yechiel@cs.technion.ac.il ostream& operator<<(ostream& os, const List &l) { os << "List has " << l.size() << " items: "; l.print(os); return os; { // A copy Ctor in disguise, for const List initialization List::List(const List& l, int /*dummy*/): first(0), last(0), num(l.num) { SHOW("List(const List&,int) begins"); if (num != 0) { const Node *tmp = l.first; first = last = new Node(tmp->Item()); while ((tmp = tmp->Next()) != false) { last->next = new Node(tmp->Item()); last = last->next; { } SHOW("List(const List&,int) ended"); {
List.cpp List::~List() { SHOW("~List() begins"); while (first) { Node *tmp = first->Next(); delete first; first = tmp; { SHOW("~List() ended"); } // CONST services// A private search method const List::Node* List::Find(const Data &d) const { SHOW("Find(const Data&) const begins"); const Node *tmp = first; for ( ; tmp != NULL && tmp->Item() != d; tmp = tmp->Next()) ; SHOW("Find(const Data&) const ended"); return tmp; {
List.cpp void List::print(ostream& os) const { // Just printout the elements SHOW("print(ostream&) const begins"); for (ConstIterator i(*this); i != false; ++i) { os << *i << ','; { SHOW("print(ostream&) const ended"); return; { bool List::IsIn(const Data &d) const { SHOW("IsIn(const Data&) const"); return Find(d) != NULL; {
// Modifiers List& List::InsertFirst(const Data &d) { SHOW("InsertFirst(const Data&)"); Node * const t = new Node(d); if (first == NULL) last = t; // An empty list (no last node) t->next = first; first = t; ++num; return *this; { List& List::InsertLast(const Data &d) { SHOW("InsertLast(const Data&)"); Node * const t = new Node(d); if (last == NULL) { first = t; // An empty list (no first node) } else { last->next = t; // Non-empty list { last = t; ++num; return *this; { List.cpp
List.cpp List& List::DeleteFirst() { SHOW("DeleteFirst() begins"); if (num == 0) return *this; Node *t = first; if ((first = first->Next()) == NULL) { last = NULL; // List had a single Node in it, and now – none } delete t; --num; SHOW("DeleteFirst() ended"); return *this; {
List.cpp List::Iterator& List::Iterator::Delete() { SHOW("Delete() begins"); if (!curr) return *this; Node *tmp = curr; if (curr == list.last) list.last = prev; // We are removing last Node if (!prev) { // We are removing first Node list.first = curr->Next(); // Update first-entry } else { prev->next = curr->Next(); // Update prev-Node { curr = curr->Next(); // Update curr pointer delete tmp; --list.num; // Update number of Nodes in List SHOW("Delete() ended"); return *this; {