Printing out elements in a list - c++

Book Administrator::bookDetails()
{
Book book;
list<Book> books;
string title;
string author;
int ISBN;
string userInput;
while (userInput != "q")
{
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
book.setTitle(title);
book.setAuthor(author);
book.setISBN(ISBN);
books.push_back(book);
}
list<Book>::iterator pos;
pos = books.begin();
for (pos = books.begin(); pos != books.end(); pos++)
{
//There error is produced here
cout << *pos << "\n";
}
}
return book;
}
This is the bookDetails function of my Administration class. It loops through and asks for a books title, author and ISBN number and when its finished it pushes the book onto a list.
This seems to work fine when i debug it but i get an error when i try to print out the details of each book using the iterator.
Can anyone help me out here?
Thanks

You need to implement operator<< for Book
std::ostream operator<<(std::ostream& os, const Book& book)
{
os << book.title << " " << book.author; // print out other information
return os;
}

Related

Arranging Vector Outputs from multiple string variables

This is an assignment I am attempting to work on where I am attempting to create a program that asks for a books title, its author, and its date of publication, before displaying all inputs at the end. My primary obstacle is trying to get everything to display in a somewhat decent way, with additional text written to clarify the information properly.
It should look like this:
Title: Great Expectations Fahrenheit 451 Animal Farm
Author: Charles Dickens Ray Bradbury George Orwell
Date: 1824 1956 1948
#include <string>
#include <vector>
using namespace std;
int main ()
{
int i=0;
int n;
string bookTitle;
string bookAuthor;
string bookDate;
vector<string> Title;
vector<string> Author;
vector<string> Date;
cout << "Enter the Number of Books: ";
cin >> n;
cin.ignore();
for (i; i < n; i++)
{
cout << "Type the Book's Title: ";
getline (cin, bookTitle);
Title.push_back(bookTitle);
cout << "Type the Book's Author: ";
getline (cin, bookAuthor);
Author.push_back(bookAuthor);
cout << "Type the Book's Date: ";
getline (cin, bookDate);
Date.push_back(bookDate);
}
cout << endl;
cout << "The Titles: ";
for (auto it = Title.begin(); it != Title.end(); ++it) {
cout << *it << " ";
}
cout << endl;
cout << "Written by: ";
for (auto ib = Author.begin(); ib != Author.end(); ++ib) {
cout << *ib << " ";
}
cout << endl;
cout << "Written in: ";
for (auto ic = Date.begin(); ic != Date.end(); ++ic) {
cout << *ic << " ";
}
return 0;
}
First, let's organize your code a bit, by storing each book in a structure:
struct Book {
string title;
string author;
string date;
};
vector<Book> books;
Read them like this:
for (int i = 0; i < n; i++)
{
Book book;
getline (cin, book.title);
getline (cin, book.author);
getline (cin, book.date);
books.push_back(book);
}
For each book, you can store a useful column width for your output. To keep it simple, only the book's title and author are considered when choosing the column width:
vector<int> widths;
int padding = 2;
for (const Book& book : books)
{
widths.push_back(padding + std::max(book.title.size(), book.author.size()));
}
Now, use std::setw from <iomanip> to set the appropriate column width for each book:
cout << "The Titles: ";
for (int i = 0; i < n; i++) {
cout << std::setw(widths[i]) << books[i].title;
}
cout << endl;
cout << "Written by: ";
for (int i = 0; i < n; i++) {
cout << std::setw(widths[i]) << books[i].author;
}
cout << endl;
cout << "Written in: ";
for (int i = 0; i < n; i++) {
cout << std::setw(widths[i]) << books[i].date;
}
cout << endl;
Output:
The Titles: Great Expectations Fahrenheit 451 Animal Farm
Written by: Charles Dickens Ray Bradbury George Orwell
Written in: 1824 1956 1948
I would recommend using the std::setw() function within the library to set a consistent field width to format the output neatly.
For example:
cout << setw(WIDTH) << *it << " ";

c++ programming function error

