<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Population</title>
</head>

<body>



<p align="center"><span lang="en-ca"><font size="6" color="#FF0000"><b>Relation</b></font></span></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A.<span lang="en-ca"> Second </span>Edition</font></b></pre>
</div>
<div align="left">
  <pre><b>This is the <span lang="en-ca">second</span> edition of my </b><span lang="en-ca"><b>Relation class and it has been lingering in my mind for a long time. </b></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Idea of program</b></font></span></pre>
</div>
<div align="left">
  <pre><b>1¡£ Basic idea: </b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca">I delete class Elements and changed logicSets to have two internal list---one is set list and the other is data list. Data</span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca">now is pure data, set is pure subsets. I also changed the implementation of &quot;call-back&quot; functions, such as forEach to be </span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca">separate as &quot;forEachSet&quot; and &quot;forEachData&quot;. I believe in this way it gives more flexibility for programmer's purpose. </span></pre>
</div>
<div align="left">
  <pre><b>2¡£ Program design: </b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca">I used so many &quot;call-back&quot; global functions that I even feel hopeless to go on. It is a pain that I cannot use member function</span></pre>
  <pre><span lang="en-ca">as call back function, which in Delphi is a possible. (I think, but now memory is blurred.)</span></pre>
  <pre><b>3¡£ Major function</b></pre>
  <blockquote>
    <blockquote>
  <pre><b> A.<span lang="en-ca">  </span></b>void forEachSet(void (*checkEach)(LogicSets* each, void* method, void* userData1, 
		void* userData2), void* method=NULL, void* userData1=NULL, void* userData2=NULL);</pre>
  <pre><span lang="en-ca">The reason that I insert so many parameters is that when Relation is construct, it need so many data to pass on.</span></pre>
  <pre><span lang="en-ca">And for simple job, programmer can use a simple form of forEachSet which only require the call-back function </span></pre>
  <pre><span lang="en-ca">pointer as parameter.</span></pre>
  <pre><b><span lang="en-ca">B. </span></b><span lang="en-ca"><b>void forEachData(void (*checkData)(void* data, void* method, void* userData1, 
void* userData2), void* method=NULL, void* userData1=NULL, void* userData2=NULL); </b></span></pre>
  <pre><span lang="en-ca">This is quite similar to forEachSet, except that it is a special method for you to handle each data and forEachSet</span></pre>
  <pre><span lang="en-ca">can do more general job. And for simple job you can use a simple form forEachData with one parameter.</span></pre>
  <pre><b><span lang="en-ca">C. void Relation::construct(LogicSets* A, LogicSets* B, bool(*condition)(void* first, void* second))</span></b></pre>
  <pre><span lang="en-ca">This function originally is constructor of Relation, and only for debug that I make it an independent method.</span></pre>
  <pre><span lang="en-ca">it first call set A's forEachData method and pass A's data itself as a parameter and Relation pointer. Then in Call-back</span></pre>
  <pre><span lang="en-ca">function, it use B's forEachData method and call the user-defined condition method pointer to make the condition-</span></pre>
  <pre><span lang="en-ca">checking. </span></pre>
  <pre><span lang="en-ca">D. bool condition(void* x, void* y)</span></pre>
  <pre><span lang="en-ca">this should be defined by user.</span></pre>
  <pre><span lang="en-ca">E. void forEachY(void* y, void* checkMethod, void* x, void* relation)</span></pre>
  <pre><span lang="en-ca"> void forEachX(void* each, void* method, void* userData1, void* userData2)</span></pre>
  <pre><span lang="en-ca">these are internal call-back functions and user should not modify them.</span></pre>
    </blockquote>
  </blockquote>
  <pre><b><font size="2">4¡£ Further improvement£º</font></b></pre>
  <pre><b>	A. <span lang="en-ca">This is actually not like a class!!! What have I done???</span></b></pre>
</div>
<pre>#include &lt;iostream&gt;
#include &lt;iomanip&gt;

