2
\$\begingroup\$

Just a disclaimer this code was one of the last homework submission for my CSCI intro to C++ class and from my guess very rough around the edges. If any of you are bored during the quarantine and want to look at around 450 lines of a novices code, please, by all means, be brutally honest I can take it and I would actually be very appreciative of it!

Given code:

class Name
{
    private:
    string first_;
    string last_;
}


class Date
{
    private:
    int year_;
    int month_;
    int day_;
}


class Book
{
    private:
    Name   author_;
    string title_;
    int    year_;
}


class LibraryBook
{
    private:
    int  id_;
    Book book_;
    Name borrower_;
    Date borrowed_;
    Date due_;
    bool isLoaned_;
}

The Following were the instructions for me to follow

  • constructors to create LibraryBook object

  • Accessors and mutators for each data member

  • neatly print all information about this library book

    • print borrower and date information only if on loan
  • loan the book:

    • parameters include borrowing date, due date, and borrower
    • Ensure that the due date is after the borrowing date (else do nothing other than print an error message)
    • if already out on loan, do nothing other than printing a message to that effect (can include due date).
  • Return the book:

    • Expunge the borrower name information and set isLoaned to false (if not loaned do nothing and print a message to that effect)
  • Renew the book:

    • update the borrowing data and due date

Test drivers were given some details too but I don't think it is too important to put the specifics in this form (Correct me if you want/need it and I will happily add it). But to sum up the requirements for the drivers I needed to declare a vector from the class LibraryBook and from this add some starting books.

Pseudocode:

include iostream
include vectors
include ctime // for getting current time


class Name
{
    public:
    get function
    set function

    private:
    string first_;
    string last_;
}


class Date
{
    public:
    set function
    get function

    private:
    int year_;
    int month_;
    int day_;
}


class Book
{
    public:
        get function
        set function

    private:
    Name   author_;
    string title_;
    int    year_;
}


class LibraryBook
{
    public:
        set function
        get function
        

    private:
    int  id_;
    Book book_;
    Name borrower_;
    Date borrowed_;
    Date due_;
    bool isLoaned_;
}

void readbooks
void menu()
void bookReturn()
void BookCheckout()

main()

    vector<libraryBook> library

    do
        menu()
        if else if block to check what they want to do

    while (x)

    return
end main()

default constructor
main constructor

get functions for Librarybooks

void BookCheckout(vector<LibraryBook> &library)

    get the author name
    get the title
    get the borrowers name
    get the current day
    get the book id

    push back vector to add book

end void book checkout

book return function

    get the users name
    find all books under their name
    print the option for what book they are returning
    erase the book that they want to return
end book return gunction

readBooks function
    read all of the current books that are on loan
end readBooks function

Main Program:

// 5/3/2020, Homework 7
//This program will keep track of books and tell you
//weather they when they were borrowed, overdue, and
//who borrowed the book.

#include <iostream>
#include <vector>
#include <ctime> // for getting current time
#include <iomanip>

using namespace std;

class Name
{
    public:
        void setName(string first, string last)
        {
            first_ = first;
            last_ = last;
        }
        string printName()
        {
            return first_ + " " + last_;
        }

    private:
    string first_;
    string last_;
};


class Date
{
    public:
        void setDate(int day, int month, int year)
        {
            day_ = day;
            month_ = month;
            year_ = year;
        }
        void setDueDate(int day, int month, int year)
        {
            day_ = day;
            if (month == 12)
            {
                month_ = 1;
                year_ = year + 1;
            }
            else
            {
                month_ = month + 1;
                year_ = year;
            }
        }

        string printDate()
        {
            return to_string(day_) + " / " + to_string(month_) + " / " + to_string(year_);
        }
        int day()
        {
            return day_;
        }
        int month()
        {
            return month_;
        }
        int year()
        {
            return year_;
        }
    private:
    int year_;
    int month_;
    int day_;
};

