我正在制作一个图书馆程序,人们可以在其中浏览和捐赠书籍。它最初有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;
}
}
浏览如下:(我让它循环了10次,因为我知道他们要捐赠多少本书,我无法将amount
从donate()
传递到这里,因为这意味着函数必须接受一个参数,当从菜单中调用时,它还没有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本书,然后自行终止,而不会循环回菜单。它为什么要这样做?它不应该循环10次(我知道很慢(然后循环回菜单吗?
如果您在收藏中没有10本书的时候浏览,那么您可能会从链接列表的末尾掉下来。display->next
将为null,因此null将被分配给display
,然后display->bookname
将因null解引用而失败。
或者我认为,没有看到您的链表实现。
您需要终止浏览循环,而不是在任意10本书之后,而是在您到达链接列表的末尾时。大概这是当显示为空时。
while (display != null) {
...output...
display = display->next;
}
此外,您注定要发生堆栈溢出。考虑一个捐书、浏览、捐赠书籍、浏览…的用户。。。
然后调用链是menu=>捐赠=>menu=>浏览=>menu=>捐赠>>菜单=>浏览…。迟早你会用完的。
其他地方也是如此。例如,假设用户在menu((中,只是一次又一次地键入"3"。
您不需要递归结构。菜单的大部分代码应该有一个大循环。