Требуется перегрузить оператор с помощью переменной head Book *, но она не работает - PullRequest
0 голосов
/ 24 апреля 2019

В настоящее время я работаю над проектом, который состоит из нескольких частей.У меня есть файлы book.h и Warehouse.h.book хранит информацию о книге, в то время как warehouse содержит книги и количество книг.Я использую связанный список и указатели для этого проекта.

Это мои book операторы потока:

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

Это мои warehouse операторы потока:

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

Мои warehouse приватные переменные:

private:
    Book* head;
    int bookCount;

В моем предыдущем проекте мы использовали массивы, и я бы просто поместил is >> warehouse.book[numofbooks] для перегрузки istream в warehouse.cpp.

Для этого проекта я попытался сделать is >> warehouse.head, но я не уверен, что это правильно.

Мой основной файл выглядит так:

#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();
}

1 Ответ

1 голос
/ 24 апреля 2019

Код, который вы показали, в порядке. Код, который вы не показали, в чем проблема.

В связанном списке его узлы должны выделяться динамически. Я бы предложил что-то вроде следующего для ваших реализаций оператора потока:

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;
    }
}

При этом Warehouse можно немного упростить, используя std::list вместо ручной реализации связанного списка:

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;
}
...