home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / OTL-MC7.DMS / in.adf / cppdemo.lha / C++ / oolists.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-30  |  6.5 KB  |  287 lines

  1. #pragma +
  2. //  Objektorientiertes Telefonlisten-Programm
  3. //
  4. //  mit generischen Listenklassen
  5. //
  6. //  Jens Gelhar 03.02.91
  7.  
  8.  
  9. #include <stream.h>
  10. #include <string.h>
  11.  
  12.  
  13. // * * * abstrakter Datentyp "Listenelement" * * *
  14.  
  15. class Listenelement
  16. { private:
  17.     Listenelement *next, *prev;       // Vorgänger und Nachfolger
  18.  
  19.     virtual int compare(const Listenelement*) const = 0;
  20.     // vergleicht Objekt "*this" mit einem anderen Listenelement
  21.     // und gibt -1, 0 oder +1 zurück (wie bei "strcmp")
  22.  
  23.     virtual void ausgabe() const = 0;
  24.     // Ein Listenelement ausgeben
  25.  
  26.     virtual ~Listenelement()
  27.      { }
  28.     // virtuieller Destruktor - hier nur ein Dummy, kann aber
  29.     // in abgeleiteten Klassen überdeckt werden
  30.  
  31.   protected:
  32.     // kleine Extras: abgeleitete Klassen dürfen "next" und "prev"
  33.     // auslesen:
  34.     Listenelement *getnext() const
  35.       { return next; }
  36.     Listenelement *getprev() const
  37.       { return prev; }
  38.  
  39.   friend class Liste;     // Diese später deklarierte Klasse
  40.                           // braucht Zugriff auf private Member
  41. };
  42.  
  43.  
  44. // * * * generischer Datentyp "Liste" * * *
  45.  
  46. class Liste
  47. { private:
  48.     Listenelement *anfang, *ende;  // erstes und letztes Element
  49.                                    // der Liste
  50.   protected:
  51.     void insert(Listenelement *neu);
  52.     // sucht eine geeignete Position für das Element "*neu" und
  53.     // hängt es in die Liste ein
  54.  
  55.   public:
  56.     Liste();          // Konstruktor zur Initialisierung
  57.     ~Liste();         // Destruktor (löscht alle
  58.                       // Listenelemente)
  59.     void ausgabe();   // gibt die ganze Liste aus
  60.  
  61.     Listenelement *suchen(Listenelement *);
  62.     // sucht ein Element, das dem Argument-Element "entspricht"
  63.     // (was immer das in einer konkreten Liste heißen mag -
  64.     // jedenfalls ein Element, bei dem "compare" Null liefert)
  65.     // oder Null, wenn kein solches element existiert.
  66.  
  67.     void loeschen(Listenelement*);
  68.     // hängt ein Element aus der Liste aus und löscht es
  69.     // mit "delete"
  70. };
  71.  
  72. Liste::Liste()
  73.  { anfang = 0;
  74.    ende = 0;
  75.  }
  76.  
  77.  
  78. Liste::~Liste()
  79.  {
  80.    Listenelement *p = anfang;
  81.  
  82.    while(p)
  83.      { Listenelement *hilf = p;
  84.        p=p->next;
  85.        delete hilf;
  86.      }
  87.  }
  88.  
  89.  
  90. void Liste::ausgabe()
  91.   { for(Listenelement *l = anfang; l; l = l->next)
  92.       l->ausgabe();
  93.   }
  94.  
  95. Listenelement *Liste::suchen(Listenelement *e1)
  96.   { for(Listenelement *e2 = anfang;
  97.         e2 && e2->compare(e1);
  98.         e2 = e2->next);
  99.     return e2;
  100.   }
  101.  
  102.  
  103. void Liste::insert(Listenelement *neu)
  104.   {
  105.     // Position suchen:
  106.     Listenelement *pos = anfang;
  107.     while (pos && neu->compare(pos) > 0)
  108.       pos = pos->next;
  109.  
  110.     // Element an Position "pos" in Liste einfügen
  111.     // (prinzipiell genau wie in der ersten Programmversion)
  112.  
  113.     if (pos == 0)
  114.     // Sonderfall: Anfügen an das Ende der Liste
  115.     {
  116.       Listenelement *alt = ende;    // altes Listenende
  117.  
  118.       if (alt != 0)
  119.       // allgemeiner Unter-Fall: wirklich anhängen
  120.       {
  121.         alt->next = neu;
  122.         neu->prev = alt;
  123.         neu->next = 0;
  124.         ende = neu;
  125.       }
  126.       else
  127.       // spezieller Spezialfall: Liste ist noch leer
  128.       { neu->next = 0;
  129.         neu->prev = 0;
  130.         anfang = neu;
  131.         ende = neu;
  132.       }
  133.     }
  134.     else
  135.     if (pos->prev == 0)
  136.     // Sonderfall: Neues Element an Listenanfang hängen
  137.     {
  138.       pos->prev = neu;
  139.       neu->next = pos;
  140.       neu->prev = 0;
  141.       anfang = neu;
  142.     }
  143.     else
  144.     // allgemeiner Fall: Element in Liste einhängen
  145.     {
  146.       Listenelement *vor = pos->prev;
  147.       // "neu" zwischen "vor" und "pos" einhängen:
  148.       vor->next = neu;
  149.       neu->prev = vor;
  150.       neu->next = pos;
  151.       pos->prev = neu;
  152.     }
  153.   }
  154.  
  155.  
  156. void Liste::loeschen(Listenelement *E)
  157.   // Löscht das Element, auf das "E" zeigt, aus der Liste
  158.   {
  159.    // Vorgänger unf Nachfolger des zu löschenden Elements
  160.    Listenelement *vor = E->prev, *nach = E->next;
  161.  
  162.    if (vor)
  163.    // Element hat Vorgänger: Dann dessen Nachfolger umsetzen
  164.      vor->next = nach;
  165.    else
  166.    // kein Vorgänger: Dann Listenanfang aktualisieren
  167.      anfang = nach;
  168.  
  169.    if (nach)
  170.    // Element hat Nachfolger: Dann dessen Vorgänger verändern
  171.      nach->prev = vor;
  172.    else
  173.    // kein Nachfolger, also Listenende anpassen
  174.      ende = vor;
  175.  
  176.    delete(E);
  177.   }
  178.  
  179.  
  180.  
  181. // * * * spezieller Datentyp "Eintrag" * * *
  182.  
  183. class Eintrag : public Listenelement
  184.  { public:
  185.      char name[30];                // Name und...
  186.      char nummer[20];              // Telefonnummer
  187.  
  188.      // Konstruktor:
  189.      Eintrag(const char *neuname, const char *neunummer);
  190.  
  191.      // Funktionen, die virtuelle Funktionen der Basisklasse
  192.      // definieren:
  193.      int compare(const Listenelement*) const;
  194.      void ausgabe() const;
  195.  };
  196.  
  197.  
  198. Eintrag::Eintrag(const char *neuname, const char *neunummer)
  199.   : name(neuname),
  200.     nummer(neunummer)
  201.   { }
  202.  
  203.  
  204. int Eintrag::compare(const Listenelement* that) const
  205.  {
  206.    Eintrag *that2 = (Eintrag*) that;
  207.    return strcmp(this->name, that2->name);
  208.  }
  209.  
  210.  
  211. void Eintrag::ausgabe() const
  212.  {  cout << name << ": " << nummer << "\n"; }
  213.  
  214.  
  215. // * * * spezieller Datentyp "Telefonbuch" * * *
  216.  
  217. class Telefonbuch : private Liste
  218.  { public:
  219.      // Neues Element erzeugen und einfügen:
  220.      Eintrag *insert(const char *, const char *);
  221.  
  222.      // Element anhand des Namens suchen:
  223.      Eintrag *suchen(const char *);
  224.  
  225.      // zwei Funktionen werden öffentlich vererbt:
  226.      Liste::ausgabe;
  227.      Liste::loeschen;
  228.  };
  229.  
  230.  
  231. Eintrag* Telefonbuch::insert(const char *neuname, const char *neunummer)
  232.  {
  233.    // neues Element erzeugen:
  234.    Eintrag *neu = new Eintrag (neuname, neunummer);
  235.  
  236.    if (!neu) return 0;           // kein Speicher frei!
  237.  
  238.    // Element in Liste einhängen:
  239.    Liste::insert(neu);
  240.  
  241.    // Fertig, Zeiger auf neues Element zurückgeben:
  242.    return neu;
  243.  }
  244.  
  245.  
  246. Eintrag *Telefonbuch::suchen(const char *name)
  247.  {
  248.    Eintrag dummy(name,"");
  249.    return (Eintrag*) Liste::suchen(&dummy);
  250.  };
  251.  
  252.  
  253. // * * *  Hauptprogram  * * *
  254.  
  255. void main()
  256.  {
  257.    // Eine Liste wird deklariert und initialisiert:
  258.  
  259.    Telefonbuch t;
  260.  
  261.    // Ein paar Beispieldaten werden eingefügt:
  262.  
  263.    t.insert("Harley-Davidson", "001-414/342-4680");
  264.    t.insert("Boris Becker", "0815/4711");
  265.    t.insert("James Bond", "007/26731");
  266.    t.insert("Maxon", "06196/481813");
  267.    t.insert("Zaphod Beeblebrox", "00042/08154242");
  268.    t.insert("Luxemburg", "00352");
  269.    t.insert("Queensr\0377che", "795069");
  270.    t.insert("Fishbone", "4676152");
  271.  
  272.    // Ein Datensatz wird gesucht und ggf. gelöscht:
  273.  
  274.    Eintrag *e = t.suchen("Maxon");
  275.    if (e)
  276.      t.loeschen(e);
  277.    else
  278.      cout << "Name nicht gefunden!\n";
  279.  
  280.    // restliche Liste ausgeben:
  281.    t.ausgabe();
  282.  
  283.    // Löschen der Liste geschieht automatisch durch Destruktor-Aufruf
  284.  }
  285.  
  286.  
  287.