class Book
{
    public:
        void setBook(string AuthorFirstName, string AuthorLastName, string Title, int Year)
        {
            author_.setName(AuthorFirstName, AuthorLastName);
            title_ = Title;
            year_ = Year;
        }
        string PrintBook()
        {
            return "AUTHOR:" + author_.printName() + "\nTITLE: " + title_ + "\nYEAR: " + to_string(year_);
        }
    private:
        Name   author_;
        string title_;
        int    year_;
};

class LibraryBook
{
    public:
        
        LibraryBook(string AuthorFirstName, string AuthorLastName, string Title, int Year, 
                            string BorrowerFirstName, string BorrowerLastName, 
                            int BarrowdDay, int BarrowedMonth, int BarrowedYear, 
                            int CurrentDay, int currentMonth, int currentYear,
                            int BookID)
        {

            due_.setDueDate(BarrowdDay, BarrowedMonth, BarrowedYear);
            borrowed_.setDate(BarrowdDay, BarrowedMonth, BarrowedYear);
            borrower_.setName(BorrowerFirstName, BorrowerLastName);
            book_.setBook(AuthorFirstName, AuthorLastName, Title, Year);
            today_.setDate(CurrentDay, currentMonth, currentYear);
            setId(BookID);
            setIsLoaned();
        }
        string getBook() // get function for book
        {
            return book_.PrintBook();
        }


        string getBorrower() // get function for borrower
        {
            return borrower_.printName();
        }


        int getID() // get function for ID
        {
            return id_;
        }


        string getBorrowedDate() // get function for borrowed date
        {
            return "Checked out on: " + borrowed_.printDate();
        }


        string getDueDate() // get function for due date
        {
            
            return "Due on: " + due_.printDate();
        }


        bool isOverDue() // get function for over due
        {
            if (today_.year() >= due_.year()){
                if (today_.month() >= due_.month())
                {
                    if (today_.day() > due_.day())
                    {
                        return true;
                    }
                    else
                        return false;
                }
                else
                    return false;
            }
            else
                return false; 
        }

        void setId(int id)
        {
            id_ = id;
        }
        void setIsLoaned(bool op = true)
        {
            isLoaned_ = op;
        }
        bool getIsLoaned()
        {
            return isLoaned_;
        }

        // string getBook();
        // string getBorrower();
        // int    getID();
        // string getBorrowedDate();
        // string getDueDate();
        // bool   isOverDue();
        
        // LibraryBook(
        // string AuthorFirstName, string AuthorLastName, string Title, int Year, 
        // string BorrowerFirstName, string BorrowerLastName,
        // int BarrowdDay, int BarrowedMonth, int BarrowdYear,
        // int CurrentDay, int currentMonth, int currentYear,
        // int BookId);
        LibraryBook(); // default constructor
        //~LibraryBook(); // deconstructor;

    private:
        int  id_;
        Book book_;
        Name borrower_;
        Date borrowed_;
        Date due_;
        Date today_;
        bool isLoaned_;
};

void readBooks(vector<LibraryBook> Library); // prototype for reading the books
void menu(); // prototype for the menu
void BookReturn(vector<LibraryBook> &Library); // prototype for returning books
void BookCheckOut(vector<LibraryBook> &Library); // prototype for checking books out 
void DefaultBook(vector<LibraryBook> &Library);

// -------------------------------------------------------------------------- //
// --------------- END OF PROTOTYPES AND CLASS DEFFINITION ------------------ //
// -------------------------------------------------------------------------- //

int main()
{

    vector<LibraryBook> Library;
    DefaultBook(Library);
    int op;
    bool logout = false;
    
    do
    {
        menu();
        cin >> op;
        if (op == 1)
        {
            BookCheckOut(Library); // calls the checkout option
        }
        else if (op == 2)
        {
            BookReturn(Library); // calls the BookReturn Function
        }
        else if (op == 3)
        {
            readBooks(Library); // calls the readbook function
        }
        else if (op == 4)
            logout = true; // logs out
        else
            cout << "The input " << op << " was not recognized" << endl << endl; // gives you an error message for a bad choice
    } while (logout != true);
    

    return 0;
}