using namespace std;
/////////////////////////////////////////////////////////////////////////////////
//This is what I thought when I wrote first edition:
//actually sets and elements are just like problem of &quot;egg&quot; and &quot;chicken&quot;, we do
//know who comes first, they should always comes together, except the emptySets who has 
//no elements at all
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//Now I think that set is element and element is set: 
//chicken is egg, and egg is chicken!!!
//////////////////////////////////////////////////////////////////////////////

template&lt;class T&gt;
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&amp; items(int index);
	void insert(int index, T ptr);
};

class LogicSets 
{
private:
	mylist&lt;LogicSets*&gt; setlst;
	mylist&lt;void*&gt; datalst;
	long ID;  //plan to use address to represent as ID
	char* name;
	LogicSets* parent;
public:		
	LogicSets* belongTo() { return parent; }
	int setCount(){ return setlst.count();}
	int dataCount(){ return datalst.count();}
	void setParent(LogicSets* father) { parent = father;}
	LogicSets* getParent() { return parent;}
	void addData(void* newData){ datalst.add(newData); }
	LogicSets* setItems(int index){ return setlst.items(index);}
	void* dataItems(int index) { return datalst.items(index);}
	char* getName() { return name;}
	void setName(const char* givenName);
	bool include(LogicSets* pSets);
	void add(LogicSets* pSets);	
	//call back function &quot;for all&quot;
	bool forAll( bool (*checkEach)(void* each)); 
	//call back function &quot;exist&quot;
	bool exists( bool (*checkEach)(void* each)); 
	//call back function for general purpose
	void forEachSet( void (*checkSet)(LogicSets* each)); 
	void forEachData(void (*checkData)(void* data));
	//a more powerful call-back function for inputting user data
	void forEachSet(void (*checkEach)(LogicSets* each, void* method, void* userData1, 
		void* userData2), void* method=NULL, void* userData1=NULL, void* userData2=NULL);
	void forEachData(void (*checkData)(void* data, void* method, void* userData1, 
		void* userData2), void* method=NULL, void* userData1=NULL, void* userData2=NULL); 
	~LogicSets();
	LogicSets();
};


struct Pair
{
	void* first;
	void* second;
};


class Relation: public LogicSets
{
private:
public:
	
	void construct(LogicSets* A, LogicSets* B, bool (*condition)(void* first, void* second));
	~Relation();
};


////////////////////////////////////////////////////////////////
//these following call-back function are all programmer-defined
//which will be passed as parameter to forall, exist method of 
//logicsets. it is like delphi &quot;even&quot; method
////////////////////////////////////////////////////////////////

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

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

void showEach(LogicSets* each)
{
	//this function should be user or programme defined
	cout&lt;&lt;&quot;\nSet name is '&quot;&lt;&lt;each-&gt;getName()&lt;&lt;&quot;' and data is: &quot;;
	for (int i=0; i&lt; each-&gt;dataCount(); i++)
	{
		cout&lt;&lt;&quot;data no &quot;&lt;&lt;i&lt;&lt;&quot; is &quot;&lt;&lt;*((int*)(each-&gt;dataItems(i)))&lt;&lt;endl;
	}
}


void forEachY(void* y, void* checkMethod, void* x, void* relation)
{
	bool (*check)(void* x, void* y);
	Pair* pair = new Pair;
	check = (bool (*)(void* , void* ))(checkMethod);

	
	if (check(x, y))
	{
		pair-&gt;first = x;
		pair-&gt;second = y;
		((Relation*)(relation))-&gt;addData((void*)(pair));
	}
}



void forEachX(void* each, void* method, void* userData1, void* userData2)
{
	((LogicSets*)(userData1))-&gt;forEachData(forEachY, method, each, userData2);
}


bool condition(void* x, void* y)
{
	return *((int*)x)&gt; *((int*)y);
}

