www.pudn.com > DlgScrSaver.rar > Collect.h
/////////////////////////////////////////////////////////////////////////////// // // // Dateiname: COLLECT.H // // // // Autor: Andreas Jäger, Friedrich-Schiller-Universität Jena // // // // System: WIN_RWPM.EXE und WINLRWPM.EXE // // // // Beschreibung: Kollektionen als Templates // // // // Hinweise: // // // /////////////////////////////////////////////////////////////////////////////// #include "resource.h" /////////////////////////////////////////////////////////////////////////////// // template-Klasse CCollection // /////////////////////////////////////////////////////////////////////////////// /* Diese Klasse entspricht in ihrer Funktionalität dem bekannten PASCAL-Objekt, sie ist jedoch typensicherer, da nicht mit generischen, sondern mit T* - Zeigern gearbeitet wird. Außerdem ist die Zahl der Objekte in der Kollektion nahezu un- begrenzt (Indizierung mit long). Es können Objekte des Typs "T" oder "abgeleitet von T" gespeichert werden, wobei ein Zeiger auf ein Objekt vom Typ T entgegengenommen wird, der dann von der Kollektion verwaltet wird. Zusätzlich ist es möglich, mittels des mitgelieferten Dialogs CChooseCollDialog bzw. TNoHelpChooseCollDialog ein Item als selektiert zu markieren. Wird CChooseCollDialog verwendet, so muß das Objekt T eine (virtuelle) Help- Funktion bereitstellen. Sortierte Kollektionen müssen zusätzlich zur Help-Funktion eine Vegleichs-Funktion Compare bereitstellen. */ templateclass CCollection : public CObject { public: // Konstruktor und Standard-Konstruktor CCollection(const char* name = _T("CCollection"), long _limit = 2, long _delta = 50); // Destruktor virtual ~CCollection(); // Lesender Zugriff auf count und delta long Count() const {return count;}; long CountNonZero() const; // Anzahl der gespeicherten Zeiger ohne Berücksichtigung der NULL-Zeiger long Delta() const {return delta;}; bool IsEmpty() const {return count == 0L;}; void SetDelta(long _delta) {delta = _delta;}; // Zugriff auf Items T* At(long index) const {return ((index>=0L) && (index =0L) && (index 0L) ? items[0L] : NULL;}; T* Last() const {return (count>0L) ? items[count-1L] : NULL;}; // Löschen von Items virtual void AtFree(long index, bool discardmem = false); virtual void FreeAll(bool discardmem = false); // true übergeben, um freigewordenen Speicher zu verwerfen protected: // Speicher-Verwaltung virtual T** Alloc_Mem(long _limit) {T** _items = new T*[_limit]; ASSERT(_items); return _items;}; virtual void ReleaseMem() {delete[] items;}; virtual void Resize(long _limit); // Anpassung des Speicherblocks, es werden keine Items eingefügt public: // Einfügen von Items virtual void AtInsert(T* t, long index); virtual void Insert(T* t); // Ersetzen von Items virtual void AtPut(T* t, long index); // Zeiger in der Kollektion durch NULL-Zeiger ersetzen, hilfreich, wenn // das Objekt von außerhalb gelöscht wurde virtual void SetNULL(long index) {if (index>=0 && index & operator << (CCollection & dest, CCollection & source); //virtual void Serialize(CArchive& ar); // Datenfelder public: CString Name; protected: long count; // Anzahl der Elemente, die sich in der Collection befinden long delta; // Inkrement, um das sich die Zahl der aufnehmbaren Elemente vergrößert oder verkleinert long limit; // Anzahl der aufnehmbaren Elemente, ohne die Collection zu vergrößern T** items; // Zeiger auf Speicherblock // Privater Kopier-Konstruktor und Zuweisungsoperator. // Somit werden die vom Compiler automatisch generierten // Funktionen verborgen, da diese nicht korrekt arbeiten. // Kollektionen haben in dieser Version keine Kopier- // Semantik. private: CCollection(const CCollection & /*coll*/) {}; CCollection & operator = (const CCollection & /*coll*/) {return *this;}; }; template class CSortCollection : public CCollection { public: // Konstruktor CSortCollection(const char* name = _T("CSortedCollection"), long _limit = 2L, long _delta = 50L) : CCollection (name, _limit, _delta) { }; // Vergleich von Items virtual int Compare(T* t1, T* t2) const; // Suche nach Items long Search(T* t) const; long BSearch(T* t) const; // Sortieren virtual bool BubbleSort(); virtual bool InsertionSort(); virtual bool SelectionSort(); virtual bool ShellSort(); virtual bool QuickSort(long l = -1, long r = -1); virtual bool MergeSort(long l = -1, long r = -1); // Privater Kopier-Konstruktor und Zuweisungsoperator. // Somit werden die vom Compiler automatisch generierten // Funktionen verborgen, da diese nicht korrekt arbeiten. // Kollektionen haben in dieser Version keine Kopier- // Semantik. private: CSortCollection(const CSortCollection & /*coll*/) {}; CSortCollection & operator = (const CSortCollection & /*coll*/) {return *this;}; }; template class CSortedCollection : public CSortCollection { public: // Konstruktor CSortedCollection(const char* name = _T("CSortedCollection"), long _limit = 2L, long _delta = 50L, bool _duplicates = false) : CSortCollection (name, _limit, _delta), duplicates(_duplicates) { }; virtual ~CSortedCollection() {}; // Duplikate void SetDuplicates(bool _duplicates = false) {duplicates = _duplicates;}; bool Duplicates() const {return duplicates;}; // Einfügen von Items virtual void Insert(T* t); protected: bool duplicates; // Privater Kopier-Konstruktor und Zuweisungsoperator. // Somit werden die vom Compiler automatisch generierten // Funktionen verborgen, da diese nicht korrekt arbeiten. // Kollektionen haben in dieser Version keine Kopier- // Semantik. private: CSortedCollection(const CSortedCollection & /*coll*/) {}; CSortedCollection & operator = (const CSortedCollection & /*coll*/) {return *this;}; }; // Template-Klasse CChooseCollection. template class CChooseCollection : public CCollection { public: // Konstruktor und Standard-Konstruktor CChooseCollection(const char* name = _T("CChooseCollection"), long _limit = 2, long _delta = 50) : CCollection (name, _limit, _delta), Selected(0) { }; // Destruktor virtual ~CChooseCollection() {}; // Auswahl long GetSelIndex() const {return Selected;}; CString GetSelName() const {return *GetSelected();}; void SetSelIndex(long _index); void SetSelIndex(const char* _name); T* GetSelected() const {return At(Selected);}; bool ChooseSelected(const char* dialogtitle = _T("Auswahl"), CWnd* parent = NULL); long* MultiSelection(const char* dialogtitle = _T("Auswahl")); long Find(const char* name) const; //virtual void Serialize(CArchive& ar); protected: long Selected; // Privater Kopier-Konstruktor und Zuweisungsoperator. // Somit werden die vom Compiler automatisch generierten // Funktionen verborgen, da diese nicht korrekt arbeiten. // Kollektionen haben in dieser Version keine Kopier- // Semantik. private: CChooseCollection(const CChooseCollection & /*coll*/) {}; CChooseCollection & operator = (const CChooseCollection & /*coll*/) {return *this;}; }; template class CChooseCollDialog : public CDialog { public: //enum { IDD = IDD_CHOOSECOLLDIALOG1 }; CChooseCollDialog(CChooseCollection & coll, LPCTSTR lpszTemplateName, CWnd* parent = NULL) : CDialog(lpszTemplateName, parent), Coll(coll), Selected(coll.GetSelIndex()) {}; CChooseCollDialog(CChooseCollection & coll, CWnd* parent = NULL, UINT nIDTemplate = IDD_CHOOSECOLLDIALOG) : CDialog(nIDTemplate, parent), Coll(coll), Selected(coll.GetSelIndex()) {}; virtual void DoDataExchange(CDataExchange* pDX); virtual BOOL OnInitDialog(); virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); CListBox m_ctlListBox; int Selected; CChooseCollection & Coll; }; // ================== CCollection ============================================= template CCollection ::CCollection(const char* name, long _limit, long _delta) : Name(name) { items = Alloc_Mem(_limit); count = 0L; delta = _delta; limit = _limit; }; template CCollection ::~CCollection() { for (long i=0L; i void CCollection ::Resize(long _limit) { if (_limit == limit) return; // nichts zu tun // temporäres Feld erzeugen T** tempitems = Alloc_Mem(_limit); // Kopieren memcpy(tempitems, items, min(limit, _limit)*sizeof(T*)); // Altes Feld freigeben ReleaseMem(); limit = _limit; items = tempitems; }; template void CCollection ::Insert(T* t) { if (count == limit) { Resize(limit + delta); } items[count++] = t; }; template void CCollection ::FreeAll(bool discardmem) // true übergeben, um freigewordenen Speicher zu verwerfen { for (long i=0L; i void CCollection ::AtPut(T* t, long index) { ASSERT(index>=0); if (index < 0) return; if(index>=count) { if (limit void CCollection ::AtFree(long index, bool discardmem) { ASSERT(index>=0L && index =count)) return; delete items[index]; items[index] = NULL; if (discardmem) { for (long i=index; i void CCollection ::AtInsert(T* t, long index) { ASSERT(index>=0L && index<=count); if(index>=count) { if (limit index; i--) { items[i] = items[i-1]; }; items[index] = t; } }; template long CCollection ::Search(T* t) const { for (long i=0L; i long CCollection ::CountNonZero() const { long ptrcount = 0L; long i; for (i=0L; i void CCollection ::Pack() { long ptrcount = CountNonZero(); T** tempitems = Alloc_Mem(ptrcount + 10L); // kleine Sicherheit // Kopieren long j = 0L; for (long i=0L; i CCollection & operator << (CCollection & dest, CCollection & source) { for (long i=0L; i void CCollection ::Serialize(CArchive& ar) { if (ar.IsStoring()) { try { ar << CountNonZero(); ar << delta; ar << limit; ar << Name; for (long i=0; i Serialize(ar); } } } catch (...) { return; } } else { FreeAll(); try { ar >> count; ar >> delta; ar >> limit; ar >> Name; if (count < 0) count = 0; if (delta < 0) delta = 2; if (limit < count) limit = count; items = Alloc_Mem(limit); for (long i=0; i Serialize(ar); items[i] = t; } } catch (...) { count = 0; limit = 2; items = Alloc_Mem(limit); return; } } }; */ // ================== CSortCollection ======================================= template long CSortCollection ::Search(T* t) const { // kann mit binärer Suche (BSearch) effizienter erledigt werden for(long i=0L; i long CSortCollection ::BSearch(T* t) const { long l = 0; long r = count-1; long m; while (l<=r) { m = (l+r)/2; switch (Compare(At(m), t)) { case -1: l = m+1; break; case 0: return m; case 1: r = m-1; } } return -1; }; template int CSortCollection ::Compare(T* t1, T* t2) const { if (!t1 && !t2) return 0; if (!t1) return -1; if (!t2) return 1; return t1->Compare(*t2); }; template bool CSortCollection ::BubbleSort() { for (long i=1; i =i; j--) { if (Compare(At(j), At(j-1)) == -1) { T* t = items[j]; items[j] = items[j-1]; items[j-1] = t; j--; } } } return true; }; template bool CSortCollection ::InsertionSort() { for (long i=1; i 0 && Compare(At(j), At(j-1)) == -1) { T* t = items[j]; items[j] = items[j-1]; items[j-1] = t; j--; } } return true; }; template bool CSortCollection ::SelectionSort() { for (long i=0; i bool CSortCollection ::ShellSort() { return true; }; template bool CSortCollection ::MergeSort(long l, long r) { if (l==-1) l = 0; if (r==-1) r = count-1; return true; }; template bool CSortCollection ::QuickSort(long l, long r) { if (l==-1) l = 0; if (r==-1) r = count-1; return true; }; // ================== CSortedCollection ======================================= template void CSortedCollection ::Insert(T* t) { if (!duplicates && Search(t)) { return; // keine doppelten Schlüssel -> Item wird nicht eingefügt }; if (count == limit) { Resize(limit + delta); }; count++; for(long i=count-1; i>0L; i--) { if (Compare(items[i-1], t) <= 0) { items[i] = t; return; }; items[i] = items[i-1]; }; items[0] = t; }; // ================== CChooseCollection ======================================= template void CChooseCollection ::SetSelIndex(long _index) { ASSERT(_index>=0L && _index = count) Selected = count-1; }; template long CChooseCollection ::Find(const char* _name) const { for (long i=0L; i GetName().Collate(_name)) == 0) { return i; } } return -1L; } template void CChooseCollection ::SetSelIndex(const char* _name) { long i = Find(_name); if (i>=0) Selected = i; }; template bool CChooseCollection ::ChooseSelected(const char* /*dialogtitle*/, CWnd* parent) { CChooseCollDialog dlg(*this, parent); if (dlg.DoModal() && dlg.Selected >= 0) { Selected = dlg.Selected; return true; } return false; }; template long* CChooseCollection ::MultiSelection(const char* dialogtitle) { return NULL; }; template void CChooseCollDialog ::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_CHOOSECOLLDIALOG_LIST1, m_ctlListBox); DDX_LBIndex(pDX, IDC_CHOOSECOLLDIALOG_LIST1, Selected); }; template BOOL CChooseCollDialog ::OnInitDialog() { BOOL ret = CDialog::OnInitDialog(); if (Coll.IsEmpty()) return false; // nothing to choose for (long i=0; i GetName()); } m_ctlListBox.SetCurSel(Coll.GetSelIndex()); return ret; }; template BOOL CChooseCollDialog ::OnCommand(WPARAM wParam, LPARAM lParam) { if ((int)HIWORD(wParam)==LBN_DBLCLK && (int) LOWORD(wParam)==IDC_CHOOSECOLLDIALOG_LIST1) { wParam = IDOK; lParam = 0; } return CDialog::OnCommand(wParam, lParam); } /* template void CChooseCollection ::Serialize(CArchive& ar) { if (ar.IsStoring()) { CCollection ::Serialize(ar); } else { CCollection ::Serialize(ar); Selected = 0; // ist beim Speichern verlorengegangen } } */