ifstream into contructors

I have two text(.txt) files (books and cards) that read:

Art of War
Sun Tzu
0195014766
1
0

explanation of above: title, author, ISBN #, status of the book, ID number of person who has taken out the book.

then the Card.txt file:

John Smith
9080341902
9999
0


explanation of above: Name, phone #, card number, books taken out.
both .txt files could have up to 500 items in each.

Now I have 2 class files for both Books and Cards. And another one called Library.

My question is how would I read those two files through the Library constructor and put them into arrays of Book[500] and Card[500]?

I need to go through books and cards (nested loop), be able to add, remove books and cards.

Any help would be great help and much appreciated.
Thank you.
Last edited on
you can use a constructor that take a path file for the books and cards:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Library::Library(const string &pathBooks, const string &pathCards){
    //use a temporary variables
    string bookTitle, bookAuthor,name,phone,ISBN;
    int bookStatus,ID,cardNumber,takenOut;
    ifstream books(pathBooks.c_str(),ios::in);
    ifstream cards(pathCards.c_str(),ios::in);
    if(books && cards){
        do{
            getline(books,bookTitle,256,'\n');
            getline(books,bookAuthor,256,'\n');
            getline(books,ISBN,256,'\n');
            books>>bookStatus>>ID;
            vBooks.insert(Book(bookTitle,bookAuthor,ISBN,bookStatus,ID); //if 'Library has a 'vector<Book>' for the books and 'Book' has constructor with parameters
        }while(books.good());
        do{
            getline(cards,name,256,'\n');
            getline(cards,phone,256,'\n');
            cards>>cardNumber>>takenOut;
            vCards.insert(Card(name,phone,cardNumber,takenOut)); //if 'Library' has a 'vector<Card>' for the cards and 'Card' has constructor with parameters
        }while(cards.good());
    }
}
This looks great. Thank you.
I will try to do it this way.


But would something like this also work? if so how?

Library::Library(ifstream &pathBooks, ifstream &pathCards) ???


EDIT:
I do have a vector for both card and book, but when I added:

cardlist.insert(Card(name,phone,cardNumber,takenOut));

get three errors, one at the dot operator, saying "no instance of overloaded function "std::vector<_Ty, _Ax>::insert [with _Ty=Card, _Ax=std::allocator<Card>]" matches the argument list"

the other one saying, no instance of constructor "Card::Card" matches the argument list.


Last edited on
yes, your constructor of Library can work fine, for example in this way:
1
2
    ifstream books,cards;
    Library library(books,cards);

then the error occours because in the class definition of Book and Card, you should define the prototype of those constructor:
1
2
3
4
5
6
7
8
9
class Book{
    //definition of the class
    Book(const string &title,const string &author,const string &isbn,int status,int id);
    //other code
};

class Card{
    Card(const string &name, const string &phone, int number,int taken);
};

with their implementation.
The other error is because insert() use an iterator for the position int its parameters, a solution can be:
1
2
vector<Card>::iterator pos=cardlist.begin();
cardlist.insert(pos,Card(/*the parameters*/));

the same for the booklist.
Last edited on
Thank you for your response.

this is what I have so far as of reading from files.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Library::Library(ifstream& inbooks, ifstream& incards)
{
	//temporary variables
	string title, author, name;
	int ISBN, status, holderID, phonenum, cardnum, booksout;

	//reading Books
	getline(inbooks, title);						//reads title
	getline(inbooks, author);					//reads author
	inbooks >> ISBN >> status >> holderID;		//reads ISBN, status and holders ID

	//reading Cards
	getline(incards, name);
	incards >> phonenum >> cardnum >> booksout;

	//vector<Book>::iterator it = booklist.begin();
	booklist.insert(booklist.begin(), Book(title,author,ISBN,status,holderID));
	cardlist.insert(cardlist.begin(), Card(name,phonenum,cardnum,booksout));
}


That should read from both card.txt and book.txt correct?

I am now trying to display books and cards to the output screen.
Classes Book and Card both have printCards() and printBooks()

and in the Library class I have:
1
2
3
4
5
6
void Library::showBookss()
{
	cout << "Current books in the library: " << endl;
	for (int i=0; i < booklist.size(); i++)
		inbooks->printbooks();
}


but nothing shows?

Thank you.
post the implementation of the print() function of Book and Card, so we can solve this.
Card:
1
2
3
4
5
6
7
8
void Card::printcards()
{
	cout << endl;
	cout << "Name: " << name << endl;
	cout << "Phone Number: " << phonenum << endl;
	cout << "ID Number: " << cardnum << endl;
	cout << "Books taken out: " <<  booksout << endl;
}

Book:
1
2
3
4
5
6
7
8
9
void Book::printbooks()
{
	cout << endl;
	cout << "Title: " << title << endl;
	cout << "Author: " << author << endl;
	cout << "ISBN-10: " << ISBN << endl;
	cout << "Status: " << status << endl;
	cout << "Holder's ID number: " << holderID << endl << endl;
}


title,author,isbn, etc are all private data members.
in the function Library::showBooks() what's 'inbooks' ? Maybe you call the function 'printBook' on a variable that isn't initialized. try to change in this way:
1
2
3
4
5
6
7
8
9
10
void Library::showBookss()
{
        if(booklist.size() > 0){	
            vector<Book>::iterator val=booklist.begin();
            do{
                (*val).printBook();
                val++;
            }while(val!=booklist.end());
        }else cout<<"\nNo books in Library.\n";
}
inbooks is a pointer to class Book.

heres my .h file for library.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include "Card.h"
#include "Book.h"
#include <vector>
using namespace std;

#ifndef LIBRARY_H
#define LIBRARY_H

class Library
{
private:
	vector<Card> cardlist;
	vector<Book> booklist;

	Book *inbooks;
	Card *incards;
public:

	Library();
	Library(ifstream& inbooks, ifstream& incards);

	void showBookss();
	void showCardss();

	void checkin();
	void checkout();

	void addBook();
	void addCard();

	void saveall();
	void showMenu();
	int doCommand(int command);
};
#endif 


I tried what you posted above, it does not display books.
Why do you need inbooks and incards with cardlist and booklist?

1
2
3
4
5
6
void Library::showBookss()
{
	cout << "Current books in the library: " << endl;
	for (int i=0; i < booklist.size(); i++)
		inbooks->printbooks();
}


How is inbooks related to booklist.size() and why are you invoking printbooks on the same instance multiple times?

Last edited on
Library has(components) of Book and Card. I created vectors to hold the information read from files.

I am not very familiar with vectors but i decided to try them since I read they are good STL containers.

inbooks holds the information read from the files, through my Library constructor.
For how many ever books are in booklist print out the books ???

Nothing shows when told to display books from the file, but when I add new books(inside the program, though addBooks() function also writes back to the same .txt file), showBookss() displays all the new books added, but its not reading from the file, only whats stored in memory.
According to the code you posted for your Library constructor, inbook does not hold the information read from the files, but booklist does.

booklist.size() has nothing to do with whatever is in inbooks, if anything. You don't allocate any memory for inbooks/incards in your Library constructor or assign them any meaningful value.

You never check to see if any input operations are successful. Are you opening the ifstream objects before passing them to the constructor?
Yes you are correct, there is no direct relationship between those two I realized, how would I set up a relationship between the vectors and Book/Card objects in library?


You don't allocate any memory for inbooks/incards in your Library constructor or assign them any meaningful value.


inbooks = new Book;
inbooks->setTitle(title);
inbooks->setAuthor(author);
etc
in the constructor, correct?


Are you opening the ifstream objects before passing them to the constructor?


Yes, ifstream objects are being opened in the main and being passed to the Library constructor.
Last edited on
inbooks = new Book;
inbooks->setTitle(title);
inbooks->setAuthor(author);
etc
in the constructor, correct?


That would allocate memory for one Book. That would be a small library.

If you're going to use the vectors, get rid of the pointers.
int numbooks = 500;

for(int i = 0; i < numBooks; i++)
{
inbooks = new Book;
inbooks->setTitle(title);
inbooks->setAuthor(author);
}
???

alright, I get rid of pointers, how will I show books/cards(from file), add new books/cards in their respective vector(and write back to file).
meanwhile I shall read more on vectors.
1
2
3
4
5
6
7
8
int numbooks = 500;

for(int i = 0; i < numBooks; i++)
{
   inbooks = new Book;
   inbooks->setTitle(title);
   inbooks->setAuthor(author);
}


This allocates space for one Book 500 times, and discards the address of the previously allocated Book on each iteration. In other words, that's a big memory leak.

1
2
int numbooks = 500 ;
inbooks = new Book[500] ;


inbooks now points 500 Books. But then your library must keep track of the number of valid book objects that are stored. What happens when your collection grows beyond 500?

The vector addresses these issues internally, so you don't have to.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Library::addBook()
{
     cout << "Title: " ;
     string title;
     getline(cin, title) ;

     cout << "Author: " ;
     string author ;
     getline(cin, author) ;

    cout << "ISBN: " ;
    string ISBN ;
    getline(cin, ISBN) ;

    booklist.push_back(Book(title, author, ISBN, /* status and id */)) ;
}


Vins code to show the books is good, and cards would be similar. Your Library constructor looks good to me, except I'd probably use push_back() over insert().


Last edited on
This is exactly what I have for my definition of addBook(), but I need to write back to book.txt file, how will I do that with a vector?
I think you need to ask the question: When should I update book.txt? It doesn't really have much to do with the container type you're using.

Perhaps it's appropriate to do it in addBook:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Library::addBook()
{
     cout << "Title: " ;
     string title;
     getline(cin, title) ;

     cout << "Author: " ;
     string author ;
     getline(cin, author) ;

    cout << "ISBN: " ;
    string ISBN ;
    getline(cin, ISBN) ;

    booklist.push_back(Book(title, author, ISBN, /* status and id */)) ;

    ofstream out( "book.txt", ios::ate | ios::out) ;

    out << author << '\n' << title << '\n' << ISBN << '\n' << /*status*/ << '\n' << /*id*/ << '\n' ;
}

Topic archived. No new replies allowed.