my full code is (couldn't make it smaller) :
/*password is admin*/
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
using namespace std;
//-------------------------------
fstream d_base;
char path[] = "library books.txt";
void output(){
//this function for displaying choices only
cout << "***********************************" << endl;
cout << "1. List all books in library" << endl;
cout << "2. List available books to borrow " << endl;
cout << "3. Borrow a Book from library" << endl;
cout << "4. Search For a Book" << endl;
cout << "5. Add New Books"<< endl;
cout << "6. Delete a Book" << endl;
cout << "7. EXIT The Library"<< endl;
cout << "***********************************" << endl;
}
//=====================================================================================================================================================
struct books{
//identfying books with all needed things
int id, status;
string title, p_name, p_address;
string aut_name, aut_nationality;
string date;
};
//=====================================================================================================================================================
//function for choice 1 showing the books (under constructions)
void choice1(){
ifstream show;
char all;
show.open(path, ios::in | ios::app);
while (!show.eof()){
show >> all;
if (all == '%'){
cout << "\n\n";
}
else if (all == '.'){
cout << "\n\n\n";
}
else
cout << all;
}
cout << endl;
show.close();
}
//=====================================================================================================================================================
void choice2(){
//function for choice 2 (list available books to borrow)
}
//=====================================================================================================================================================
void choice3(){
//function for choice 3( Borrow a Book )
}
//=====================================================================================================================================================
void choice4(){
char s;
ifstream search;
char idx;
cout << "what book you want to search for : ";
cin >> idx;
search.open(path, ios::in | ios::app);
while (!search.eof()){
search >> s;
if (s == idx)
cout << "book found" << endl;
break;
}
search.close();
}
//=====================================================================================================================================================
//for choice 5 to fill books (under constructions)
void choice5(books new_book[],books aut[], int books_number,int aut_number){
//function for adding books to the system
cout << "how many books you want to add ? ";
cin >> books_number;
//call the function to record the book
d_base.open(path, ios::out | ios::app);
for (int i = 0; i < books_number; i++){
d_base << "[Book Id]: " << new_book[i].id << "%[title]: " << new_book[i].title;
d_base << "%[Publisher Name]: " << new_book[i].p_name << "% [puplisher Address]: " << new_book[i].p_address;
for (int j = 0; j < aut_number; j++){
d_base << "%[author info]" << "%[Authors Name]: " << aut[i].aut_name << "%[Nationality]: " << aut[i].aut_nationality;
}
d_base << "%[PublishedAt]: " << new_book[i].date << "%[status]:" << new_book[i].status << "." << endl;
}
d_base.close();
}
//=====================================================================================================================================================
void choice6(){
//function for searching for a book
}
//=====================================================================================================================================================
int main(){
string choice;
cout << "welcome to FCIS library\n\n";
do{
output();
cout << "what do you want to do ? ";
getline( cin , choice);
if (choice == "1"){
choice1();
}
//this one for list available books
else if (choice == "2"){
choice2();
}
//this one for borrow a book
else if (choice == "3"){
//not completed yet don't choose 3
}
else if (choice == "4"){
choice4();
}
//this one is for adding new books to the list
else if (choice == "5"){
int books_number, aut_number;
books new_book[10000], aut[10000];
string password;
do{
cout << "you must be an admin to add new books." << endl << "please enter passowrd (use small letters) : ";
cin >> password;
if (password == "b")
break;
else if (password == "admin"){
cout << "ACCESS GAINED WELCOME " << endl;
cout << "what books you want to add :" << endl;
for (int i = 0; i < books_number; i++){
cout << "id please : "; cin >> new_book[i].id;
cout << "title : "; cin.ignore(); getline(cin, new_book[i].title);
cout << "publisher name :"; getline(cin, new_book[i].p_name);
cout << "publisher address : "; getline(cin, new_book[i].p_address);
cout << "Publish date :"; getline(cin, new_book[i].date);
cout << "How many copies of " << new_book[i].title << " "; cin >> new_book[i].status;
cout << "How Many Authors for the Book ?"; cin >> aut_number;
for (int j = 1; j <= aut_number; j++){
cout << "author number " << j << " name : "; cin.ignore(); getline(cin, aut[i].aut_name);
cout << "Nationality : "; getline(cin, aut[i].aut_nationality);
choice5(new_book[i], aut[j], books_number, aut_number);
}
}
}
else{
cout << "Wrong password try again or press (b) to try another choice";
continue;
}
} while (password != "admin");
}
//this one for deleteing a book
else if (choice == "6"){
//not completed yet
}
else if (choice == "7"){
cout << "Thanks for Using FCIS LIBRARY" << endl;
break;
}
else
cout << "\nwrong choice please choose again\n\n";
} while (true);
}
the problem is when i call the choice5() function it gets me errors :
*-IntelliSense: no suitable conversion function from "books" to "books
*-IntelliSense: no suitable conversion function from "books" to "books
-error C2664: 'void choice5(books [],books [],int,int)' : cannot convert argument 1 from 'books' to 'books []
i don't know if it's parameters problem or what!!
the choice5(); function call is in the main in the if(choice==5) after submitting books
and i'm like level 1 at c++ so i'm doing my best to make it smaller
i don't know if it's parameters problem or what!!
The compiler tells you exactly what and where the problem is: your call to choice5. The first parameter is an array of books and you're passing in a single book.
choice5(new_book[i], aut[j], books_number, aut_number);
new_book is an array, new_book[i] is a particular book in the array. Same goes for aut.
The function choice5(books new_book[],books aut[], int books_number,int aut_number) must receive as first parameter an array of books or a pointer to a struct books. You will have the same problem with the second parameter "aut". To match with the functioon definiton your call shall have this format :
choice5(new_book, aut, books_number, aut_number)

My list objects are being destroyed

list<Book> *books = new list<Book>;
list<Book>::iterator pos;
void Administrator::addBook()
{
Book *newBook = new Book();
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
cout << endl;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
cout << endl;
newBook->setTitle(title);
newBook->setAuthor(author);
newBook->setISBN(ISBN);
newBook->setAvailability(true);
books->push_back(*newBook);
}
}
*****************
I really need help with this, i have received a few answers today but none have helped me with this problem. This is my admin class. It creates books on the heap and stores them in an stl::list
void Guest::searchBook(Book* search)
{
string searchBook;
cout << "What book would you like to search for?" << endl;
cin >> searchBook;
printBookDetails();
}
This is my Guest class, what i would like to do here is to search through the list of books i created in my Administrator class but when it goes into the function printBookDetails, my list contains no elements, im assuming they've been destroyed.
Administrator* admin1 = new Administrator("jayfitz91", 24681357);
Guest* guest1 = new Guest("guest", 0000);
void main()
{
//Everything here works fine
admin1->addBook();
admin1->addBook();
admin1->makeAvailable();
admin1->printBookDetails();
//My list is destroyed at this point and it returns nothing
guest1->printBookDetails();
My Guest class inherits the printBookDetails from my Administrator class
All of the admin functions work but as soon as it gets to guest, the elements disappear.
Is there anyway i can get around this? The help would greatly be appreciated
Thanks to #OldProgrammer, i realised i had to return the list of books from my Admin class and pass it through as a parameter to my printBookDetails method in my guest class:
//Admin class
//Now returning a list
list<Book> Administrator::addBook()
{
Book *newBook = new Book();
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
cout << endl;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
cout << endl;
newBook->setTitle(title);
newBook->setAuthor(author);
newBook->setISBN(ISBN);
newBook->setAvailability(true);
books->push_back(*newBook);
}
return *books;
}
//Guest class function
void Guest::printBookList(list<Book> *tempList)
{
pos = tempList->begin();
for (pos = tempList->begin(); pos != tempList->end(); ++pos)
{
cout << pos->getTitle() << "\n"
<< pos->getAuthor() << "\n"
<< pos->getISBN() << "\n"
<< pos->getAvailability() << "\n"
<< "******************************" << endl;
}
}
//Main class function
//Create a temporary variable for the list
list<Book> tempList;
//pass it through to the method
guest1->printBookList(&tempList);
First off, you don't have to dynamically create your list object.
list<Book> books = new list<Book>();
You do this because
you have less responsibility: you don't have to release the resources contained by books. It will automatically be released.
list is a stl container, which means it automatically handles dynamic allocations.
This is different if you use an dynamically allocated array...
I think your list is "gone" is because Guest and Administrator has two entirely different list.
To solve this issue, you should grant access to the book list that Administrator has to your Guest.
Or extract out the book list and store it in another class that allow access to the list to both Administrator and Guest.

