说明一下这是最近博主做的一篇C++课程设计报告形式的,代码的话我是测试过的应该没有bug,如果有问题的话可以在评论@我。
第一章 问题描述
要求以图书馆管理业务为背景,设计并实现一个“图书馆管理信息系统”软件,使用该系统可以方便查询图书的信息、借阅者的个人等信息,实现借书与还书等功能。
要求:(1)实现图书信息的录入、修改、删除和查看(2)实现借阅者分类及借阅者个人信息的录入、修改和删除(3)实现借书和还书功能(4)可图书信息查询和读者信息查询(5)对用户信息管理及权限分配
第二章 需求分析
根据题目的任务要求,对将要实现的系统做功能分析及数据分析如下:
(1)功能分析(操作需求)
根据问题描述与设计要求,本系统应具备如下功能:
图书系统的创建:系统启动时,从图书馆功能文件加载图书信息,如果图书馆功能文件不存在,应初始化图书馆功能文件;
添加图书信息:增加新的图书信息到图书信息系统中;
修改图书信息:修改现有的图书的基本信息;
删除图书信息:从图书信息系统中删除一个已经存在的图书信息;
查找图书信息:查找图书是否存在。
显示图书信息:显示图书信息。
全删图书信息:把图书信息全部清空。
读者信息系统的创建:系统启动时,从图书馆功能文件加载读者信息;
添加读者信息:增加新的读者信息到读者信息系统中;
修改读者信息:修改现有的读者的基本信息;
删除读者信息:从读者信息系统中删除一个已经存在的读者信息;
查找读者信息:查找读者是否存在。
显示读者信息:显示读者信息。
全删读者信息:把读者信息全部清空。
借书管理系统的创建:系统启动时,从图书馆功能文件加载借书管理系统;
借书功能:输入借书图书信息,查找该图书并取走该书,并进行记录借阅者信息。
还书功能:输入借书图书信息,查找该图书并插入。
退出系统管理的创建:关闭正运行的系统回到到图书管理系统 。
(2)数据分析
根据问题描述确定图书信息包括:书名,编号;借阅者的信息有:姓名,编号;借书信息包括:读者信息,书籍信息。
第三章 编程实现
#include
#include
#include
#include
#include
using namespace std;
const int Reader=100; //给读者分配储存空间
const int Maxb=100; //给图书分配储存空间
const int Bor=5;
class Student
{
private:
int tag;
int number;
char name[10]; //读者名称
int borbook[Bor];
public:
Student() { }
char *getname()
{
return name;
}
int gettag()
{
return tag;
}
int getnumber()
{
return number;
}
void setname(char *na)
{
strcpy(name,na);
}
void delbook()
{
tag=1;
}
void addStudent(int n,char *na)
{
tag=0;
number=n;
strcpy(name,na);
for(int i=0; i<Bor; i++)
borbook[i]=0;
}
void borrowbook(int bookid) //借书操作
{
for(int i=0; i<Bor; i++)
{
if (borbook[i]==0)
{
borbook[i]=bookid;
return;
}
}
}
int retbook(int bookid) //还书操作
{
for(int i=0; i<Bor; i++)
{
if(borbook[i]==bookid)
{
borbook[i]=0;
return 1;
}
}
return 0;
}
void output() //读出读者信息
{
cout << setw(5) << number <<setw(10) << name<<"借书编号:[";
for(int i=0; i<Bor; i++)
if(borbook[i]!=0)
cout << borbook[i] << "|";
cout << "]"<<endl;
}
};
class RData
{
private:
int top; //读者记录指针
Student read[Reader];
public:
RData() //构造函数,将Student.txt读到read[]中
{
Student s;
top=-1;
fstream file("Student.txt",ios::in); //打开一个输入文件
while (1)
{
file.read((char *)&s,sizeof(s));
if (!file)break;
top++;
read[top]=s;
}
file.close();
}
void clear()
{
top=-1;
}
int addStudent(int n,char *na) //查找是否存在
{
Student *p=equal(n);
if (p==NULL)
{
top++;
read[top].addStudent(n,na);
return 1;
}
return 0;
}
Student *equal(int Studentid)//按编号查找
{
for (int i=0; i<=top; i++)
if (read[i].getnumber()==Studentid &&
read[i].gettag()==0)
{
return &read[i];
}
return NULL;
}
void output()
{
for (int i=0; i<=top; i++)
read[i].output();
}
void Studentdata(); //读者库维护
~RData() //析构函数,将read[]写到Student.txt文件中
{
fstream file("Student.txt",ios::out);
for (int i=0; i<=top; i++)
if (read[i].gettag()==0)
file.write((char *)&read[i],sizeof(read[i]));
file.close();
}
};
void RData::Studentdata()
{
char choice;
char rname[20];
int Studentid;
Student *r;
while (choice!='0')
{
cout<<" ┏━━━━━━━━━━━━━┓\n";
cout<<" ┃ 读 者 维 护 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃1.新 增 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃2.更 改 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃3.删 除 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃4.查 找 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃5.显 示 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃6.全 删 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃0.退出 ┃\n";
cout<<" ┗━━━━━━━━━━━━━┛\n";
cin >> choice;
switch (choice)
{
case '1':
cout << "输入读者编号:";
cin >> Studentid;
cout << "输入读者姓名:";
cin >> rname;
addStudent (Studentid,rname);
break;
case '2':
cout << "输入读者编号:";
cin >> Studentid;
r=equal(Studentid);
if (r==NULL)
{
cout << " 该读者不存在 "<<endl;
break;
}
cout << "输入新的姓名:";
cin >> rname;
r->setname(rname);
break;
case '3':
cout << " 输入读者编号:";
cin >> Studentid;
r=equal(Studentid);
if (r==NULL)
{
cout <<" 该读者不存在" << endl;
break;
}
r->delbook();
break;
case '4':
cout << "读入读者编号:";
cin >> Studentid;
r=equal(Studentid);
if (r==NULL)
{
cout <<"该读者不存在"<< endl;
break;
}
r->output();
break;
case '5':
output();
break;
case '6':
clear();
break;
default:
cout<<"退出:\n";
system("cls");
break;
}
}
}
class Book //图书信息
{
private:
int tag;
int number;
char name[20]; //书名分配空间
int onshelf;
public:
Book() {}
char *getname()
{
return name;
}
int getnumber()
{
return number;
}
int gettag()
{
return tag;
}
void setname(char na[])
{
strcpy(name,na);
}
void delbook()
{
tag=1;
}
void addbook(int n,char *na)
{
tag=0;
number=n;
strcpy(name,na);
onshelf=1;
}
int borrowbook() //借书操作
{
if(onshelf==1)
{
onshelf=0;
return 1;
}
return 0;
}
void retbook() //还书操作
{
onshelf=1;
}
void output() //输出图书
{
cout << setw(6) << number << setw(18) << name << setw(10)
<<(onshelf==1? "在架":"已借") <<endl;
}
};
class BDatabase
{
private:
int top;
Book book[Maxb]; //图书记录
public:
BDatabase()//构造函数,将book.txt读到book[]中
{
Book b;
top=-1;
fstream file("book.txt",ios::in);
while (1)
{
file.read((char *)&b,sizeof(b));
if (!file) break;
top++;
book[top]=b;
}
file.close();
}
void clear()
{
top=-1;
}
int addbook(int n,char *na)
{
Book *p=equal(n);
if (NULL==p)
{
top++;
book[top].addbook(n,na);
return 1;
}
return 0;
}
Book *equal(int bookid)
{
for (int i=0; i<=top; i++)
if (book[i].getnumber()==bookid &&book[i].gettag()==0)
{
return &book[i];
}
return NULL;
}
void bookdata();
void output()
{
for (int i=0; i<=top; i++)
if (book[i].gettag()==0)
book[i].output();
}
~BDatabase()//析构函数,将book[]写到book.txt文件中
{
fstream file("book.txt",ios::out);
for (int i=0; i<=top; i++)
if (book[i].gettag()==0)
file.write((char *)&book[i],sizeof(book[i]));
file.close();
}
};
void BDatabase::bookdata()
{
char choice;
char bname[40];
int bookid;
Book *b;
while (choice!='0')
{
cout<<" ┏━━━━━━━━━━━━━┓\n";
cout<<" ┃ 图书 维 护 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃1.新 增 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃2.更 改 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃3.删 除 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃4.查 找 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃5.显 示 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃6.全 删 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃0.退出 ┃\n";
cout<<" ┗━━━━━━━━━━━━━┛\n";
cin >> choice;
switch (choice)
{
case '1':
cout << "输入图书编号:"<<endl;
cin >> bookid;
cout << "输入图书书名:"<<endl;
cin >> bname;
addbook(bookid,bname);
break;
case '2':
cout << "输入图书编号:"<<endl;
cin >> bookid;
b=equal(bookid);
if (b==NULL)
{
cout << " 该图书不存在 "<<endl;
break;
}
cout << "输入新的书名:"<<endl;
cin >> bname;
b->setname(bname);
break;
case '3':
cout <<" 读入图书编号:"<<endl;
cin >> bookid;
b=equal(bookid);
if (b==NULL)
{
cout <<" 该图书不存在" << endl;
break;
}
b->delbook();
break;
case '4':
cout << " 读入图书编号:"<<endl;
cin >> bookid;
b=equal(bookid);
if (b==NULL)
{
cout <<" 该图书不存在"<< endl;
break;
}
b->output();
break;
case '5':
output();
break;
case '6':
clear();
break;
default:
cout<<"退出\n";
system("cls");
break;
}
}
}
int main()
{
char choice;
int bookid,Studentid;
RData StudentDB;
Student *r;
BDatabase BookDB;
Book *b;
while(choice!='0')
{
cout<<" ┏━━━━━━━━━━━━━┓\n";
cout<<" ┃ 图 书 管 理 系 统 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃1.借书 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃2.还书 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃3.图书维护 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃4.读者维护 ┃\n";
cout<<" ┃━━━━━━━━━━━━━┃\n";
cout<<" ┃0.退出 ┃\n";
cout<<" ┗━━━━━━━━━━━━━┛\n";
cin >> choice;
switch (choice)
{
case '1':
system("cls");
cout <<" 借书 读者编号:";
cin >>Studentid;
cout <<" 图书编号: ";
cin >>bookid;
r=StudentDB.equal(Studentid);//按编号查找
if (NULL==r)
{
cout <<" 不存在该读者,不能借书"<< endl;
break;
}
b=BookDB.equal(bookid);
if (b==NULL)
{
cout <<" 不存在该图书,不能借书"<< endl;
break;
}
if (b->borrowbook()==0)
{
cout << " 该图书已借出,不能借书"<< endl;
break;
}
r->borrowbook(b->getnumber());
system("cls");
break;
case '2':
system("cls");
cout<<"还书\n 读者编号:";
cin >>Studentid;
cout << " 图书编号:";
cin >>bookid;
r=StudentDB.equal(Studentid);
if (r==NULL)
{
cout <<" 不存在该读者,不能还书" << endl;
break;
}
b=BookDB.equal(bookid);
if (b==NULL)
{
cout <<" 不存在该图书,不能还书" <<endl;
break;
}
b->retbook();
r->retbook(b->getnumber());
break;
case '3':
system("cls");
BookDB.bookdata();
break;
case '4':
system("cls");
StudentDB.Studentdata();
break;
default:
cout<<"退出\n";
}
}
}
第四章 总结
图书馆管理系统的学习是对我近期的学习成果的综合考验,说实话对我来说确实是很困难,第一次使用对一个程序修改这么多次,第一次对一个程序的修改这么长时间,但历经的千辛万苦换来了最总还是换来了甘甜的成果。
首先,图书馆管理系统需要多各类来实现,包括、图书类,记录类、用户类、管理类。其中对于记录类的修改多达数次,
对用户的借阅信息不能够完整的输出,中间夹杂着一些乱码,最后还是在同学的帮助下把读入文件内的结束限定符给删除才得以解决,借阅信息的自己最看中的还是对于借阅次数的修改,用户借过几本书,借阅记录这是怎么显示的,其中关联到借还书的流程,用到了两个判断语句,最终得意实现,这次对于结构体的使用又加深了理解,前面加一个有关判断这本书存不存在,后面在管理端查找书提供了方便,这就体现了关联性,很好的实现了功能.
第五章 实习日记(按日期6篇)
第一篇
在此次课设中我选择的是图书馆管理信息系统,其中涉及到图书信息系统读者信息,图书借阅信息等多种数据的管理,使得使用该系统可以方便查询信息和实现借书还书功能。实验中要求实现图书的分类及图书信息的录入、修改、删除和校审;实现借阅者分类及借阅者个人信息的录入、修改和删除;实现借书和还书功能;可图书查询和借阅查询;对用户信息管理及权限分配。对于图书管理系统,首先是要确定它的功能。图书管理系统的功能有两部分,一是后台,后台拥有的功能就是增删查改。增就是增加图书,增加用户;删就是删除图书删除用户;查就是查找图书和用户的信息,其中有通过书号和学生姓名查找等等;该就是修改图书和用户的信息。二是客户端,对于客户端,功能就是查书、借书、还书和续借。要注意的是客户端的查书和后台的查书是不一样的,客户端的查书只有书籍的信息,后台的查书还有书籍的借阅记录,所以写代码时要注意区分开从而进一步进行需求分析,首先做一个总的图书管理的系统,里面包含借书还书,信息查询等。其次建立图书信息系统和读者信息系统的函数调用,完成对图书和读者添加,修改,删除,查询,显示以及全删的功能。然后再其中加入还书和借书功能,并再信息管理中做好记录,已借和未借的记录。最后增加一个退出系统,该系统分为一个大系统,两个小系统,进入小系统中可返回至大系统,从而实现别的系统功能。
数据分析中图书信息要包含书名和编号,方便查找及借还,读者信息则需要信息增添才可实现借书还书功能,读者信息包括姓名以及编号。
以上分析可得知我们需要建立不同的多个系统,并具有包含关系,以便于下一步编写代码。
6月10
第二篇
概要设计主要为大概对图书馆系统编程设计的规划,首先建函数,用于联系各个功能函数模块,以及退出程序时的退出画面提示。函数的入口:整个程序是从主函数开始的。函数的出口:当从main()的ove函数开始中进入,即显示出欢迎使用界面;跳出while循环,然后退出main()函数,即:退出整个程序。函数调用关系:该函数不被其它函数调用。
其次还需要加入功能函数output()。用来输出所有图书信息。函数的入口:从Find()的switch()开关结构中进入,即sclele的值为4时,进入该函数。并调用PrintRecord()函数对每一条图书信息进行输出。函数调用关系:被Find()函数调用。由switch()开关结构中进入,并在文中无返回值的空值void函数。函数的出口:将所有图书信息都输入到屏幕上后,执行Find()函数中“break;”跳出switch()开关函数,继续执行while循环结构。
还要创建功能函数BorrowBook()。用来借阅图书。函数的入口:从Borrow()的switch()开关结构中进入,即shl的值为2时,进入该函数。之后对用户的信誉值进行判断,若低于60将无法借书。然后调用FindByName()函数对所借图书进行搜索,若存在则输入借书时间,否则借书失败。函数调用关系:被Borrow()函数调用。由switch()开关结构中进入,并在文中无返回值的空值void函数。函数的出口: 将借书结果输入到屏幕上后,执行Borrow ()函数中“break;”跳出switch()开关函数,继续执行while循环结构。
最后建立功能函数SendBook ()。用来归还图书。函数的入口:从Borrow ()的switch()开关结构中进入,即shl的值为3时,进入该函数。之后先判断该用户是否有借书记录,并调用FindByName()函数找到还的图书并对其数量进行修改,最后判断是否按期归还图书和图书有无破损。函数调用关系:被Borrow ()函数调用。由switch()开关结构中进入,并在文中无返回值的空值void函数。函数的出口: 还书完成后后,执行Borrow()函数中“break;”跳出switch()开关函数,继续执行while循环结构。
6月11
3.第三篇
详细设计为具体代码的编写,先考虑该系统所需要的数据类:1>记录类(学号,书号,借还时间,是否续借);2>用户信息类(姓名,密码,类型,当前借阅,最大借阅,是否违规);3>图书信息类(书号,书名,作者是否续借,总册数,可借本数);在用户信息类和图书信息类中都有储存记录的vector以及两个索引:在一本书借阅记录中查找借阅人,在用户借阅记录中查找借阅书;在所有的数据类中都有输入输出运算符重载,方便整体输入输出。再分析该系统所需要的操作类:1>管理员操作类(储存用户的vector和储存图书的vector以及两个查找指定用户或图书的索引)增删查改用户和图书:先输入学号或书号,判断当前输入是否有效(-1为无效结束输入),再通过查找判断输入的学号或书号是否存在,然后再进行后续操作。2>客户端类(指定用户,储存图书的vector,三个索引)查询图书,分为按书名查询和按作者查询,两者功能相似,现就其一说明——使用find_if函数对vector中储存的图书进行查找,符合条件的输出到屏幕;为了设定查询条件,在之前写了一个结构体.。3>借还书功能类(借书功能与还书功能操作的具体实现)。
关于图书馆系统编程需要考虑各个方面,借书时考虑图书记录,学生记录添加,图书总册数减一,借出册数加一,学生总借书量加一,还可以借减一,当学生有违纪时,不能借书;还书时,在记录里考虑是否有这本书,如果没有就提示,有的话考虑是否已换,还书给记录打上标志,表示该书已经还过了,同时将借书时总书量等修改,当还书时间超过该还书的时间,会提示;至于续借就是将该图书还日期加上两个月,续借过的书不能再续借;至于添加图书学生信息,可以重载输入输出进行添加,一定记住添加到multimap和 vector,尤其是重载赋值号。消除学生违纪,就是将学生的违纪标志去掉,就可以借书了。
6月13
4.第四篇
这次是完成项目的搭建以及代码的编写,写代码的时候一定要写一个功能调试一个功能,所谓的一个功能不是一个类,而是一个类的一个函数,如果一个函数会影响到其他函数的运行,不调好之前的函数,现在的函数也没法运行,当代码随着项目的增大,代码长度几何增长是,再找错误就很难的了,所以顺着调试下去,以便你写完的代码是可以运行的,是正确的,而具体能否实现功能在另说。数据类与操作类的分离,面向对象要的是封装性,操作抽象+数据抽象,继承,写代码写完能够复用最好,乱糟糟的写完不能复用的类扔在那里,以后再也不会用到,浪费时间,完全可以写一些代码条理清晰,更重要的是,下次相似的代码不用再继续写,这应该是应该具备的素养。
此图书管理系统可以简单实现书籍的添加删除,学生信息的添加删除,以及学生借书、还书等功能。目前此系统运用了“类与对象”“运算符重载”“STL”等知识,
在编写过程中,遇到问题了很多问题,如信息写入文件后,不能再重复读入;不能准确的查找到信息;新知识运用的不够灵活,掌握的不够好,等等。其中文件的读写这个问题比较严重,第一次使用文件流很多东西还不懂,就去看了不少网课和有关的博客,还有c++ primer plus,最后照着葫芦画瓢写了出来吧,日后还要多多研究。寻找并改正错误的过程也很艰辛,一点一点检查排除,记得在排查multimap中搜寻不到的时候,还使用了单步调试。
编写到这儿遇到了大大小小许多问题,这是对学到知识的检测以及耐心的考验。这次课题作业也让我懂得了在遇到问题要心平气和慢慢的来,不能着急,多查查资料,多请教一下同学,心急吃不了热豆腐。
6月15
5.第五篇
进行程序调试得测试,对于这个系统在操作的过程中出错最多的地方是文件的操作,就是文件的读入和读出总是出现问题,问题在于以下两点:一是在重载输入流输出流运算符的时候出现了错误,即输入和输出的格式是不相同的。也就是说,在重载的过程中要保证输入和输出的格式保持一致;第二点,是加一个识别的控制符,控制输入图书信息和记录,让系统能够识别你输入的是记录,还是图书信息,同样用户也是这样,也要加一个控制符来区别用户信息和借阅记录,这样系统也就可以正确的识别出来,我的方法是,加一个number,也就是借阅的总量,让系统在输入的时候,可以依照for循环来向系统里输入借阅记录。对于这个系统,是分成两个部分一个是用户操作类,另一个是管理员操作类。对于用户类应该有查书,借书还书,查看自己的借阅记录几个功能,
查书需要先进行几个前提处理,这本书的库存是否够,自己是否有不良借阅记录,自己借书的上限是否已经达到,满足条件即可实现借书功能还书时候需要搜寻这本书之前的借阅记录,一一对应起来之后就可以,修改可借数量即可。
最后,是查询功能,这个地方在写的时候,会出现查询的信息不一一对应的情况,要加一个clear(),加一个clear()函数可以把建立的临时对象及时更新,避免查询时出现错误,同时还可以将用户操作类和管理员操作类中的相同数据成员与成员函数建立基类,使用继承法,继续优化代码,让代码变得简洁。
第一次完全放弃使用数组,使用vector(动态数组)的方式储存,和multimap的查找方式,代码比以前简洁、规范和易懂,理解明白里push_back、insert、erase、find等的具体实现方法,发现了push_back()输入时要写深复制的复制构造函数,等等新知识
6月17
6.第六篇
图书馆管理系统是我至今为止做的最复杂的管理系统,持续了近一个星期,修改了5到6次,到现在还是处在修改完善的状态,这个过程很辛苦,但也收获满满。在这个过程里,我遇到的最大障碍应该是文件的读取,我一开始对重载输入输出流的定义不当,导致文件读取的内容不对,经过长时间的修改与调整才克服了这一难关。虽然完整,但有两个致命的缺陷,一个是只从文件中读取了图书和用户的基本信息,而忽略了借阅记录,还有就是将用户端的用户对象定义成向量,而没有定好特定的对象。后来我使用了重载赋值运算符的方法,找到特定的用户对象。在文件方面,我将图书和用户的借阅信息加入了文件中,这个过程同样有一些问题,一开始,是记录无法正常存取,我加了记录数目这个数据成员做限定才最终解决。之后又发现只能读取第一个人的记录信息,在同学的提示下,我对临时对象做了清空处理,才最后解决这一问题。这一版,总的来说比较成熟,但还是有一个严重的问题,我在用户操作类中用户对象使用了无参的构造函数,登陆之后才去输编号,这其实并不能把用户封死。然后,我就把对应的无参构造函数改成了有参构造函数,只能对特定对象做操作,而且,我把时间改成了每次登陆只输一次,每次登陆后所有借书还书操作都是在同一时间进行,而不用重复的输入时间,借书时只要输入书号即可。通过,这些修改,我基本可以正确的模拟图书馆管理系统功能的实现。我有些地方还不是特别会写,还需要进一步的研究。通过这个系统,我对学过的各种知识有了更加全面的掌握,同时我明白了一个道理,考虑问题一定要考虑周全,一定要联系实际情况,就像用户端一定要只能对特定用户做操作一样,同时要学会修改程序,只有在不断修改中,程序才会完善。这个系统只是我的第一步,我会吸取经验教训,写出更加完善的程序。
6月18