PTL.cpp
// Test program for Eli Tilevich which was originally coded in two versions for
// for comparison between Data Object Library and Pattern Template Library.
#include <stdio.h>
#include <string.h>
#include "manymany.h"
#include <mgr.h>
class School;
class Student;
class Takes;
class Class;
// School encapsulates your problem
class School : public CollectionParent<School,Student>,
public CollectionParent<School,Class> {
public:
School(){}
char *getName(int i,char *buf);
};
class Student : public CollectionChild<School,Student>,
public ManyToManySource<Student,Takes,Class> {
char *sName;
public:
Student(char *name){
if(name)sName=new char[strlen(name)+1]; else sName=NULL;
if(sName)strcpy(sName,name);
}
~Student(){if(sName)delete[] sName;}
char *getName(){return sName;}
};
class Class : public CollectionChild<School,Class>,
public ManyToManyTarget<Student,Takes,Class> {
char *cName;
public:
Class(char *name){
if(name)cName=new char[strlen(name)+1]; else cName=NULL;
if(cName)strcpy(cName,name);
}
~Class(){if(cName)delete[] cName;}
char *getName(){return cName;}
};
class Takes : public ManyToManyRelation<Student,Takes,Class> {
int mark;
int absentDays;
public:
int addAbsent(int d){absentDays+=d; return absentDays;} // for d=0 reports
int getMark(){return mark;}
void setMark(int m){mark=m;}
};
// ----------- data organization --------------
ManyToMany<Student,Takes,Class> scRelation;
Collection<School,Student> students;
Collection<School,Class> classes;
// --------------------------------------------
// pick up names including spaces, if i>0 skip the first word
char* School::getName(int i,char *buf){
char *p;
for(p=buf; *p!='\n'; p++)continue;
*p='\0'; // mark the end of the name
if(i==0)return buf;
for(p=buf; *p!='\0' && *p!=' '; p++)continue;
if(*p=='\0')return p;
for( ;*p==' ' && *p!='\0'; p++);
return p;
}
#define BSIZE 80
char buff[BSIZE];
char* fileName="eli.dat";
// compared to DOL, the main is shorter, because PTL does not store data to disk
int main(int argc,char **argv) {
School *school; Student *sp; Takes *tp; Class *cp;
char *name,cc;
CollectionIterator<School,Student> sit;
CollectionIterator<School,Class> cit;
ManyToManySourceIterator<Student,Takes,Class> sourceIter;
school=new School;
for(;;){
printf("type your name (STOP to stop the program):\n");
fgets(buff,BSIZE,stdin);
name=school->getName(0,buff);
if(!strcmp(name,"STOP"))break;
ITERATE(sit,school,sp){ // search for 'your name'
if(!strcmp(name,sp->getName()))break;
}
if(sp){
printf("registered in:");
ITERATE(sourceIter,sp,tp){ // walk through all Takes's of sp
cp=scRelation.target(tp);
printf("(%s)",cp->getName());
}
printf("\n");
}
else {
printf("new student=%s\n",name);
sp=new Student(name);
students.addTail(school,sp);
}
for(;;){
printf("menu(A className,D className,R=remove student,E=exit):\n");
fgets(buff,BSIZE,stdin);
sscanf(buff,"%c",&cc);
name=school->getName(1,buff);
if(cc=='A'){
// first check that this student isn't already registered there
ITERATE(sourceIter,sp,tp){ // walk through all Takes's of sp
cp=scRelation.target(tp);
if(!strcmp(name,cp->getName()))break;
}
if(tp){ printf("... you are already registered\n"); continue;}
// find the class
ITERATE(cit,school,cp){ // search for the given class
if(!strcmp(name,cp->getName()))break;
}
if(!cp){
printf("... new class\n");
cp=new Class(name);
classes.addTail(school,cp);
}
tp=new Takes; // many-to-many involves 3 object types!!
scRelation.add(sp,tp,cp);
}
else if(cc=='D'){
ITERATE(sourceIter,sp,tp){ // walk through all Takes's of sp
cp=scRelation.target(tp);
if(!strcmp(name,cp->getName()))break;
}
if(!tp){
printf(" you are not registered for this class\n");
continue;
}
scRelation.remove(tp); // disconnect tp
delete tp;
}
else if(cc=='R'){
// delete all class links of this student
ITERATE(sourceIter,sp,tp){ // walk through all Takes's of sp
scRelation.remove(tp); // disconnect tp
delete tp; // yes, this is allowed within the loop!
}
students.remove(school,sp);
break;
}
else if(cc=='E')break;
else printf("unknown command=%c\n",cc);
}
}
return(0);
}