Creating a list pointer that points to other objects

list<Book*> books;
list<Book>::iterator pos, last;
Book Administrator::addBook()
{
Book *newBook = new Book();
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
cout << endl;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
cout << endl;
newBook->setTitle(title);
newBook->setAuthor(author);
newBook->setISBN(ISBN);
newBook->setAvailability(true);
books.push_back(newBook);
}
return *newBook;
}
void Administrator::printBookDetails()
{
books.begin()->setPrevBook(NULL);
for (pos = books.begin(); pos != books.end(); ++pos)
{
cout << pos->getTitle() << "\n"
<< pos->getAuthor() << "\n"
<< pos->getISBN() << "\n"
<< pos->getAvailability() << "\n"
<< "******************************" << endl;
if (pos != books.begin())
{
last->setNextBook(&*pos);
pos->setPrevBook(&*last);
}
last = pos;
}
books.back().setNextBook(NULL);
}
Can someone help me finish off this project please, these are my two functions addBook and printbookDetails . These are in my Admin class.
I would like the books i create on the heap to be stored in list< book*> books as i want to reference them in another class.
I've gotten a bit of help on here so far in regards to pointers and i know its something to do with me not linking the pointers to the correct objects.
My printBookDetails is giving me trouble, the first line books.begin()->setPrevBook(NULL); is saying i need a pointer-to-class type but when i put the -> i still have an error.
Book Guest::searchBook(Book* search)
{
string searchBook;
cout << "What book would you like to search for?" << endl;
cin >> searchBook;
printBookDetails();
}
What id like to do is use the searchBook function above in my Guest class to reference the books in the list at a later time but when i cannot seem to get my pointers right.
Can someone please put me on the right track.
for (pos = books.begin(); pos != books.end(); ++pos)
Here, pos is an iterator, over your list. Iterators are like pointers to list entries.
But each of your list entries is also a pointer to a book, not a book itself.
So, you need code like: (*pos)->getTitle() when trying to access member functions for those elements.

Creating objects on the heap through a class function

Book book;
list<Book>* books;
string title;
string author;
int ISBN;
Book* Administrator::addBook()
{
Book *newBook = new Book();
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
cout << endl;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
cout << endl;
newBook->setTitle(title);
newBook->setAuthor(author);
newBook->setISBN(ISBN);
newBook->setAvailability(true);
books->push_back(*newBook);
}
return newBook;
}
Here im creating my book objects in my Administration class, the problem im having is when i try and access them from another class, its says they are not there.
I did a bit of reading and understand I've to allocate the objects to the heap using dynamic memory management, is there a way i can do this within my code?
Any help would greatly be appreciated.
Here's a simple way:
if (userInput == "yes")
{
Book *newBook = new Book(); // <-- allocates a Book object on the heap
cout << "What is the title of the book you want to enter?" << endl;
[...]
newBook->setTitle(title);
[...]
return *newBook;
}
you have to decide if you want to use the book that is in your class, or create a different book, or a heap copy of your book
if you want a different book you will need to use the new operator at the start
if you want to create a copy of your book on the heap:
return new Book(book)
Book* Administrator::addBook()
{
Book *bookOnHeap = new Book();
....
return bookOnHeap;
}