int main()
{
	const int Number =10;
	char buffer[4];
	char str[20];
	LogicSets aSets[Number];
	LogicSets A, B;
	int aNum[Number];
	for (int i=0; i&lt;Number; i++)
	{
		itoa(i, buffer, 10);
		strcpy(str, &quot;this is &quot;);
		strcat(str, buffer);
		aNum[i] = rand()%90;
		aSets[i].addData((void*)(aNum+i));
		aSets[i].setName(str);
		if (i &lt;7)
		{
			A.add(aSets + i);
		}
		else
		{
			B.add(aSets + i);
		}
	}
	for (i=0; i&lt;Number; i++)
	{
		(aSets+i)-&gt;forEachSet(showEach);
	}
	A.setName(&quot;this is set A&quot;);
	B.setName(&quot;this is set B&quot;);
	cout&lt;&lt;&quot;\nNow show Set A\n&quot;;
	A.forEachSet(showEach);
	cout&lt;&lt;&quot;\nNow show Set B\n&quot;;
	B.forEachSet(showEach);
	cout&lt;&lt;endl;
	Relation C;
	C.setName(&quot;A relation of AXB&quot;);
	C.construct(&amp;A, &amp;B, condition);
	int *x, * y;
	Pair* pair;
	for (int j =0; j &lt; C.dataCount(); j++)
	{
		cout&lt;&lt;&quot;pair no.&quot;&lt;&lt;j&lt;&lt;&quot; is \n&quot;;
		pair = (Pair*)(C.dataItems(j));
		x = (int*)(pair-&gt;first);
		y = (int*)(pair-&gt;second);
		cout&lt;&lt;&quot; x is &quot;&lt;&lt;*x&lt;&lt;endl;
		cout&lt;&lt;&quot; y is &quot;&lt;&lt;*y&lt;&lt;endl;
	}

	
	return 0;
}

Relation::~Relation()
{
	for (int i=0; i&lt; dataCount(); i++)
	{
		delete dataItems(i);
	}
}


void Relation::construct(LogicSets* A, LogicSets* B, bool(*condition)(void* first, void* second))
{	
	A-&gt;forEachData(forEachX, (void*)condition, (void*)B, (void*)this);
}

void LogicSets::forEachData(void (*checkData)(void* data, void* method, void* userData1, 
	void* userData2), void* method, void* userData1, void* userData2)
{
	for (int i=0; i&lt;setCount(); i++)
	{
		setItems(i)-&gt;forEachData(checkData, method, userData1, userData2);
	}
	for (i=0; i&lt;dataCount(); i++)
	{
		checkData(dataItems(i), method, userData1, userData2);
	}
}


LogicSets::LogicSets()
{
	name = NULL;
	ID =0;
	parent = NULL;
}


void LogicSets::forEachSet(void (*checkEach)(LogicSets* each, void* method, void* userData1,
				void* userData2), void* method, void* userData1, void* userData2)
{
	for (int i=0; i&lt; setCount(); i++)
	{
		setItems(i)-&gt;forEachSet(checkEach, method, userData1, userData2);	
	}
	checkEach(this, method, userData1, userData2);
}

bool LogicSets::include(LogicSets* pSets)
{
	return setlst.find(pSets);
}


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

}

void LogicSets::forEachData(void (*checkData)(void* data))
{
	for (int i=0; i&lt;setCount(); i++)
	{
		setItems(i)-&gt;forEachData(checkData);
	}
	for ( i=0; i&lt; dataCount(); i++)
	{
		checkData(dataItems(i));
	}
}

void LogicSets::forEachSet(void (*checkSet)(LogicSets* each))
{	
	checkSet(this);
	for (int i = 0; i&lt; setCount(); i++)
	{
		setItems(i)-&gt;forEachSet(checkSet);			
	}
	
}

void LogicSets::setName(const char* givenName)
{
	if (name==NULL)
	{
		name = (char*)malloc(strlen(givenName)+1);
		strcpy(name, givenName);
	}
	else
	{
		name = (char*)realloc((void*)name, strlen(givenName)+1);
		strcpy(name, givenName);
	}
}

void LogicSets::add(LogicSets* pSets)
{
	setlst.add(pSets);
	pSets-&gt;setParent(this);
}

