Relation

A.First Edition
This is the first edition of my Relation class and it has been lingering in my mind for a long time. 
B.Idea of program
1¡£ Basic idea: 
Relation is indeed a kind of Logic Set which use a pair of elements from set A and Set B to act as its elements
according to a certain condition. Or in other word, Relation is a set of element pairs of which the elements 
of each pair comes from two other sets. So, it is quite natural to inherent from LogicSets. However, it is 
much complicated than a LogicSet as a pair is an element of another set, we need to define a struct of pair, 
and we need to add a condition.   
2¡£ Program design: 
I used so many "call-back" global functions that I even feel hopeless to go on. It is a pain that I cannot use member function
as call back function, which in Delphi is a possible. (I think, but now memory is blurred.)
3¡£ Major function
 A.  LogicSets* Relation::operator *(LogicSets& B)
This is the only function I implemented. Simply overload * operator and in the call back function, I use a simple 
condition to make sure element from A is bigger than element from B.
B. void LogicSets::forEach(void (*checkEach)(Elements* each, void* data1, void* data2),
    void* data1, void* data2)
This is a expanded version of forEach function, for which I add two more parameters, so that I can pass element from
A and Relation as two parameters when called from second Set. (Confusing? I think it is really unnecessary since
I limiting myself by forbidding access private data of LogicSets, so I have to use call back function to visit 
each elements in relation.
4¡£ Further improvement£º
	A. This is actually not like a class!!! What have I done???
#include <iostream>

using namespace std;

template<class T>
class mylist
{
private:
	T *flist;
	int LENGTH;
	int SIZE;
	int counter;
protected:
	void uninitialize();
	void initialize();
	bool checksize();
	void expand();
	int locate(T ptr);
public:
	mylist();
	~mylist();
	void add(T ptr);
	bool find(T ptr);
	void display();
	int count();
	T& items(int index);
	void insert(int index, T ptr);

};

//actually sets and elements are just like problem of "egg" and "chicken", we do
//know who comes first, they should always comes together, except the emptySets who has 
//no elements at all

class LogicSets;//forward definition

class Elements
{
	void* data;
	long ID;  //plan to use address to represent as ID
	char* name;
	LogicSets* parent;
public:
	LogicSets* belong() { return parent; }
	void setData(void* newData) {data = newData;}
	void* getData() { return data;}
	char* getName() { return name;}
	void setName(const char* givenName);
	bool belong(LogicSets* father){ return father== parent;}
	void setParent(LogicSets* father) { parent = father;}
	Elements(LogicSets* father);
	Elements();
	~Elements();	
};



class LogicSets 
{
private:
	mylist<Elements*> lst;
	//I don't want programmer to use this method
	void create(char* givenName);
public:
	bool include(Elements* pElement);
	void add(Elements* pElement);	
	//call back function "for all"
	bool forAll( bool (*checkEach)(Elements* each)); 
	//call back function "exist"
	bool exists( bool (*checkEach)(Elements* each)); 
	//call back function for general purpose
	void forEach( void (*checkEach)(Elements* each)); 
	//a more powerful call-back function for inputting user data
	void forEach(void (*checkEach)(Elements* each, void* data1, void* data2),  void* data1, void* data2);
	~LogicSets();
};

void destroyElements(Elements* each)
{
	//this is a programmer's job to destroy each element by his own way.
	//I just leave it for an example as following:
	delete((void*)(each));	
}

struct Pair
{
	Elements* x;
	Elements* y;
};

class Relation: public LogicSets
{
public:
	LogicSets* operator*(LogicSets& B); //AxB
	~Relation();
};

void putY(Elements* yPtr, void* xPtr, void* rln)
{
	int *a, *b;
	a = (int*)(((Elements*)(xPtr))->getData());
	b = (int*)(yPtr->getData());
	if (*a > *b)
	{
		Elements* rlnElement= new Elements((LogicSets*)(rln));
		Pair* pair = new Pair;

		pair->x = (Elements*)(xPtr);
		pair->y = yPtr;
		rlnElement->setData((void*)(pair));
		((Relation*)(rln))->add(rlnElement);
	}
}

void destroyPair(Elements* each)
{
	free(each->getData());
}

void putX(Elements* x, void* setB, void* rln)
{
	LogicSets* setPtr;
	setPtr = (LogicSets*)(setB); 
	setPtr->forEach(putY, (void*)(x), rln);
}


//to check all if all are string like "this is no.5"
bool allCheck(Elements* each)
{
	//this function should be user or programme defined
	return strcmp(each->getName(), "this is no.5") == 0;
}

bool existCheck(Elements* each)
{
	//this function should be user or programme defined
	return strcmp(each->getName(), "this is no.5") == 0;
}

void showEach(Elements* each)
{
	//this function should be user or programme defined
	cout<<"\n"<<each->getName()<<" is ";
	cout<<*((int*)(each->getData()))<<endl;
}

void showPair(Elements* each)
{
	Pair* p;
	p = (Pair*)(each->getData());
	cout<<"\nthis pair is:\n";
	cout<<p->x->getName()<<" is "<<*((int*)(p->x->getData()))<<"\t";
	cout<<p->y->getName()<<" is "<<*((int*)(p->y->getData()))<<endl;
}


int main()
{
	const Number = 5;
	Relation A, B;
	Relation *C;
	Elements elementA[Number];
	Elements elementB[Number];
	int dataA[Number];
	int dataB[Number];
	char bufferA[4];
	char bufferB[4];
	char buffer[3];

	for (int i=0; i< Number; i++)
	{
		dataA[i] = rand()%100;
		dataB[i] = rand()%200;
		elementA[i].setData((void*)(dataA+i));
		itoa(i, buffer, 10);
		strcpy(bufferA, "A");
		strcpy(bufferB, "B");
		strcat(bufferA, buffer);
		strcat(bufferB, buffer);
		elementA[i].setName(bufferA);
		elementB[i].setName(bufferB);
		elementB[i].setData((void*)(dataB+i));
		A.add(elementA+i);
		B.add(elementB+i);
	}
	C = (Relation*)(A*B);
	cout<<"Now show set A\n";
	A.forEach(showEach);
	cout<<"Now show set B\n";
	B.forEach(showEach);
	cout<<"Now show Relation C\n";
	C->forEach(showPair);

	return 0;
}


Relation::~Relation()
{
	//forEach(destroyPair);
}

LogicSets* Relation::operator *(LogicSets& B)
{
	LogicSets* R = new LogicSets;
	this->forEach(putX, (void*)(&B), (void*)(R));
	return R;
}

void LogicSets::forEach(void (*checkEach)(Elements* each, void* data1, void* data2),
						void* data1, void* data2)
{
	for (int i=0; i< lst.count(); i++)
	{
		checkEach(lst.items(i), data1, data2);
	}
}




LogicSets::~LogicSets()
{
	/*
	for (int i=0; i<lst.count(); i++)
	{
		delete lst.items(i);
	}
	*/
}

void LogicSets::forEach(void (*checkEach)(Elements* each))
{
	for (int i = 0; i< lst.count(); i++)
	{
		checkEach(lst.items(i));
	}
}


Elements::~Elements()
{
	if (name!=NULL)
	{
		free(name);
	}
	
}


void Elements::setName(const char* givenName)
{
	name = (char*)malloc(strlen(givenName)+1);
	strcpy(name, givenName);
}

Elements::Elements()
{
	parent = NULL;
	data = NULL;
	ID = 0;
	setName("no name, no father");
}
Elements::Elements(LogicSets* father)
{
	parent = father; 
	data = NULL;
	ID = (long)(this); //use add as ID
	setName("no name");
}

//nobody should use this method, otherwise nobody will do  the retrieve mem job
void LogicSets::create(char* givenName)
{
	Elements* ptr;
	ptr = new Elements(this);
	ptr->setParent(this);
	ptr->setName(givenName);
	lst.add(ptr);
}

void LogicSets::add(Elements* pElement)
{
	lst.add(pElement);
	pElement->setParent(this);
}

bool LogicSets::forAll(bool (*checkEach)(Elements* each))
{
	for (int i=0; i< lst.count() - 1; i++)
	{
		if (!checkEach(lst.items(i)))
		{
			return false;
		}
	}
	return true;
}

bool LogicSets::exists(bool (*checkEach)(Elements* each))
{
	for (int i=0; i< lst.count() - 1; i++)
	{
		if (checkEach(lst.items(i)))
		{
			return true;
		}
	}
	return false;
}



//dynamic list

template<class T>
void mylist<T>::insert(int index, T ptr)
{
	if (!checksize())
		expand();

	if (counter == 0)
	{
		items(0) = ptr;
		counter++;
	}
	else
	{
		if (index>=0&& index<=counter)
		{
			int i=index;
			T hold1 = items(index), hold2= items(index+1);
			while (i<counter)
			{	
				hold2 = items(i+1);
				items(i+1) = hold1;
				hold1 = hold2;				
				i++;
			}
			items(index) = ptr; //any exception trap???
			counter++;
		}
	}
}
			
template<class T>
int mylist<T>::locate(T ptr)
{
	int index = 0;
	while (items(index) <ptr &&index <counter)
	{
		index++;
	}
	return index;
}



template<class T>
bool mylist<T>::find(T ptr)
{
	int index = 0;

	index = locate(ptr);
	if (index == counter)
	{
		return false;
	}
	else
	{
		return (items(index) == ptr);
	}
}


template<class T>
int mylist<T>::count()
{
	return counter;
}

template<class T>
T& mylist<T>::items(int index)
{
	return flist[index];
}


template<class T>
void mylist<T>::display()
{
	cout<<setiosflags(ios::showpoint|ios::fixed);
	for (int i = 0; i < counter; i ++)
	{
		cout<<"Number "<<i<<" item is:"<<flist[i]<<endl;
	}
}

template<class T>
void mylist<T>::uninitialize()
{
	free(flist);
}

template<class T>
mylist<T>::~mylist()
{
	uninitialize();
}


template<class T>
void mylist<T>::add(T ptr)
{ 
	int index;
	index = locate(ptr);
	if (items(index)!=ptr)
	{
		insert(index, ptr);
	}
}

template<class T>
void mylist<T>::initialize()
{
	LENGTH = 10;
	SIZE = LENGTH;
	if ((flist =(T*)(malloc(sizeof(T) * SIZE)))==NULL)
		cout<<"Unable malloc memory for size of "<<SIZE<<endl;  //exception need to be handled here!!
	counter = 0;
}

template<class T>
bool mylist<T>::checksize()
{
	return (counter < SIZE);
}

template<class T>
void mylist<T>::expand()
{
	SIZE += LENGTH;
	if ((flist = (T*)(realloc(flist, sizeof(T) * SIZE)))== NULL)
		cout<<"Unable realloc memory for mylist of size "<<SIZE<<endl;
}

template<class T>
mylist<T>::mylist()
{
	initialize();
}

¡¡

This simple output result demonstrate the relation actually choose all elements from A as first

element in each pair, and elements from B as second in each pair by condition that first element

is bigger that second element:

Now show set A

A0 is 41

A1 is 34

A2 is 69

A3 is 78

A4 is 62
Now show set B

B0 is 67

B1 is 100

B2 is 124

B3 is 158

B4 is 64
Now show Relation C

this pair is:
A3 is 78 B4 is 64

this pair is:
A3 is 78 B0 is 67

this pair is:
A2 is 69 B4 is 64

this pair is:
A2 is 69 B0 is 67

¡¡

                                                        back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)

Hosted by www.Geocities.ws

1