Click here to Skip to main content
15,894,907 members
Articles / Programming Languages / C++

A powerful function parser

Rate me:
Please Sign up or sign in to vote.
4.40/5 (21 votes)
22 Feb 2000 141.3K   2.2K   60  
A simple yet powerful function parser that parses and evaluates standard mathematical functions
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// 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.
*/
template <class T>
class 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<count)) ? items[index] : NULL;};
	T* operator [](long index) const       {return ((index>=0L) && (index<count)) ? items[index] : NULL;};
	T* First() const                       {return (count>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<count) items[index]=NULL;};

	// Suche nach Items
	virtual long Search(T* t) const;

	// Entfernen von NULL-Zeigern
	virtual void Pack();

	// Verschieben von Items von einer Kollektion in eine andere
	friend CCollection<T>& operator << (CCollection<T>& dest, CCollection<T>& 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<T>& /*coll*/)  {};
	CCollection<T>& operator = (const CCollection<T>& /*coll*/) {return *this;};
};

template <class T>
class CSortCollection : public CCollection<T>
{
public:
	// Konstruktor
	CSortCollection(const char* name = _T("CSortedCollection"), long _limit = 2L, long _delta = 50L)
		: CCollection<T>(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<T>& /*coll*/) {};
	CSortCollection<T>& operator = (const CSortCollection<T>& /*coll*/) {return *this;};
};

template <class T>
class CSortedCollection : public CSortCollection<T>
{
public:
	// Konstruktor
	CSortedCollection(const char* name = _T("CSortedCollection"), long _limit = 2L, long _delta = 50L, bool _duplicates = false)
		: CSortCollection<T>(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<T>& /*coll*/) {};
	CSortedCollection<T>& operator = (const CSortedCollection<T>& /*coll*/) {return *this;};
};

// Template-Klasse CChooseCollection. 
template<class T>
class CChooseCollection : public CCollection<T>
{
public:
	// Konstruktor und Standard-Konstruktor
	CChooseCollection(const char* name = _T("CChooseCollection"), long _limit = 2, long _delta = 50)
		: CCollection<T>(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<T>& /*coll*/) {};
	CChooseCollection<T>& operator = (const CChooseCollection<T>& /*coll*/) {return *this;};
};