bool LogicSets::forAll(bool (*checkEach)(void* each))
{
	for (int i=0; i&lt; setCount(); i++)
	{
		if (!setItems(i)-&gt;forAll(checkEach))
		{
			return false;
		}
	}
	for (i=0; i&lt; dataCount(); i++)
	{
		if (!checkEach(dataItems(i)))
		{
			return false;
		}
	}
	return true;
}

bool LogicSets::exists(bool (*checkEach)(void* each))
{
	for (int i=0; i&lt; setCount(); i++)
	{
		if (setItems(i)-&gt;exists(checkEach))
		{
			return true;
		}
	}

	for (i=0; i&lt; dataCount(); i++)
	{
		if (checkEach(dataItems(i)))
		{
			return true;
		}
	}
	return false;
}


template&lt;class T&gt;
void mylist&lt;T&gt;::insert(int index, T ptr)
{
	if (!checksize())
		expand();

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



template&lt;class T&gt;
bool mylist&lt;T&gt;::find(T ptr)
{
	int index = 0;

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


template&lt;class T&gt;
int mylist&lt;T&gt;::count()
{
	return counter;
}

template&lt;class T&gt;
T&amp; mylist&lt;T&gt;::items(int index)
{
	return flist[index];
}


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

template&lt;class T&gt;
void mylist&lt;T&gt;::uninitialize()
{
	free(flist);
}

template&lt;class T&gt;
mylist&lt;T&gt;::~mylist()
{
	uninitialize();
}


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

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

template&lt;class T&gt;
bool mylist&lt;T&gt;::checksize()
{
	return (counter &lt; SIZE);
}

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

template&lt;class T&gt;
mylist&lt;T&gt;::mylist()
{
	initialize();
}





</pre>

<p><font color="#FF0000"><b> <span lang="en-ca">This simple output result 
demonstrate the relation actually choose all elements from A as first</span></b></font></p>

<p><span lang="en-ca"><font color="#FF0000"><b>element in each pair, and 
elements from B as second in each pair by condition that first element </b>
</font></span></p>

<p><span lang="en-ca"><font color="#FF0000"><b>is bigger that second element</b></font></span><font color="#FF0000"><b><span lang="en-ca">:</span></b></font></p>

<pre>Set name is 'this is 0' and data is: data no 0 is 41

Set name is 'this is 1' and data is: data no 0 is 17

Set name is 'this is 2' and data is: data no 0 is 34

Set name is 'this is 3' and data is: data no 0 is 40

Set name is 'this is 4' and data is: data no 0 is 89

Set name is 'this is 5' and data is: data no 0 is 64

Set name is 'this is 6' and data is: data no 0 is 48

Set name is 'this is 7' and data is: data no 0 is 18

Set name is 'this is 8' and data is: data no 0 is 52

Set name is 'this is 9' and data is: data no 0 is 74

Now show Set A

Set name is 'this is set A' and data is: 
Set name is 'this is 0' and data is: data no 0 is 41

Set name is 'this is 1' and data is: data no 0 is 17

Set name is 'this is 2' and data is: data no 0 is 34

Set name is 'this is 3' and data is: data no 0 is 40

Set name is 'this is 4' and data is: data no 0 is 89

Set name is 'this is 5' and data is: data no 0 is 64

Set name is 'this is 6' and data is: data no 0 is 48

Now show Set B

Set name is 'this is set B' and data is: 
Set name is 'this is 7' and data is: data no 0 is 18

Set name is 'this is 8' and data is: data no 0 is 52

Set name is 'this is 9' and data is: data no 0 is 74

pair no.0 is 
 x is 89
 y is 18
pair no.1 is 
 x is 40
 y is 18
pair no.2 is 
 x is 34
 y is 18
pair no.3 is 
 x is 41
 y is 18
pair no.4 is 
 x is 48
 y is 18
pair no.5 is 
 x is 64
 y is 52
pair no.6 is 
 x is 64
 y is 18
pair no.7 is 
 x is 89
 y is 74
pair no.8 is 
 x is 89
 y is 52
</pre>

<p>¡¡</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp; <a href="Monopoly.htm">                  







                       <img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<a href="index.htm"><img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a>       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                         
<img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35">          


</p>

</body>

</html>