Dear all,
The concept behind the code is:
There is an associationlist that holds association pointers. Each association pointer has two pointers, that point to a book
and to a member object respectively.
Now what I'm trying to do is:
To have the association pointer to use its two pointers to point to an array of books(booklist, up to 10 books) and to an
array of members (memberlist, up to 10) respectively.
If you copy and paste the code the program works ok only for books(adding a new book to the booklist(up to 3 for test
purposes) and displaying the books).
If one wants to add a member and display the members, they have to use the function: get_book(); in the file : template<class
Object>
void List<Object>::displayElement(char* type) of the List.cpp, and also to put in comments the
//book1.displayElement("Books" of the main.cpp file.
If I don't use the comments in the main.cpp file and use the get_book() function then an error will occur: " 'get_book'
:cannot convert parameter 1 from 'class Book*' to 'class Member*' "
Could someone suggest a solution using a single template function, for displaying members and books?
The code of each file is:
and finally
//main()
What I want to do is to use one function for displaying members and books (to use a template).
What needs to be changed to use only one function for displaying members and books?
Regards,
grscot
The concept behind the code is:
There is an associationlist that holds association pointers. Each association pointer has two pointers, that point to a book
and to a member object respectively.
Now what I'm trying to do is:
To have the association pointer to use its two pointers to point to an array of books(booklist, up to 10 books) and to an
array of members (memberlist, up to 10) respectively.
If you copy and paste the code the program works ok only for books(adding a new book to the booklist(up to 3 for test
purposes) and displaying the books).
If one wants to add a member and display the members, they have to use the function: get_book(); in the file : template<class
Object>
void List<Object>::displayElement(char* type) of the List.cpp, and also to put in comments the
//book1.displayElement("Books" of the main.cpp file.
If I don't use the comments in the main.cpp file and use the get_book() function then an error will occur: " 'get_book'
:cannot convert parameter 1 from 'class Book*' to 'class Member*' "
Could someone suggest a solution using a single template function, for displaying members and books?
The code of each file is:
Code:
//Association.h
#ifndef _ASSOCIATION
#define _ASSOCIATION
//#include "Book.h"
//#include "Member.h"
template<class Book,class Member>
class Association
{
public:
//Sets up book and member with parameters
Association(Book* book, Member* member);
//Returns Book
Book* linked_book(){return this->book;}
//Returns Member
Member* linked_member(){return this->member;}
private:
Book* book;
Member* member;
};
#endif
Code:
//Association.cpp
#ifndef _ASSOCIATIONCPP
#define _ASSOCIATIONCPP
#include "Association.h"
template<class Book,class Member>
Association<Book,Member>::Association(Book* book, Member* member)
{
this->book=book;
this->member=member;
}
#endif
Code:
//AssociationList.h
#ifndef _ASSOCIATIONLIST
#define _ASSOCIATIONLIST
#include "Association.h"
//#include "Book.h"
//#include "Member.h"
const int LIST_SIZE=100;
template<class Book,class Member>
class AssociationList
{
public:
//It initialises all slots in the associationlist array to zero.
AssociationList();
/* It searches the associationlist, if book is found then returns
the member that is connected with.*/
Member* get_member(Book* book);
/* It searches the associationlist, if member is found then returns
the book that is connected with.*/
Book* get_book(Member* member);
template<class R,class P>
R* get_member(P* pArg);
/* Checks that book/member not already linked
creates association if objects are free to link
returns whether or not link was valid */
bool link(Book* book,Member* member);
/* Checks that book and member are linked
deletes association if they are linked
returns whether or not unlinking was valid */
bool unlink(Book* book,Member* member);
private:
Association<Book,Member>* association_list[LIST_SIZE];
};
#endif
Code:
//AssociationList.cpp
#ifndef _ASSOCIATIONLISTCPP
#define _ASSOCIATIONLISTCPP
#include <iostream>
#include "Association.h"
#include "Association.cpp"
#include "AssociationList.h"
#include "Book.h"
#include "Member.h"
using namespace std;
template<class Book,class Member>
AssociationList<Book,Member>::AssociationList()
{
cout<<"AssociationList constructor called\n";
int index;
for(index=0; index<LIST_SIZE; index++)
this->association_list[index]=0;
}
/*template<class R,class P>
R* AssociationList<Book,Member>::get_member(P* pArg)
{
R* member=0;
bool searching=true;
int index=0;
while(searching)
{
if (this->association_list[index])
if (this->association_list[index]->linked_book()==book)
{
member=this->association_list[index]->linked_member();
searching=false;
}
else
index++;
else
index++;
if (searching && (index == LIST_SIZE))
{
searching=false;
}
}
return member;
}*/
template<class Book,class Member>
//Member* AssociationList::get_member(Book* book)
Member* AssociationList<Book,Member>::get_member(Book* book)
{
Member* member=0;
bool searching=true;
int index=0;
while(searching)
{
if (this->association_list[index])
if (this->association_list[index]->linked_book()==book)
{
member=this->association_list[index]->linked_member();
searching=false;
}
else
index++;
else
index++;
if (searching && (index == LIST_SIZE))
{
searching=false;
}
}
return member;
}
template<class Book,class Member>
Book* AssociationList<Book,Member>::get_book(Member* member)
{
Book* book=0;
bool searching=true;
int index=0;
while(searching)
{
if (this->association_list[index])
if (this->association_list[index]->linked_member()==member)
{
book=this->association_list[index]->linked_book();
searching=false;
}
else
index++;
else
index++;
if (searching && (index == LIST_SIZE))
{
searching = false;
}
}
return book;
}
template<class Book,class Member>
bool AssociationList<Book,Member>::link(Book* book,Member* member)
{
bool searching=true;
bool success=true;
int index=0;
int free_slot;
while(searching)
{
if(this->association_list[index])
if((this->association_list[index]->linked_book()==book ||
(this->association_list[index]->linked_member()==member)))
{
searching=false;
success=false;
}
else
index++;
else
{
free_slot=index;
index++;
}
if(searching&&(index == LIST_SIZE))
searching=false;
}
if (success)
this->association_list[free_slot]=new Association(book,member);
return success;
}
template<class Book,class Member>
bool AssociationList<Book,Member>::unlink(Book* book,Member* member)
{
bool searching=true;
bool success=true;
int index=0;
int link_slot;
while(searching)
{
if (this->association_list[index])
if (this->association_list[index]->linked_book()==book &&
this->association_list[index]->linked_member()==member)
{
searching=false;
link_slot=index;
}
else
index++;
else
{
index++;
}
if (searching && (index == LIST_SIZE))
{
searching=false;
success=false;
}
}
if (success)
delete this->association_list[link_slot];
return success;
}
#endif
Code:
//Book.cpp
#include<iostream>
#include"Book.h"
#include"Member.h"
using namespace std;
Book::Book()
{
cout<<"Book constructor called called\n";
this->bookDetails=get_string_ver2("input book title and author separated by a comma and a space character: ");
}
Book::~Book()
{
if (this->bookDetails)
delete [] this->bookDetails;
}
void Book::display(Member* borrower)
{
cout<<"Book title and author are: "<<this->bookDetails<<"."<<endl;
if (borrower)
cout<<"The member's name is: "<<borrower->get_name()<<"."<<endl;
else
cout<<"No member has borrowed a book."<<endl;
}
Code:
//Book.h
#ifndef _BOOK
#define _BOOK
#include "utility.h"
class Member;//Forward Reference
class Book
{
public:
//Reads and allocates space for title and author.
Book();
//Releases the space pointed at by the title and author.
~Book();
//Returns the book title and author.
char* get_bookDetails(){return this->bookDetails;}
//Displays the book title and author and the member who has borrowed the book as applicable.
void display(Member* borrower);
private:
Member* borrower;
char* bookDetails;
};
#endif
Code:
//Member.cpp
#include<iostream>
#include"Book.h"
#include"Member.h"
using namespace std;
Member::Member()
{
cout<<"Member constructor called\n";
this->name=get_string("Input member's surname and forename respectively, separated by a comma and a space character:
");
}
Member::~Member()
{
if (this->name)
delete [] this->name;
}
void Member::display(Book* book)
{
cout<<"Member's name is: "<<this->name<<"."<<endl;
if (book)
cout<<"Book title and author are: "<<book->get_bookDetails()<<"."<<endl;
else
cout<<this->name<<" has not borrowed any book."<<endl;
}
Code:
//Member.h
#ifndef _MEMBER
#define _MEMBER
#include "utility.h"
class Book;//Forward Reference
class Member
{
public:
//Reads and allocates space for member's full name.
Member();
//Releases the space pointed at by name.
~Member();
//Returns member's full name.
char* get_name(){return this->name;}
//Displays the member's full name and the book borrowed by the member as applicable.
void display(Book* book);
private:
Book* book;
char* name;
};
#endif
Code:
//List.cpp
#ifndef _LISTCPP
#define _LISTCPP
#include <iostream>
#include "AssociationList.h"
//#include "Book.h"
#include "List.h"
//#include "Member.h"
using namespace std;
template<class Object>
List<Object>::List()
{
this->num_elements=0;
}
template<class Object>
List<Object>::~List()
{
for(int element=0; element<this->num_elements; element++)
delete this->element_list[element];
}
template<class Object>
void List<Object>::addElement(char* type)
{
if (this->num_elements == MAX_ELEMENTS)
{
cout<<"No more room in the "<<type<<" array.\n";
cout<<"The maximum number of "<<type<<" is "<<MAX_ELEMENTS<<"."<<endl;
}
else
{
this->element_list[num_elements]=new Object;
(this->num_elements)++;
}
}
template<class Object>
void List<Object>::displayElement(char* type)
{
if (num_elements == 0)
cout<<"No "<<type<<" is found in the "<<type<<" array.\n";
else
for(int element=0; element<this->num_elements; element++)
{
cout<<'\n';
this->element_list[element]->display(association_list.get_member(element_list[element]));
}
}
template<class Object>
void List<Object>::borrowElement()
{
cout<<"Borrow book function invoked\n";
}
template<class Object>
void List<Object>::returnElement()
{
cout<<"Return book function invoked\n";
}
#endif
Code:
//List.h
#ifndef _LIST
#define _LIST
#include "AssociationList.h"
#include "Book.h"
#include "Member.h"
const int MAX_ELEMENTS=3;
template<class Object>
class List
{
public:
List();
~List();
void addElement(char* type);
void removeElement();
void displayElement(char* type);
void borrowElement();
void returnElement();
private:
AssociationList<Book,Member>association_list;
Object* element_list[MAX_ELEMENTS];
int num_elements;
};
#endif
Code:
//utility.cpp
#include <iostream>
#include <cstring>
#include <ctype.h>
using namespace std;
#define cinFlush cin.seekg(ios::end)
char* get_string (char* prompt)
{
const int MAX_SIZE=100;
char string[MAX_SIZE];
char* out_string;
char *substring=", ";
int position=0;
bool result=false;
do
{
cout<<prompt; cinFlush;
//cin>>string;
//cin.get();
cin.getline(string,MAX_SIZE);
if (strstr(string,substring) == NULL)
{
cout<<"Invalid Name(substring ', ' not found into the string)"<<endl;
result=false;
}
else
{
position=strstr(string,substring) - string;
if (position == 0)
{
cout<<"Invalid Name(substring ', ' found in the beginning of the string)"<<endl;
result=false;
}
else if (toascii(string[position + 1]) == 32 && string[position + 2] == '\0')
{
cout<<"Invalid Name(substring ', ' found at the end of the string)"<<endl;
result=false;
}
else
{
for(int j=0; j<position; j++)
if ((toascii(string[j]) >= 0 && toascii(string[j]) <= 64)
|| (toascii(string[j]) >= 91 && toascii(string[j]) <= 96)
|| (toascii(string[j]) >= 123 && toascii(string[j]) <= 127))
{
cout<<"Invalid character(s) found before the substring ', '"<<endl;
result=false;
break;
}
else
{
for(int m=position + 2; m<strlen(string); m++)
if ((toascii(string[m]) >= 0 && toascii(string[m]) <= 64)
|| (toascii(string[m]) >= 91 && toascii(string[m]) <= 96)
|| (toascii(string[m]) >= 123 && toascii(string[m]) <= 127))
{
result=false;
break;
}
else
result=true;
}
}
}
}while(!result && !cin.eof());
out_string=new char [strlen(string)+1];
if (out_string)
strcpy(out_string,string);
return out_string;
}
char* get_string_ver2 (char* prompt)
{
const int MAX_SIZE=100;
char string[MAX_SIZE];
char* out_string;
char *substring=", ";//new
int position=0;//new
bool result=false;//new
do//new
{//new
cout<<prompt; cinFlush;
//cin>>string;
//cin.get();
cin.getline(string,MAX_SIZE);
if (strstr(string,substring) == NULL)
{
cout<<"Invalid String(substring ', ' not found into the string)"<<endl;
result=false;
}
else
{
position=strstr(string,substring) - string;
if (position == 0)
{
//cout<<"Substring found at position: "<<position<<endl;
cout<<"Invalid String(substring ', ' found in the beginning of the string)"<<endl;
result=false;
}
else if (toascii(string[position + 1]) == 32 && string[position + 2] == '\0')
{
//cout<<"Substring found at position: "<<position<<endl;
cout<<"Invalid String(substring ', ' found at the end of the string)"<<endl;
result=false;
}
else
{
for(int z=0;z<position; z++)
if (!(( toascii(string[z]) > 64 && toascii(string[z]) < 91 )
|| ( toascii(string[z]) > 96 && toascii(string[z]) < 123)
|| ( toascii(string[z]) == 32)))
{
cout<<"Invalid character(s) found before the substring"<<endl;
result=false;
break;
}
else
{
for(int m=position + 2; m<strlen(string); m++)
if (!(( toascii(string[z]) > 64 && toascii(string[z]) < 91 )
|| ( toascii(string[z]) > 96 && toascii(string[z]) < 123)
|| ( toascii(string[z]) == 32)))
{
result=false;
break;
}
else
result=true;
}
}
}
}while(!result);
out_string=new char [strlen(string)+1];
if (out_string)
strcpy(out_string,string);
return out_string;
}
void hold_screen()
{
char ch;
cout << "hit enter to continue" << endl;
cin.get(ch);
}
void prompt_to_quit()
{
char ch;
cout << "hit enter to quit" << endl;
cin.get(ch);
}
Code:
//utility.h
#ifndef _UTILITY
#define _UTILITY
/* prompts for a string, checks for the existence of
the substring ', ' and for valid characters before
and after the substring and finally dynamically
allocates space to store the string, returns the
pointer to the allocated storage or 0 if the allocation fails */
char* get_string (char* prompt);
/* prompts for a string, checks for the existence of
the substring ', ' and for valid characters before
and after the substring and finally dynamically
allocates space to store the string, returns the
pointer to the allocated storage or 0 if the allocation fails */
char* get_string_ver2(char* prompt);
/* prompts for a carriage return character to hold
window on display before program continues */
void hold_screen();
/* prompts for a carriage return character to hold
window on display before program ends */
void prompt_to_quit();
/* prompts for a string up to 100 characters
and checks whether the string characters are all alphabetical
returns either true or false. */
//bool validateInput(char *input);
#endif
//main()
Code:
#include <iostream>
#include "List.cpp"
#include "Association.cpp"
#include "AssociationList.h"
#include "AssociationList.cpp"
#include "Book.h"
#include <conio.h>
#include "Member.h"
#include "utility.h"
#define cinFlush cin.seekg(ios::end)
using namespace std;
void main()
{
List<Member>member1;
List<Book>book1;
char menuChoice;
do
{
cout<<'\n';
cout<<'\n';
cout<<"**** Main Menu ****"<<endl;
cout<<'\n';
cout<<"1: Add Book "<<endl;
cout<<'\n';
cout<<"2: Remove Book "<<endl;
cout<<'\n';
cout<<"3: Display Books "<<endl;
cout<<'\n';
cout<<"4: Add Member "<<endl;
cout<<'\n';
cout<<"5: Remove Member "<<endl;
cout<<'\n';
cout<<"6: Display Members "<<endl;
cout<<'\n';
cout<<"7: Borrow Book "<<endl;
cout<<'\n';
cout<<"8: Return Book "<<endl;
cout<<'\n';
cout<<"0: Quit "<<endl;
cout<<endl;
cout<<"Enter one of the above choices: ";cinFlush;
cin>>menuChoice;
switch(menuChoice)
{
case '1': cout<<'\n';
book1.addElement("Books");
break;
case '2': cout<<'\n';
break;
case '3': cout<<'\n';
book1.displayElement("Books");
break;
case '4': cout<<'\n';
//member1.addElement("Member");
break;
case '5': cout<<'\n';
break;
case '6': cout<<'\n';
//member1.displayElement("Member");
break;
case '7': cout<<'\n';
//book1.borrowElement();
break;
case '8': cout<<'\n';
//book1.returnElement();
break;
default: cout<<'\n';
cout<<"Invalid Selection\n";
}
}while(menuChoice != '0' && !cin.eof());
prompt_to_quit();
}
What I want to do is to use one function for displaying members and books (to use a template).
What needs to be changed to use only one function for displaying members and books?
Regards,
grscot