// -------------------------------------------------------------------------- //
// -------------------------------- END OF MAIN ----------------------------- //
// -------------------------------------------------------------------------- //


void menu() // function to print the  main option menu
{
    cout << "Check out a book: 1" << endl;
    cout << "Return book: 2" << endl;
    cout << "Read books: 3" << endl;
    cout << "logout: 4" << endl;
    cout << "[*] ";
}

void BookCheckOut(vector<LibraryBook> &Library) // function to check out a book
{
    string AuthorFirstName, AuthorLastName, Title, BorrowerFirstName, BorrowerLastName;
    int Year, BarrowdDay, BarrowedMonth, BarrowdYear, BookId, CurrentDay, currentMonth, currentYear;
    cout << endl;
    
    cout << "Please enter the authors first name: ";
    cin >> AuthorFirstName;
    cout << endl;
    
    cout << "Please enter the authors last name: ";
    cin >> AuthorLastName;
    cout << endl;
    
    cout << "Please enter the title of the book: ";
    getline(cin, Title);
    cout << endl;

    cout << "Please enter the year the book was published: ";
    cin >> Year;

    cout << "Please enter your first and last name: ";
    cin >> BorrowerFirstName >> BorrowerLastName;
    cout << endl;

    cout << "Please enter todays date (Day Month Year) seperated with spaces: ";
    cin >> BarrowdDay >> BarrowedMonth >> BarrowdYear;
    cout << endl; 

    cout << "Please enter the book ID (If it starts with a zero don't enter the zero): ";
    cin >> BookId;
    cout << endl;

    time_t t = time(NULL);
    tm* timePtr = localtime(&t);

    CurrentDay = timePtr->tm_mday;
    currentMonth = timePtr->tm_mon;
    currentYear = timePtr->tm_year + 1900;

    Library.push_back(LibraryBook(
        AuthorFirstName, AuthorLastName, Title, Year, 
        BorrowerFirstName, BorrowerLastName,
        BarrowdDay, BarrowedMonth, BarrowdYear,
        CurrentDay, currentMonth, currentYear,
        BookId));
    
    return;
}

void BookReturn(vector<LibraryBook> &Library)
{
    string firstName, lastName;
    vector<int> pos;
    int op;

    cout << "Please enter your first name and last name seperated with a space\n[*]";
    cin >> firstName >> lastName;
    for (int i = 0; i < Library.size(); i++)
    {
        if (firstName + " " + lastName == Library[i].getBorrower())
        {
            pos.push_back(i);
        }
    }
    cout << "Please enter the option number you are returning... \nIf there are more than one options please do this multiple times" << endl;
    for (int i = 0; i < pos.size(); i++)
    {
        cout << "Op: " << i << endl << Library[pos[i]].getBook() << endl;
    }

    cout << "\n[*]";
    cin >> op;
    cout << pos[op];
    Library[pos[op]].setIsLoaned(false);

    Library.erase(Library.begin() + op);
    return;
}
void readBooks(vector<LibraryBook> Library)
{
    cout << endl << endl;
    for (int i = 0; i < Library.size(); i++)
    {
        cout << Library[i].getBook() << endl;
        cout << "ID: " <<Library[i].getID() << endl;
        cout << "Checked out by: " << Library[i].getBorrower() << endl;
        cout << Library[i].getBorrowedDate() << endl;
        cout << Library[i].getDueDate() << endl;
        if (Library[i].isOverDue())
            cout << setw(4) << ' ' << "This book is over due" << endl;
        if (Library[i].getIsLoaned())
            cout << setw(4) << ' ' << "This book is on loan" << endl;
        else if (!Library[i].getIsLoaned())
            cout << setw(4) << ' ' << "This book is not on loan" << endl;
        cout << endl << endl << endl;
    }
    return;
}

