Thread: Template question

  1. #1
    Registered User
    Join Date
    Apr 2003
    Posts
    16

    Template question

    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:

    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
    and finally
    //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

  2. #2
    Veni Vidi Vice
    Join Date
    Aug 2001
    Posts
    343
    Reading code, reading code reading code ....... ZZZZzzzzzz....sleeping......
    I´m sorry to say this but we dont like when people cross-post threads. And do really expect someone to debug your code that is like 1000 lines??? Try to isolate what portion of code is problematic and post relevat code and it would be easier to help.

    Could someone suggest a solution using a single template function, for displaying members and books?
    You could start be reading previous post.
    Last edited by ripper079; 04-29-2003 at 03:15 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Default class template problem
    By Elysia in forum C++ Programming
    Replies: 5
    Last Post: 07-11-2008, 08:44 AM
  2. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  3. another template question
    By l2u in forum C++ Programming
    Replies: 4
    Last Post: 02-13-2008, 03:52 PM
  4. Quick question about class template
    By merixa in forum C++ Programming
    Replies: 5
    Last Post: 12-06-2005, 11:43 PM
  5. Nested loop frustration
    By caroundw5h in forum C Programming
    Replies: 14
    Last Post: 03-15-2004, 09:45 PM