Почему происходит сбой моей функции при повторном вызове? - PullRequest
0 голосов
/ 16 апреля 2020

Я пишу программу, в которой люди могут брать книги из связанного списка из 5 книг. Они могут позаимствовать либо первую, либо последнюю книгу. Затем название заимствованной книги будет сохранено в файле, а узел будет удален.

#include <cstddef>
#include <iostream>
using namespace std;

struct node
{
    string bookname;
    node* next;
};

void menu();

node* head;
node* second;
node* third;
node* fourth;
node* tail;
node* display;
node* secondlast;
node* deletor;


void initialize()
{
    head= new node;
    second= new node;
    third= new node;
    fourth= new node;
    tail= new node;

    head->bookname = "Book1"; 
    head->next = second;

    second->bookname = "Book2";
    second->next = third;

    third->bookname = "Book3";
    third->next = fourth;

    fourth->bookname = "Book4";
    fourth->next = tail;

    tail->bookname = "Book5";
    tail->next = NULL;
}

void borrow()
{
    string temp;
    display = head;
    while (display!=NULL)
    {
        cout<<display->bookname<<endl;
        display = display->next;
    }
    // User indicates if borrowing the first or last book.
    // For this example, always borrow the last.
    // if (choice=='l'||choice=='L')
    {
        secondlast=head;
        tail=head->next;
        while (tail->next != NULL)
        {
            secondlast->next=tail;
            secondlast=tail;
            tail=tail->next;
        }

        temp=tail->bookname;
        deletor=tail;
        delete deletor;
        secondlast->next==NULL;
    }

    cout<<"Finished borrowing."<<endl;
}

void menu()
{
    borrow();
    borrow();
    borrow();
    borrow();
    borrow();
}

int main()
{
    initialize();
    menu();
}

Если я попытаюсь заимствовать последнюю книгу дважды, она остановится. Я думаю, что что-то не так с моим последним удалением узла, но я не знаю что. Я хочу иметь возможность одолжить все 5 книг, начиная с последней.

Что мне сделать, чтобы это исправить?

1 Ответ

3 голосов
/ 16 апреля 2020

https://godbolt.org/z/rRqeMy

  1. Не использовать связанные списки. Особенно в C ++. Предпочитаю std::vector. Это просто быстрее на процессорах, выпускаемых с 1990-х годов. (Попробуйте найти тест на quick-bench.com, если вы считаете, что нашли случай, когда связанные списки работают быстрее.)
  2. Используйте предоставленные структуры данных. Вот почему я переключил вашу реализацию в стиле C на std::list. Если у вас есть веские причины не использовать стандартную библиотеку, то хотя бы сделайте ее C ++ и поддерживайте инварианты в классе. Особенно не используйте глобальные переменные для поддержания состояния.
  3. Отдельные обязанности: borrow делает слишком много вещей: получает входные данные выбора из std::cin, а также операции со связанными списками, а также обслуживание базы данных. Я решил, что borrow примет choice в качестве параметра и вернет заимствованное название книги.
#include <iostream>
#include <list>

class Library {
public:
  Library() { repository_ = {"Book1", "Book2", "Book3", "Book4", "Book5"}; }
  void print_inventory() const {
    for (auto const &book : repository_) {
      std::cout << book << "\n";
    }
  }

  /** Borrow a book from the library.
  * - choice can be either 'f' (front) or 'l' (last). (Uppercase also allowed).
  * - NOTE: Will fail badly if library is empty. Change the return type to 
  * std::optional<std::string> and handle an empty library that way.
  * Instead of `choice` being a char, consider making it an enum.
  */
  std::string borrow(char choice) {
    std::string temp = "";
    if (choice == 'f' || choice == 'F') {
      temp = repository_.front();
      repository_.pop_front();
    } else if (choice == 'l' || choice == 'L') {
      temp = repository_.back();
      repository_.pop_back();
    } else {
      throw 42; // TODO: Use proper input validation!
    }
    return temp;
  }

private:
  std::list<std::string> repository_;
};

void menu(Library &lib) {
  for (char choice : {'f', 'l', 'f', 'f'}) {
    std::cout << "---------\n";
    lib.print_inventory();
    std::string borrowed = lib.borrow(choice);
    std::cout << "--\nBorrowed: " << borrowed << "\n";
  }
}

int main() {
  Library lib;
  menu(lib);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...