template<class T>
class CChooseCollDialog : public CDialog
{
public:
	//enum { IDD = IDD_CHOOSECOLLDIALOG1 };
	CChooseCollDialog(CChooseCollection<T>& coll, LPCTSTR lpszTemplateName, CWnd* parent = NULL) : CDialog(lpszTemplateName, parent), Coll(coll), Selected(coll.GetSelIndex()) {};
	CChooseCollDialog(CChooseCollection<T>& 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<T>& Coll;
};

// ================== CCollection =============================================

template <class T>
CCollection<T>::CCollection(const char* name, long _limit, long _delta) : Name(name)
{
	items = Alloc_Mem(_limit);
	count = 0L;
	delta = _delta;
	limit = _limit;
};

template <class T>
CCollection<T>::~CCollection()
{
	for (long i=0L; i<count; i++) 
		delete items[i];
	ReleaseMem();
};

template <class T>
void CCollection<T>::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 <class T>
void CCollection<T>::Insert(T* t)
{
	if (count == limit)
	{
		Resize(limit + delta);
	}
	items[count++] = t;
};

template <class T>
void CCollection<T>::FreeAll(bool discardmem) // true �bergeben, um freigewordenen Speicher zu verwerfen
{
	for (long i=0L; i<count; i++) delete items[i];
	count = 0L;
	if (discardmem) Resize(delta);
};

template <class T>
void CCollection<T>::AtPut(T* t, long index)
{
	ASSERT(index>=0);
	if (index < 0) return;
	if(index>=count) 
	{
		if (limit<index+1+delta) Resize(index+1+delta);
		for (long j=count; j<index; j++)
		{
			items[j] = NULL;
		}
		items[index] = t;
		count = index + 1;
	}
	else
	{
		if (items[index] != t)
		{
			delete items[index];
			items[index] = t;
		};
	};
};

template <class T>
void CCollection<T>::AtFree(long index, bool discardmem)
{
	ASSERT(index>=0L && index<count);
	if ((index<0L) || (index>=count)) return;
	delete items[index];
	items[index] = NULL;
	if (discardmem)
	{
		for (long i=index; i<count-1; i++)
		{
			items[i] = items[i+1];
		};
		count--;
	}
	else
	{
		if (index==count-1) count--;
	}
};

template <class T>
void CCollection<T>::AtInsert(T* t, long index)
{
	ASSERT(index>=0L && index<=count);
	if(index>=count) 
	{
		if (limit<index+1+delta) Resize(index+1+delta);
		for (long j=count; j<index; j++)
		{
			items[j] = NULL;
		}
		items[index] = t;
		count = index + 1;
	}
	else
	{
		if (count == limit)
		{
			Resize(limit + delta);
		};
		count++;
		for(long i=count; i>index; i--)
		{
			items[i] = items[i-1];
		};
		items[index] = t;
	}
};

template <class T>
long CCollection<T>::Search(T* t) const
{
	for (long i=0L; i<count; i++)
	{
		if (items[i] == t) return i;
	};
	return -1L;
};

template <class T>
long CCollection<T>::CountNonZero() const
{
	long ptrcount = 0L;
	long i;
	for (i=0L; i<Count(); i++)
	{
		if (At(i)) ptrcount++;
	};
	return ptrcount;
};

// Entfernen von NULL-Zeigern
template <class T>
void CCollection<T>::Pack()
{
	long ptrcount = CountNonZero();
	T** tempitems = Alloc_Mem(ptrcount + 10L);  // kleine Sicherheit
	// Kopieren
	long j = 0L;
	for (long i=0L; i<Count(); i++)
	{
		if (At(i))
		{
			tempitems[j++] = At(i);
		}
	};
	// Altes Feld freigeben
	ReleaseMem();
	limit = ptrcount + 10L;
    count = ptrcount;
	items = tempitems;
};

// Verschieben von Items von einer Collection in eine andere
template <class T>
CCollection<T>& operator << (CCollection<T>& dest, CCollection<T>& source)
{
	for (long i=0L; i<source.Count(); i++)
	{
		dest.Insert(source.At(i));
	};
	source.count = 0; //!! count wird auf Null gesetzt, ohne die Items freizugeben,
							//da diese jetzt von dest verwaltet werden
	return dest;
};

template<class T>
void CCollection<T>::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		try
		{
			ar << CountNonZero();
			ar << delta;
			ar << limit;
			ar << Name;
			for (long i=0; i<count; i++)
			{
				if (At(i))
				{
					At(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<count; i++)
			{
				T* t = new T();
				t->Serialize(ar);
				items[i] = t;
			}
		}
		catch (...)
		{
			count = 0;
			limit = 2;
			items = Alloc_Mem(limit);
			return;
		}
	}
};

// ================== CSortCollection =======================================

template <class T>
long CSortCollection<T>::Search(T* t) const
{
	// kann mit bin�rer Suche (BSearch) effizienter erledigt werden
	
	for(long i=0L; i<count; i++)
	{
		if (Compare(items[i], t) == 0) return i;
	};
	
	return -1;
};

template <class T>
long CSortCollection<T>::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 <class T>
int CSortCollection<T>::Compare(T* t1, T* t2) const
{
	if (!t1 && !t2) return 0;
	if (!t1) return -1;
	if (!t2) return  1;
	return t1->Compare(*t2);
};

template <class T>
bool CSortCollection<T>::BubbleSort()
{
	for (long i=1; i<count; i++)
	{
		for (long j=count-1; j>=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 <class T>
bool CSortCollection<T>::InsertionSort()
{
	for (long i=1; i<count; i++)
	{
		long j = i;
		while (j>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 <class T>
bool CSortCollection<T>::SelectionSort()
{
	for (long i=0; i<count; i++)
	{
		long minindex = i;
		T* minkey = At(i);
		for (long j=i+1; j<count; j++)
		{
			if (Compare(At(j), minkey) == -1)
			{
				minkey = At(j);
				minindex = j;
			}
			items[minindex] = items[i];
			items[i] = minkey;
		}
	}
	return true;
};

template <class T>
bool CSortCollection<T>::ShellSort()
{
	return true;
};

template <class T>
bool CSortCollection<T>::MergeSort(long l, long r)
{
	if (l==-1) l = 0;
	if (r==-1) r = count-1;
	return true;
};

template <class T>
bool CSortCollection<T>::QuickSort(long l, long r)
{
	if (l==-1) l = 0;
	if (r==-1) r = count-1;
	return true;
};

// ================== CSortedCollection =======================================

template <class T>
void CSortedCollection<T>::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 <class T>
void CChooseCollection<T>::SetSelIndex(long _index)
{
	ASSERT(_index>=0L && _index<count);
	Selected = _index;
	if (Selected < 0L) Selected = 0L;
	if (Selected >= count) Selected = count-1;
};

template <class T>
long CChooseCollection<T>::Find(const char* _name) const
{
	for (long i=0L; i<count; i++)
	{
		if (At(i)->GetName().Collate(_name)) == 0)
		{
			return i;
		}
	}
	return -1L;
}

template <class T>
void CChooseCollection<T>::SetSelIndex(const char* _name)
{
	long i = Find(_name);
	if (i>=0) Selected = i;
};

template <class T>
bool CChooseCollection<T>::ChooseSelected(const char* /*dialogtitle*/, CWnd* parent)
{
	CChooseCollDialog<T> dlg(*this, parent);
	if (dlg.DoModal() && dlg.Selected >= 0)
	{
		Selected = dlg.Selected;
		return true;
	}
	return false;
};

template <class T>
long* CChooseCollection<T>::MultiSelection(const char* dialogtitle)
{
	return NULL;
};

template<class T>
void CChooseCollDialog<T>::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_CHOOSECOLLDIALOG_LIST1, m_ctlListBox);
	DDX_LBIndex(pDX, IDC_CHOOSECOLLDIALOG_LIST1, Selected);
};

template<class T>
BOOL CChooseCollDialog<T>::OnInitDialog()
{
	BOOL ret = CDialog::OnInitDialog();
	if (Coll.IsEmpty()) return false; // nothing to choose
	for (long i=0; i<Coll.Count(); i++)
	{
		m_ctlListBox.AddString(Coll.At(i)->GetName());
	}
	m_ctlListBox.SetCurSel(Coll.GetSelIndex());
	return ret;
};

template<class T>
BOOL CChooseCollDialog<T>::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<class T>
void CChooseCollection<T>::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		CCollection<T>::Serialize(ar);
	}
	else
	{
		CCollection<T>::Serialize(ar);
		Selected = 0; // ist beim Speichern verlorengegangen
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions