简体   繁体   中英

Need to overload operator with Book* head variable but doesnt work

I'm currently working on a project that has a couple of parts to it. I have book.h and Warehouse.h files. The book stores information about a book while the warehouse holds the books and number of books. I am using a linked list and pointers for this project.

These are my book stream operators:

friend istream& operator >> (istream& is, Book&book);
friend ostream& operator << (ostream& os, const Book&book);

These are my warehouse stream operators:

friend istream& operator >> (istream& is, Warehouse& warehouse);
friend ostream& operator << (ostream& os, const Warehouse& warehouse)

My warehouse private variables:

private:
    Book* head;
    int bookCount;

In my previous project, we used arrays and I would just put is >> warehouse.book[numofbooks] for the istream overload in the warehouse.cpp .

For this project, I tried doing is >> warehouse.head but I'm not sure that is correct.

My main file looks like:

#include "Book.h"
#include "Warehouse.h"
#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char* argv[])
{
  bool found;
  Warehouse warehouse;
  Book book;
  string filename=argv[1];  //assigns the filename from console to a string

  ifstream is;
  is.open(filename);

  if(is.fail())       //check if the file was opened
  {
    cout<< "Unable to read file: " << filename<< endl;    //if not opened, tell user
    return -1;
  }

  is >> warehouse;

  is.close();
}

The code you have shown is fine. The code you have not shown is where the problem is.

In a linked list, its nodes need to be allocated dynamically. I would suggest something like the following for your stream operator implementations:

book.h

#include <iostream>

class Book
{
public:
    // fields as needed ...

    friend std::istream& operator >> (std::istream& is, Book& book);
    friend std::ostream& operator << (std::ostream& os, const Book& book);
};

book.cpp

#include "book.h"

std::istream& operator >> (std::istream& is, Book& book)
{
    // read book fields as needed...
    return is;
}

std::ostream& operator << (std::ostream& os, const Book& book)
{
    // write book fields as needed...
    return os;
}

warehouse.h

#include <iostream>
#include "book.h"

class Warehouse
{
private:
    struct ListItem
    {
        ListItem* next = nullptr;
        Book book;

        ListItem(const Book &b) : book(b) {}
    };

    ListItem *head = nullptr;
    int bookCount = 0;

public:
    // fields as needed...

    void clear();
    // other methods as needed...

    friend std::istream& operator >> (std::istream& is, Warehouse& warehouse);
    friend std::ostream& operator << (std::ostream& os, const Warehouse& warehouse)
};

warehouse.cpp

#include "warehouse.h"

void Warehouse::clear()
{
    ListItem *item = head;
    head = nullptr;
    bookCount = 0;

    while (item)
    {
        ListItem *next = item->next;
        delete item;
        item = next;
    }
}

std::istream& operator >> (std::istream& is, Warehouse& warehouse)
{
    warehouse.clear();

    int count;
    if (is >> count)
    {
        Warehouse::ListItem **item = &(warehouse.head);

        Book book;
        for (int i = 0; i < count; ++i)
        {
            if (!(is >> book)) return;
            *item = new Warehouse::ListItem(book);
            warehouse.bookCount++;
            item = &(item->next);
        }
    }

    return is;
}

std::ostream& operator << (std::ostream& os, const Warehouse& warehouse)
{
    os << warehouse.bookCount;

    Warehouse::ListItem *item = warehouse.head;
    for(int i = 0; i < warehouse.bookCount; ++i)
    {
        os << item->book;
        item = item->next;
    }
}

That being said, Warehouse can be simplified a bit by using std::list instead of a manual linked-list implementation:

warehouse.h

#include <iostream>
#include <list>
#include "book.h"

class Warehouse
{
private:
    std::list<Book> books;

public:
    // fields as needed...

    void clear();
    // other methods as needed...

    friend std::istream& operator >> (std::istream& is, Warehouse& warehouse);
    friend std::ostream& operator << (std::ostream& os, const Warehouse& warehouse)
};

warehouse.cpp

void Warehouse::clear()
{
    books.clear();
}

std::istream& operator >> (std::istream& is, Warehouse& warehouse)
{
    warehouse.clear();

    std::size_t count;
    if (is >> count)
    {
        Book book;
        for (std::size_t i = 0; i < count; ++i)
        {
            if (!(is >> book)) return;
            warehouse.books.push_back(book);
        }
    }

    return is;
}

std::ostream& operator << (std::ostream& os, const Warehouse& warehouse)
{
    os << warehouse.books.size();
    for(const Book &book : warehouse.books)
        os << book;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM