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

Я делаю библиотечную программу, где люди могут просматривать и жертвовать книги. Изначально в связном списке хранятся 3 книги. Когда они делают пожертвования, их пожертвования добавляются в связанный список, поэтому при повторном просмотре книги увеличиваются.

(я объявил void menu() вверху)

( Расположение: menu(), donate(), browse(), initialize() снизу вверх соответственно)

Вот меню:

void menu()
{
    int choice;
    char repeat;

    do{
        system("cls");
        cout<<"1. Browse books"<<endl;
        cout<<"2. Donate books"<<endl;
        cin>>choice;

        if (choice==1)
        {
            browse();
        } else if (choice==2)
        {
            donate();
        } else
        {
            cout<<"Input not valid. Try again."<<endl;
            menu();
        }
        cout<<"Do you want to go back to menu?(Y/N)"<<endl;
        cin>>repeat;
    } while (repeat=='y'||repeat=='Y');
}

Вот пожертвование:

void donate()
{
    int amount;
    cout<<"How many books are you donating? ";
    cin>>amount;
    string donation[amount];
    cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n'); 

    cout<<"Enter the titles:"<<endl;
    for (int i=0; i<amount; i+=1)
    {
        getline(cin, donation[i]);
    }

    for(int k=0; k<amount; k+=1)
    {
        newbook = new node;
        newbook->bookname = donation[k];
        newbook->next = NULL;
        tail->next = newbook;
        tail = newbook;
    }
}

Вот просмотр: (I сделал это l oop 10 раз coz idk, сколько книг они собираются пожертвовать, и я не могу передать amount из donate() сюда bcs, это означает, что функция должна будет принимать параметр и при вызове из меню, у него пока нет amount.) (Я знаю, что это замедляет работу программы, но я не знаю, как это сделать. Если у кого-то есть идеи, пожалуйста, скажите мне.)

void browse()
{   
    display = head;
    cout<<"We have these books in our collection:"<<endl;
    for (int i=1; i<=10; i+=1)
    {
        cout<<display->bookname<<endl;
        display = display->next;
    }
}

Вот инициализация: (это 3 книги, изначально присутствующие в библиотеке)

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

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

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

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

Если они просматривают после пожертвования, это работает нормально. Но если они просматривают без пожертвования, он показывает первые 3 книги, а затем завершает себя, не возвращаясь к меню. Почему он это делает? Разве это не просто l oop 10 раз (медленно, я знаю), а затем l oop вернуться в меню?

1 Ответ

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

Если вы просматриваете, когда в коллекции нет 10 книг, вы, вероятно, попадете в конец связанного списка. display->next будет иметь значение NULL, поэтому значение NULL будет присвоено display, а затем display->bookname завершится ошибкой с нулевым разыменованием.

Или, как я полагаю, не вижу реализации связанного списка.

Вам необходимо прекратить просмотр l oop не после произвольных 10 книг, а по достижении конца связанного списка. Предположительно, это когда дисплей пуст.

   while (display != null) {
       ...output...
       display = display->next;  
   }

Кроме того, вы обречены на переполнение стека. Рассмотрим пользователя, который жертвует книгу, просматривает, жертвует книгу, просматривает ...

Вы называете цепочку, затем menu => donate => menu => browse => menu => donate => menu => просматривать ... и рано или поздно у вас закончится стек.

То же самое верно и в других местах. Например, предположим, что пользователь находится в menu () и просто продолжает набирать «3» снова и снова.

Вам не нужна рекурсивная структура. меню, вероятно, должно просто иметь большую l oop вокруг большей части его кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...