void DefaultBook(vector<LibraryBook> &Library)
{
    string AuthorFirstName, AuthorLastName, Title, BorrowerFirstName, BorrowerLastName;
    int Year, BarrowdDay, BarrowedMonth, BarrowdYear, BookId, CurrentDay, currentMonth, currentYear;
    { // book one that will be automatically added to the books when you check out
        AuthorFirstName = "Robert";
        AuthorLastName  = "Ludlum";
        Title           = "The Bourne Identity";
        Year            = 1980;

        BorrowerFirstName = "Connor";
        BorrowerLastName  = "Jenson";

        BarrowdDay = 3;
        BarrowedMonth = 5;
        BarrowdYear = 2020;
        
        BookId = 399900705;

        time_t t = time(NULL);
        tm* timePtr = localtime(&t);

        CurrentDay = timePtr->tm_mday;
        currentMonth = timePtr->tm_mon;
        currentYear = timePtr->tm_year + 1900;

        Library.push_back(LibraryBook(
            AuthorFirstName, AuthorLastName, Title, Year, 
            BorrowerFirstName, BorrowerLastName,
            BarrowdDay, BarrowedMonth, BarrowdYear,
            CurrentDay, currentMonth, currentYear,
            BookId));
    }
    { // book two that will be automatically added to the books when you check out
        AuthorFirstName = "Dan";
        AuthorLastName  = "Brown";
        Title           = "The Da Vinci Code";
        Year            = 2003;

        BorrowerFirstName = "John";
        BorrowerLastName  = "Doe";

        time_t t = time(NULL);
        tm* timePtr = localtime(&t);    

        BarrowdDay = timePtr->tm_mday;
        BarrowedMonth = timePtr->tm_mon;
        BarrowdYear = timePtr->tm_year + 1900;
        
        BookId = 399900705;

        CurrentDay = timePtr->tm_mday;
        currentMonth = timePtr->tm_mon;
        currentYear = timePtr->tm_year + 1900;

        Library.push_back(LibraryBook(
            AuthorFirstName, AuthorLastName, Title, Year, 
            BorrowerFirstName, BorrowerLastName,
            BarrowdDay, BarrowedMonth, BarrowdYear,
            CurrentDay, currentMonth, currentYear,
            BookId));
    }
    { // book two that will be automatically added to the books when you check out
        AuthorFirstName = "Stephenie";
        AuthorLastName  = "Meyer";
        Title           = "Forks"; // this is the orrigional title (first book in twilight)
        Year            = 2005;

        BorrowerFirstName = "James";
        BorrowerLastName  = "Christian";

        time_t t = time(NULL);
        tm* timePtr = localtime(&t);    

        BarrowdDay = 1;
        BarrowedMonth = 3;
        BarrowdYear = 2020;
        
        BookId = 399900705;

        CurrentDay = timePtr->tm_mday;
        currentMonth = timePtr->tm_mon;
        currentYear = timePtr->tm_year + 1900;

        Library.push_back(LibraryBook(
            AuthorFirstName, AuthorLastName, Title, Year, 
            BorrowerFirstName, BorrowerLastName,
            BarrowdDay, BarrowedMonth, BarrowdYear,
            CurrentDay, currentMonth, currentYear,
            BookId));
    }
    return;
}
```
\$\endgroup\$
4
  • \$\begingroup\$ @πάνταῥεῖ it seems like the part on the bottom is the working code. Perhaps pseudocode and real code (submission) should be separated into multiple sections to make it clear which functions were required to implement. \$\endgroup\$ Jun 10 '20 at 16:18
  • 1
    \$\begingroup\$ Since this is a homework solution, I suggest removing the name of the course so that people googling "<name of course> solution" won't discover this post. (Personally I'd also consider removing your IRL name so that future employers googling "<your name>" won't find this, but that's more of a personal decision.) \$\endgroup\$ Jun 10 '20 at 16:20
  • \$\begingroup\$ @Quuxplusone Thank you for the insight for that and I think that that is a good idea and I'll keep these in mind for the future! \$\endgroup\$
    – Connor
    Jun 10 '20 at 16:50
  • \$\begingroup\$ @πάνταῥεῖ I removed the pseudocode and I will also added a bit more detail for what I needed to do to create this! \$\endgroup\$
    – Connor
    Jun 10 '20 at 16:51
3
\$\begingroup\$

Write real constructors for all your classes

You wrote a proper constructor for LibraryBook, but for the other classes you only wrote setSomething() functions. Try to convert those to proper constructors. The advantage of that is that it forces you to properly initialize instances of those classes. If I just write:

Date date;

This allows me to forget to call setDate(), and then if I access it later on it will have an undefined value that might cause bad things to happen.

Only write setter functions for variables that are allowed to be changed.

For example, you probably never want a library book's ID to be changed, so don't add setId(). If possible, I would make the member variable id_ itself const as well.

Ensure there are getters and setters for all relevant member variables

Your class Book doesn't have getters to get the author, title or year from a book. While you might not use it right now, it would be helpful to have getters for all of those if for example you want to search the library for all books from a certain author.

Don't add unnecessary member variables

Why did you add today_ to LibraryBook? You can always query the current day by using one of the time functions from the standard library, like std::chrono::system_clock::now(). You don't need to store this in the book itself.

Write proper std::ostream formatters and/or to_string() functions

Your classes have printSomething() functions that don't print anything, but rather create strings. I would rename those functions to_string(), so it matches what the standard library does.

Furthermore, you can also functions that make it easy to print in the C++ way, by writing so-called std::ostream formatters. It looks like this:

class Name {
public:
    ...
    friend std::ostream &operator<<(std::ostream &os, const Name &self) {
        return os << first_ << " " << last__;
    }
};

You can then print a Name like so:

Name name("John", "Smith");
std::cout << "The name is: " << name << "\n";

Use "\n" instead of std::endl

std::endl is equivalent to "\n" plus a forced flush of the output stream, which might hurt performance. See this StackOverflow question for more the details.

Consider using a std::chrono class to store dates

If you are not allowed to change the way dates are stored, it's fine. But the standard library provides several ways to store times. Since C++11, there's std::chrono::time_point which represents arbitrary points in time, and in C++20 there will be std::chrono::year_month_day to represent calendar dates. The advantage of these classes is that they come with member function which allow easy manipulation of them, like checking if a given day comes before or after another day, and so on.

Check your spelling

You wrote BarrowdDay, which should be BorrowedDay. There are tools that can help you find and fix spelling errors in source code, like codespell.

Don't initialize things in a constructor that don't need initialization

Typically, when adding a book to a library, it will not be in a checked out state. Only when it is part of the library can it be checked out. It therefore makes sense to have the constructor of LibraryBook only take parameters necessary to inialize the book and the id_ variables, and set isLoaned_ to false.

Avoid using namespace std

Writing using namespace std is considered bad practice, because it hides namespace conflicts. Just make it a habit to add std:: where necessary. You have to use it less often than you think, especially if you make use of auto.

Pass strings using const references

Passing strings by value can cause unnecessary copying of the strings. Pass them by const reference instead. See the example below.

Use member initializer lists where possible

When writing a constructor, it's preferable to use member initializer lists instead of setting each member in the body of the constructor function. For example:

class Name {
    public:
    Name(const std::string &first, const std::string &last): first_(first), last_(last) {}
    ...
};

Consider passing a Book to the constructor of LibraryBook

Instead of having the constructor take lots of parameters, that are then passed on to the construction of the book_ member variable, take a const reference to a Book instead, like so:

class LibraryBook {
    public:
    LibraryBook(const Book &book, int BookID): book_(book), id_(BookID), isLoaned_(false) {}
    ...
};

The copy constructor of Book, which will have been created implicitly in your case, will take care of copying the details from the parameter book into the member variable book_. You can use it like so:

Book book("Lewis", "Carrol", "Alice's Adventures in Wonderland", ...);
LibraryBook libraryBook(book, 9780199558292);

You can also avoid creating a named Book variable, and create a LibraryBook like so:

LibraryBook libraryBook({"Lewis", "Carrol", ...}, 9780199558292);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.