第一篇:用C++编写的图书管理系统
C++实现图书管理系统 一:功能:
1.需要有个系统管理员和普通读者;
2.对图书库存图书的创建,添加,删除,修改,查询;
3.对读者借阅信息的创建,添加,删除,修改,查询; 4:普通读者只有查询上述两个文件的权利;
5:管理员可对普通读者的创建,添加,修改,删除; 6:管理员拥有上述全部权利;
7:要与文件流进行关联,如:创建,添加,读取,删除,查询;
第二篇:C++课程设计(简单图书管理系统)
课 程 设 计
课程名称
C++课程设计 题目名称
图书管理系统
2016 年月 29 日
目录
一.设计内容与要求...............................................................................................................2 二.设计思路:.......................................................................................................................4 三.关键模块实现及主要代码...............................................................................................4 四.实验结果及分析.............................................................................................................13
五、心得体会.........................................................................................................................16
六、参考文献.........................................................................................................................17
一.设计内容与要求
(1)、设计一个图书管理系统,能够实现用户信息管理,图书信息的 录入、查询、删除等功能。
(2)、实现用户管理,系统具有用户注册功能。管理员的账号和密码由系统指定,登录后可进行修改。一般用户注册后才能登录使用系统。管理员具有录入、查询、删除图书信息及一般用户的功能。一般用户只有图书查询功能。
(3)、登录功能,只有注册了的用户才能进入系统,没有注册的则有提示信息出现。
(4)、图书管理功能,管理员能够录入、查询、删除图书信息。(5)、图书查询功能,管理员及一般用户能够通过图书的基本信息,如图书作者、书名、出版社、出版日期等等,进行查询。
提示:上述为基本功能,可参考实际的系统进行扩展。
二.设计思路:
为了实现用户信息以及图书信息的管理,建立一个用户CUser类与图书信息CBoodata类,其中CUser类应该包含用户账号以及密码,CBookdata类应该包含图书作者,书名,出版社,出版日期。同时应该建立两个dat文件,一个为存储用户信息,一个用来储存图书信息。程序主要分为4个页面:(1)登录页面,由Cdialog类派生出CMyprojectDlg类,用来处理账号注册与用户登录。
(2)图书查询页面。由Cdialog类派生出CSearch类。包含读取所有图书数据响应函数,以及根据作者姓名或者书名来查询图书响应函数。
(3)管理员图书管理页面。由Cdialog类派生出CBookdata类。包含读取所有图书响应函数,添加图书响应函数,修改图书响应函数,删除图书响应函数。(4)用户信息管理页面,由Cdialog类派生出CUserdata类。包含读取所有用户信息响应函数,删除用户响应函数、添加用户响应函数、修改用户信息响应函数。
因为本人能力有限,而且自己是根据老师给的教程以及结合书本内容来完成课程设计,于是我第一想到的就是应数组来存储信息,而不是用链表,所以,对于文件数据的删除与修改,难免会过于乏力。
三.关键模块实现及主要代码
(1)自己建立的类 1.用户类: class CUser { public: int num;char password[20];};
2.图书信息类:
class Book
//图书类 { public:
char author[10];
//设置作者姓名
char bname[20];
//设置图书书名
char pub_name[20];
//设置出版社名称
int pub_date;
//设置出版年月 };
(2)登录页面,由Cdialog类派生出CMyprojectDlg类,用来处理账号注册与用户登录。1.用户注册处理响应函数:
void CMyprojectDlg::OnButton3()
//用户注册 { // TODO: Add your control notification handler code here
////////////////////////////////////////////////////////////////////////////////////// //以下代码主要还是把这条记录写入文件,注意写入的格式:文件的前四个字节是保持用户记录数,//后面依次保持用户记录注意,写用户的每个信息的顺序要与读取时的顺序一致。
UpdateData(TRUE);CUser user;int n_user=0;
//用户的个数,管理员默认为第一个。自己输入为账号:1111,密码:0000。
int size=0;
fstream file(“user.dat”,ios::in|ios::out);// 建立一个文件类,关于其用法,请baidu。
file.seekg(ios::beg);
//将文件指针指向文件头。
file.read((char*)&n_user,sizeof(n_user));
//读取用户数。
n_user+=1;file.seekp(ios::beg);file.write((char*)&n_user,sizeof(n_user));//写学生记录个数
user.num=m_num;
//之前定义user.password为string,导致密码匹配时有错误。。。
memcpy(user.password,m_password.GetBuffer(m_password.GetLength()),m_password.GetLength());// 把类CString对象的内容赋值到字符数组中
user.password[m_password.GetLength()]=' ';//在数组末尾加结束符号
//在文件末尾,把新的记录写入。
file.seekp(4+(n_user-1)*sizeof(CUser),ios::beg);
//这里出错
file.write((char*)&user.num,sizeof(user.num));file.write((char*)&user.password,sizeof(user.password));
file.close();
///////////////////////////////////////////////////////////////////////////////////////// //用消息框提示
CString str;str.Format(“成功注册,成为第 %d 个注册用户,请按确定返回重新登录.”,n_user-1);
///因为第一个为管理员,不算为用户人数。
AfxMessageBox(str);
} 2.用户登录处理响应函数。其中包含判断是管理员,还是普通用户。void CMyprojectDlg::OnButton2()
//用户登录 { // TODO: Add your control notification handler code here
UpdateData(TRUE);
CUser m_user[100];int i;int size;int n_user=0;//文件中用户的个数
////////////////////////////////////////////////////////////////////////////////////////// //读取文件中的用户记录,注意读取顺序与写入的顺序要一致,文件最开始的4个字节是表示记录个数。
//根据记录个数,依次读取用户记录 放在成员变量m_st数组中(已在类体中声明了)
CFile file;
file.Open(“user.dat”,CFile::modeReadWrite);size=GetFileSize((void*)file.m_hFile,NULL);//读取文件大小,size==0表示是空文件
if(size>0){
file.SeekToBegin();
file.Read(&n_user,sizeof(n_user));}
if(n_user>0 && n_user<99)//实验中限定为0~100个用户记录
{
for(i=0;i { //请注意与写入数据的顺序要保持一样,否则会读错数据。 file.Read(&(m_user[i].num),sizeof(m_user[i].num)); file.Read(&(m_user[i].password),sizeof(m_user[i].password)); } } file.Close();///////////////////////////////////////////////// if(m_num==1111&&m_password==“0000”) //管理员进入管理员页面 { CAdministrators administrators; administrators.DoModal();} CString str_password;for(i=0;i //普通用户,进入图书查询页面 { str_password=m_user[i].password; if(m_user[i].num==m_num) { if(str_password==m_password) { CSearch search; search.DoModal(); } else { CString str; str.Format(“密码或者账号错误,请重新输入!”); AfxMessageBox(str); } } } } (3)图书查询页面。包含读取所有图书数据,以及根据作者姓名或者书名来查询图书。1.读取所有图书响应函数。 void CSearch::OnButton5() //显示出所有图书 { // TODO: Add your control notification handler code here int i;int size;int n_book=0;//文件book的本数 ////////////////////////////////////////////////////////////////////////////////////////// //读取文件中的书本记录,注意读取顺序与写入的顺序要一致,文件最开始的4个字节是表示记录个数。 //根据记录个数,依次读取书籍记录 放在成员变量m_user_book数组中(已在类体中声明了) CFile file; file.Open(“book.dat”,CFile::modeReadWrite);size=GetFileSize((void*)file.m_hFile,NULL);//读取文件大小,size==0表示是空文件 if(size>0){ file.SeekToBegin(); file.Read(&n_book,sizeof(n_book));} if(n_book>0 && n_book<99)//实验中限定为0~100个书本记录 { m_num_book=n_book; for(i=0;i { //请注意与写入数据的顺序要保持一样,否则会读错数据。 file.Read(&(m_user_book[i].author),sizeof(m_user_book[i].author)); file.Read(&(m_user_book[i].bname),sizeof(m_user_book[i].bname)); file.Read(&(m_user_book[i].pub_name),sizeof(m_user_book[i].pub_name)); file.Read(&(m_user_book[i].pub_date),sizeof(m_user_book[i].pub_date)); } } file.Close();///////////////////////////////////////////////// //在列表控件中显示所有条记录 //插入每列的表头; m_list.InsertColumn(0,“作者”,LVCFMT_LEFT,100,1); m_list.InsertColumn(1,“书名”,LVCFMT_LEFT,100,1);m_list.InsertColumn(2,“出版社”,LVCFMT_LEFT,100,1);m_list.InsertColumn(3,“出版日期”,LVCFMT_LEFT,100,1);//每一行插入一条书本记录 for(i=0;i CString str; str=m_user_book[i].author; m_list.InsertItem(i,str);//InsertItem向CListCtr控件申请一行用来存放数据,同时写入一行的头名称(即编号为0列的数据) str=m_user_book[i].bname; m_list.SetItemText(i,1,str);//设置第i行第1列的的数据为书名 str=m_user_book[i].pub_name; m_list.SetItemText(i,2,str);//设置第i行第2列的的数据为出版社 str.Format(“%d”,m_user_book[i].pub_date); ///整型变为字符串,便于在控件显示 m_list.SetItemText(i,3,str);//设置第i行第3列的的数据为出版日期 } } 2.图书查询响应函数。 void CSearch::OnButton4() //查询图书 { // TODO: Add your control notification handler code here UpdateData(TRUE);m_list.DeleteAllItems();int num=0;//表示查找结果的个数 int i; for(i=0;i { CString str; int ret1=0,ret2=0; str=m_user_book[i].author; ret1=str.Find(m_author,0);//ret1>=0, 表示str中包含了m_author的字段 str=m_user_book[i].bname; ret2=str.Find(m_bname,0);//ret2>=0, 表示str中包含了m_bname的字段 if(ret1>=0) //按作者查询 { str=m_user_book[i].author; m_list.InsertItem(num,str);//InsertItem向CListCtr控件申请一行用来存放数据,同时写入一行的头名称(即编号为0列的数据) str=m_user_book[i].bname; m_list.SetItemText(num,1,str);//设置第i行第1列的的数据为书名 str=m_user_book[i].pub_name; m_list.SetItemText(num,2,str);//设置第i行第2列的的数据为出版社 str.Format(“%d”,m_user_book[i].pub_date); ///整型变为字符串,便于在控件显示 m_list.SetItemText(num,3,str);//设置第i行第3列的的数据为出版日期 num+=1;//结果+1; } } } (4)管理员图书管理页面。包含读取所有图书,添加图书,修改图书,删除图书的功能。1.读取所有图书功能实现与(3)的实现一样。2.添加图书响应函数。 void CBookdata::OnButton7() //添加图书 { UpdateData(TRUE);Book book;int n_book=0; //书本的个数 int size=0; fstream file(“book.dat”,ios::in|ios::out);// 建立一个文件类,关于其用法,请baidu。 file.seekg(ios::beg); //将文件指针指向文件头。 file.read((char*)&n_book,sizeof(n_book)); //读取书籍数。 ////////////////////////////////////////////////////////////////////////////////////// //以下代码主要还是把这条记录写入文件,注意写入的格式:文件的前四个字节是保持书本记录数,//后面依次保持书本记录注意,写学生的每个信息的顺序要与读取时的顺序一致。 n_book+=1;file.seekp(ios::beg);file.write((char*)&n_book,sizeof(n_book));//写学生记录个数 memcpy(book.author,m_add_author.GetBuffer(m_add_author.GetLength()),m_add_author.GetLength());// 把类CString对象的内容赋值到字符数组中 book.author[m_add_author.GetLength()]=' ';//在数组末尾加结束符号 memcpy(book.bname,m_add_bname.GetBuffer(m_add_bname.GetLength()),m_add_bname.GetLength());// 把类CString对象的内容赋值到字符数组中 book.bname[m_add_bname.GetLength()]=' ';//在数组末尾加结束符号 memcpy(book.pub_name,m_add_pub_name.GetBuffer(m_add_pub_name.GetLength()),m_add_pub_name.GetLength());// 把类CString对象的内容赋值到字符数组中 book.pub_name[m_add_pub_name.GetLength()]=' ';//在数组末尾加结束符号 book.pub_date=m_add_pub_date; //在文件末尾,把新的记录写入。 file.seekp(4+(n_book-1)*54,ios::beg); file.write((char*)&book.author,sizeof(book.author));file.write((char*)&book.bname,sizeof(book.bname));file.write((char*)&book.pub_name,sizeof(book.pub_name));file.write((char*)&book.pub_date,sizeof(book.pub_date)); file.close();///////////////////////////////////////////////////////////////////////////////////////// //用消息框提示 CString str;str.Format(“文件中已有 %d 本书籍记录.”,n_book);AfxMessageBox(str);} 3.修改图书响应函数。 void CBookdata::OnButton5() //修改图书,,必须先读取图书才能修改图书。{ // TODO: Add your control notification handler code here UpdateData(TRUE);m_list.DeleteAllItems();m_list.InsertColumn(0,“作者”,LVCFMT_LEFT,100,1); m_list.InsertColumn(1,“书名”,LVCFMT_LEFT,100,1);m_list.InsertColumn(2,“出版社”,LVCFMT_LEFT,100,1);m_list.InsertColumn(3,“出版日期”,LVCFMT_LEFT,100,1); CString str_author,str_bname,str_pub_name,str; //将book类的字符串数组赋值为字符串变量,方便比较。 CFile file;// 建立一个文件类,关于其用法,请baidu。 file.Open(“book.dat”,CFile::modeReadWrite);//打开文件 file.SeekToBegin(); file.Write(&m_num_book,sizeof(m_num_book));//写书本记录本数 for(int i=0;i { str_author=m_book[i].author; str_bname=m_book[i].bname; str_pub_name=m_book[i].pub_name; if(str_author==m_author||str_bname==m_bname||str_pub_name==m_pub_name||m_book[i].pub_date==m_pub_date) { memcpy(m_book[i].author,m_modify_author.GetBuffer(m_modify_author.GetLength()),m_modify_author.GetLength());// 把类CString对象的内容赋值到字符数组中 m_book[i].author[m_modify_author.GetLength()]=' ';//在数组末尾加结束符号 memcpy(m_book[i].bname,m_modify_bname.GetBuffer(m_modify_bname.GetLength()),m_modify_bname.GetLength());// 把类CString对象的内容赋值到字符数组中 m_book[i].bname[m_modify_bname.GetLength()]=' ';//在数组末尾加结束符号 memcpy(m_book[i].pub_name,m_modify_pub_name.GetBuffer(m_modify_pub_name.GetLength()),m_modify_pub_name.GetLength());// 把类CString对象的内容赋值到字符数组中 m_book[i].pub_name[m_modify_pub_name.GetLength()]=' ';//在数组末尾加结束符号 m_book[i].pub_date=m_modify_pub_date; } ////////////////////////////////////////////////////////////////////////////////////// //以下代码主要还是把这条记录写入文件,注意写入的格式:文件的前四个字节是保持学生记录数,//后面依次保持学生记录注意,写学生的每个信息的顺序要与读取时的顺序一致。 file.Write(&m_book[i].author,sizeof(m_book[i].author)); file.Write(&m_book[i].bname,sizeof(m_book[i].bname)); file.Write(&m_book[i].pub_name,sizeof(m_book[i].pub_name)); file.Write(&m_book[i].pub_date,sizeof(m_book[i].pub_date)); ///////////////////////////////////////////////////////////////////////////////////////// //在列表控件中显示所有条记录 str=m_book[i].author; m_list.InsertItem(i,str);//InsertItem向CListCtr控件申请一行用来存放数据,同时写入一行的头名称(即编号为0列的数据) str=m_book[i].bname; m_list.SetItemText(i,1,str);//设置第i行第1列的的数据为书名 str=m_book[i].pub_name; m_list.SetItemText(i,2,str);//设置第i行第2列的的数据为出版社 str.Format(“%d”,m_book[i].pub_date); ///整型变为字符串,便于在控件显示 m_list.SetItemText(i,3,str);//设置第i行第3列的的数据为出版日期 } file.Close(); //用消息框提示 str.Format(“成功修改书籍记录.”);AfxMessageBox(str);} 4.删除图书响应函数。 void CBookdata::OnButton6() //删除图书,,读取了图书数据后才能删除图书 { // TODO: Add your control notification handler code here UpdateData(TRUE);m_list.DeleteAllItems();m_list.InsertColumn(0,“作者”,LVCFMT_LEFT,100,1); m_list.InsertColumn(1,“书名”,LVCFMT_LEFT,100,1);m_list.InsertColumn(2,“出版社”,LVCFMT_LEFT,100,1);m_list.InsertColumn(3,“出版日期”,LVCFMT_LEFT,100,1); CString str_author,str_bname,str_pub_name,str; //将book类的字符串数组赋值为字符串变量,方便比较。 int n_book,n_flag=0; // n_flag为删除标志,1为有元素删除了 CFile file;// 建立一个文件类,关于其用法,请baidu。 file.Open(“book.dat”,CFile::modeReadWrite);//新建一个文件并且打开文件 file.SeekToBegin(); file.Write(&m_num_book,sizeof(m_num_book));//写书本记录本数,先填入本来的书本数。 for(int i=0;i { str_author=m_book[i].author; str_bname=m_book[i].bname; str_pub_name=m_book[i].pub_name; if(str_author==m_del_author||str_bname==m_del_bname||str_pub_name==m_del_pub_name||m_book[i].pub_date==m_del_pub_date) { n_flag=1; //删除标志置1 i+=1; //第i个元素为要删除元素,跳过 } ////////////////////////////////////////////////////////////////////////////////////// //以下代码主要还是把这条记录写入文件,注意写入的格式:文件的前四个字节是保持 学生记录数,//后面依次保持学生记录注意,写学生的每个信息的顺序要与读取时的顺序一致。 file.Write(&m_book[i].author,sizeof(m_book[i].author)); file.Write(&m_book[i].bname,sizeof(m_book[i].bname)); file.Write(&m_book[i].pub_name,sizeof(m_book[i].pub_name)); file.Write(&m_book[i].pub_date,sizeof(m_book[i].pub_date)); } if(n_flag==1) { n_book=m_num_book-1; //表示删除了一本书,则将文件的书本数减1。 file.SeekToBegin(); file.Write(&n_book,sizeof(n_book));//写书本记录本数,先填入本来的书本数。 //用消息框提示 str.Format(“成功删除书籍记录.”); AfxMessageBox(str); } else { //用消息框提示 str.Format(“没有这一本书的记录,不能删除.”); AfxMessageBox(str); } file.Close();} (5)、用户信息管理页面,包含读取所有用户信息,删除、添加、修改用户信息。1.读取所有用户信息以(4)基本相同。 2.删除用户信息实现基本方法与(4)基本相同。3.添加用户信息实现基本方法与(4)基本相同。4.修改用户信息实现基本方法与(4)基本相同。 四.实验结果及分析 (1.)登录页面 成功注册 普通用户成功登录页面 查询结果 管理员登录页面 图书管理页面 成功添加图书。 用户信息管理页面 分析:基本功能是可以实现的,但是因为是用数组来存放图书信息与用户信息,所以对于数据大了之后处理能力不够方便以及效率不高。而且删除信息的时候只是删除该条数据的信息,数据后面的信息往上移动,所以最后面会有两条重复的信息,虽然文件开头储存信息数目已经减一,读取数据是按照文件开头储存的信息数目来读取信息,但是有时候读取会有乱码。我在程序中找不到那个隐藏的bug,五、心得体会 这次C++课程设计学到了很多,懂得了C++看起来虽然简单,可是要用这个计算机语言来实现一些有用的功能,怎么运用确实是一门挺高深的学问,我们学习计算机语言不能只是看书看概念,要多上机实验,这样才能对计算机语言有比较深的了解,才能够提高自己的编程以及调试找BUG的能力。现在来总结一下编程过程中遇到的一些值得注意的问题。 1.派生出一个类时,为编辑框增加变量名后,然后在类声明中自己增加类成员,如果再想在对话框中增加编辑框并且添上变量名会出现错误。(如下,在Csearch 类中自己添加下面箭头指向的代码后,会出现下图右的错误,解决方法是把箭头指向的代码放到//}}AFX_DATA后面,因为此语句为MFC对话框自行添加编辑变量的结束,如果我们将自己定义的变量也添加到此语句前,编译器不清楚是MFC自行添加的变量还是用户自行添加的变量。)2.遇到编译器没有出错,可是运行结果与自己想象的不一样,很可能是逻辑错误。如: 在用户注册时,我是将用户数据直接存到文件尾,这是不正确的,因为管理员页面有删除用户的功能,这个功能的原理是先读文件头的用户数(假定为10个),然后将用户的数据先读取出来,然后经过一个判断,再储存重新储存回文件,而文件中储存的用户数据大小是没有变化的,也就是说文件尾会有两份最后一个用户的数据(即如果删除的是第七个,文件中最后会有两份第十个用户的数据,文件头的记录用户数为9个),如果添加用户直接储存在文件尾则会储存在第11个用户的位置,可是以后读取的话只是读取到第10个。所以会出现读取错误,密码不匹配的问题。应该根据记录的用户数让文件指针指向最后一个用户数据后面。file.seekp(4+(n_user-1)*sizeof(CUser),ios::beg); 以上两个问题是困扰我比较久的,其他问题经过百度还有自己的调试,解决还算快,不值得重点说。 六、参考文献 1.C++面向对象程序设计(第二版) 谭浩强 编著 2.成绩管理系统MFC教程 3.CNDN论坛,关于文件操作的指针运算。 #include #include #include #define NONE “ 33[m” #define RED “ 33[0;32;31m” #define GREEN “ 33[0;32;32m” #define BLUE “ 33[0;32;34m” #define YELLOW “ 33[1;33m” #define LIGHT_RED “ 33[1;31m” #define LIGHT_GREEN “ 33[1;32m” #define LIGHT_BLUE “ 33[1;34m” /* 在编译程序之前,请先开启mysql服务器(命令为 sudo mysqld_safe &),然后再登录mysql客户端(命令为 mysql-u root-p)建立数据库 stu;建立数据表reader,book;具体操作语句如下: create database stu; create table reader(stu_name varchar(20),stu_phone varchar(15),stu_password varchar(10),stu_num int,debt float,lend_time double,back_time double,count int); create table book(book_name varchar(40),book_aut varchar(40),book_pre varchar(40),book_num int,book_mux int,book_con int); 编译时用如下命令: g++ $(mysql_config--cflags)110.cpp-o t $(mysql_config--libs)*/ //定义mysql数据库变量 MYSQL mysql;MYSQL_RES * results; MYSQL_FIELD *fileds; MYSQL_ROW rows; char strHost[] = “localhost”; char strUser[] = “root”; char strPasswd[] = “3335599”; char strDb[] = “stu”;char strSQL[200]; unsigned int num_fields;/* 程序导读: 1.程序中对书的操作,可通过书名,编号来进行,flag=0按书名来操作,flag=1按书编号来操作 2.程序中对用户的操作,也可通过姓名,用户ID号或编号两种方式来进行,flag=0按姓名来操作,flag=1按用户ID号或编号来操作 3.本程序分5个部分,具体已标识如(1)图书管理...4.本程序即可实现将数据保存至本地即stu.txt,book.txt,又可将数据保存至mysql数据库,只 需稍加修改,具体如何修改,在此就不做说明 */ using namespace std;class Book { public: string book_name;string book_num;//编号 string book_pre;//出版社 string book_aut;//作者 int book_con;//这样的书还有几本 int book_mux;//这样的书总共有几本 public: Book(){book_con=0;book_mux=0;} void show_book(); }; /****************************************(1)图书管理*******************************************/ void Book::show_book(){ cout<<“书名:”< class BookNode { public: Book book;BookNode *next;};BookNode *headbook=NULL; void savebook(BookNode *p);//保存图书信息到数据库 void del_sql_book(BookNode *p);//将图书信息从数据库中删除 class BookManage { public: int totolbook;public: BookManage(){totolbook=0;} void addbook(); void delbook(string s,int num,int flag);void findbook(string s,int flag);//查询图书 }; void BookManage::addbook(){ string h; cout<<“添加输入0,退出输入-1”< if(h==“-1”)break;else if(h==“0”){ string na,nu,p1,aut;int con;BookNode *p=new BookNode;cout<<“请输入书名:”< cout<<“继续添加输入0,取消添加输入-1”< cin>>h; } else cout< void BookManage::delbook(string s,int num,int flag){ BookNode *p=headbook;if(headbook!=NULL){ switch(flag) { case 0: if(headbook->book.book_name==s) { if(headbook->book.book_con>1) {headbook->book.book_con-=num;headbook->book.book_mux-=num;} else { headbook=p->next;totolbook-=num; del_sql_book(p);//从数据库中删除 //delete p; } } else if(p->next) { for(p=headbook;p->next!=NULL&&p!=NULL;p=p->next) { if(p->next->book.book_name==s) { if(p->next->book.book_con>1) { p->next->book.book_con-=num;headbook->book.book_mux-=num; break; } else { p->next=p->next->next; totolbook-=num; del_sql_book(p->next);//从数据库中删除 //delete p->next; break; } } } if(p->next==NULL) cout< break;case 1: if(headbook->book.book_num==s){ if(headbook->book.book_con>1) {headbook->book.book_con-=num;headbook->book.book_mux-=num;} else { headbook=p->next; totolbook-=num; del_sql_book(p);//从数据库中删除 //delete p; } } else if(p->next) { for(p=headbook;p->next!=NULL&&p!=NULL;p=p->next) { if(p->next->book.book_num==s) { if(p->next->book.book_con>1) { p->next->book.book_con-=num;headbook->book.book_mux-=num; break; } else { p->next=p->next->next; totolbook-=num; del_sql_book(p->next);//从数据库中删除 //delete p->next; break; } } } if(p->next==NULL) cout< } break; default: cout< } } } void BookManage::findbook(string s,int flag){ BookNode *p;int h=0;switch(flag){ case 0: for(p=headbook;p!=NULL;p=p->next)//先查看是否有此书 { if(p->book.book_name==s)break;} if(NULL==p)cout< if(p->book.book_name==s){ p->book.show_book();//显示出图书的基本信息 if(p->book.book_con==0) 打印出来 } cout< cout< } } break;case 1: for(p=headbook;p!=NULL;p=p->next){ if(p->book.book_num==s) { p->book.show_book(); if(p->book.book_con==0) cout< } } if(NULL==p)cout< /****************************************(*******************************************/ class Admin//管理员 { public: string adm_name;//帐号 string adm_passw;//密码 public: Admin(){ adm_name=“adm”; adm_passw=“123”;} }; class LendBook { public: string bookname[3];int count;//借多少本数 time_t lend_time;time_t back_time;LendBook(){count=0;} }; class Stu { public: string stu_name; }; 2)用户管理 string stu_phone;//联系方式 string stu_num;//学号(登录帐号)string password;//密码 float debt;//欠费额 LendBook lendbook;//用户借书信息 public: void show_stu();//把此人所有信息(包括借书)显示出来 void Stu::show_stu(){ cout<<“姓名:”< class StuNode { public: Stu stu;StuNode *next;};StuNode *headstu=NULL; void savestu(StuNode *p);//保存读者信息到数据库 void del_sql_stu(StuNode *p);//将读者信息从数据库中删除 class StuManage:public BookManage { private: int totolstu;//用户总数 public: StuManage(){totolstu=0;} void addstu();//增加用户 void delstu(string s,int flag);//删除用户 void findstu(string s,int flag);//查找用户 void lendbook(string ss,string s,int flag);//借书 void backbook(string ss,string s,int flag);//还书 void paydebt(string s);//还款 void mux_stu_book();//查询图书管总的图书量与总的用户量 }; void StuManage::addstu(){ string h; cout<<“添加输入0,退出输入-1”< if(h==“-1”)break;else if(h==“0”){ string na,num,p1,pa,pa1,pa2; StuNode *p=new StuNode; cout<<“请输入姓名:”< cin>>na; p->stu.stu_name=na; cout<<“请输入联系电话:”< cout<<“请输入六位密码:”< (StuManage::totolstu)++;//用户总数加一 cout<<“继续添加输入0,取消添加输入-1”< } else cout< void StuManage::delstu(string s,int flag){ StuNode *p=headstu;if(headstu!=NULL){ switch(flag) { case 0: if(headstu->stu.stu_name==s)//当要删除的用户位于链表的头结点位置 { headstu=p->next;StuManage::totolstu--;del_sql_stu(p);//从数据库中删除 delete p;} else if(p->next)//非头结点位置 { for(p=headstu;p->next!=NULL&&p!=NULL;p=p->next){ if(p->next->stu.stu_name==s) { p->next=p->next->next; totolstu--; del_sql_stu(p->next);//从数据库中删除 //delete p->next; break; } } if(p->next==NULL) cout< break;case 1: if(headstu->stu.stu_name==s){ headstu=p->next;totolstu--;del_sql_stu(p);//从数据库中删除 delete p;} else if(p->next){ for(p=headstu;p->next!=NULL&&p!=NULL;p=p->next){ if(p->next->stu.stu_name==s) { p->next=p->next->next; totolstu--; del_sql_stu(p->next);//从数据库中删除 //delete p->next; break; } } if(p->next==NULL) cout< } break; default: cout< } } } void StuManage::findstu(string s,int flag){ StuNode *p;int h=0,m=1;switch(flag){ case 0: for(p=headstu;p!=NULL;p=p->next) { if(p->stu.stu_name==s) break; } if(p==NULL) cout< for(p=headstu;p!=NULL;p=p->next) { if(p->stu.stu_name==s)h++;} if(h>0)cout< p->stu.show_stu(); if(p->stu.lendbook.count>=3) { cout< ”NONE< cout<<“所借书的名字为:”< while(i) { cout<<“t(”< } cout< } else { int i=p->stu.lendbook.count; if(i>0) cout<<“所借书的名字为:”< while(i) { cout<<“t(”< } } } break;case 1: } cout<<“您已借了”< stu.lendbook.count<<“本书!”< for(p=headstu;p!=NULL;p=p->next) { if(p->stu.stu_num==s) { p->stu.show_stu(); if(p->stu.lendbook.count>=3) { cout< int i=p->stu.lendbook.count; cout<<“所借书的名字为:”< //输出用户所借书的名字 cout<<“t(”< } cout< } else { int i=p->stu.lendbook.count; cout<<“所借书的名字为:”< while(i) { //输出用户所借书的名字 cout<<“t(”< } cout<<“您已借了”< stu.lendbook.count<<“本书!”< cout<<“您还可以借”<<3-p->stu.lendbook.count<<“本书!”NONE< cout< } break; } } if(p==NULL) cout< break; default: cout< } void StuManage::mux_stu_book(){ StuNode *p;BookNode *q;int i=0,j=0,h=0;for(p=headstu;p!=NULL;p=p->next)i++;cout<<“当前图书馆注册用户数为:”<next){ h+=q->book.book_mux; j+=q->book.book_con;} } cout<<“当前图书馆库存的总书记数为:”< if(q->stu.stu_num==ss) {del_sql_stu(q);break;}//丛数据库中删除 } if(q==NULL){cout< switch(flag){ case 0: for(p=headbook;p!=NULL;p=p->next) { if(p->book.book_name==s) { “NONE< del_sql_book(p);//从数据库中删除 int i=q->stu.lendbook.count;if(i>=3||q->stu.debt>0){ if((i>=3)&&(q->stu.debt==0)){cout< if((i<3)&&(q->stu.debt>0)) {cout< if((i>=3)&&(q->stu.debt>0)) {cout< } else { //记录下所借书的名字存入用户信息中 q->stu.lendbook.bookname[i]=p->book.book_name; time_t now; time(&now); q->stu.lendbook.lend_time=time(&now);//保存借书时间 q->stu.lendbook.count++;//所借书数目加一 p->book.book_con--;//同样的书的个数减一 } break; } } if(p==NULL) cout< break; case 1: for(p=headbook;p!=NULL;p=p->next) { if(p->book.book_num==s) { del_sql_book(p);//从数据库中删除 int i=q->stu.lendbook.count; if(i>=3||q->stu.debt>0) { if((i>=3)&&(q->stu.debt==0)) {cout< if((i<3)&&(q->stu.debt>0)) {cout< if((i>=3)&&(q->stu.debt>0)) {cout< } else { } q->stu.lendbook.bookname[i]=p->book.book_name; time_t now; time(&now); q->stu.lendbook.lend_time=time(&now); q->stu.lendbook.count++; p->book.book_con--;//同样的书的个数减一 } break; } } if(p==NULL) cout< break;default: cout< void StuManage::backbook(string ss,string s,int flag)//还书 { BookNode *p;StuNode *q;for(q=headstu;q!=NULL;q=q->next){ if(q->stu.stu_num==ss) {del_sql_stu(q);break;}//丛数据库中删除 } if(q==NULL){cout< switch(flag){ case 0: for(p=headbook;p!=NULL;p=p->next) { if(p->book.book_name==s) { del_sql_book(p);//从数据库中删除 time_t now; time(&now); q->stu.lendbook.back_time=time(&now); q->stu.lendbook.count--; p->book.book_con++;//同样的书的个数加一 time_t s=difftime(q->stu.lendbook.lend_time,q->stu.lendbook.back_time); if(s>2592000)//2592000为一个月的秒数 { int t=ceil((s-2592000)/86400); q->stu.debt=t*0.1; } break;} } if(p==NULL) cout< break; case 1: for(p=headbook;p!=NULL;p=p->next) { if(p->book.book_num==s) { del_sql_book(p);//从数据库删除 time_t now; time(&now); q->stu.lendbook.back_time=time(&now); q->stu.lendbook.count--; p->book.book_con++;//同样的书的个数加一 //计算借用图书的时间,超过一个月,开始计费 time_t s=difftime(q->stu.lendbook.lend_time,q->stu.lendbook.back_time); } if(s>2592000)//2592000为一个月的秒数 { int t=ceil((s-2592000)/86400); q->stu.debt=t*0.1; } break; } } if(p==NULL)cout< } void StuManage::paydebt(string s){ StuNode *p; for(p=headstu;p!=NULL;p=p->next)//查找用户 { if(p->stu.stu_num==s){ p->stu.debt=0; cout< stream << result;//将string输入流 stream >> stu_str;//从i中抽取前面插入的string值 return stu_str;} void savestu(StuNode *p)//保存读者信息到数据库 { memset((void*)strSQL,0,200);sprintf(strSQL,“insert into reader values(%s,%s,%s,%s,%f,%ld,%ld,%d)”,change_char(p->stu.stu_name),change_char(p->stu.stu_phone),change_char(p->stu.password),change_char(p->stu.stu_num),p->stu.debt,(long)(p->stu.lendbook.lend_time),(long)(p->stu.lendbook.back_time),p->stu.lendbook.count);if(mysql_real_query(&mysql,strSQL,strlen(strSQL))!= 0) printf(“记录插入失败!n”);} void savebook(BookNode *p)//保存图书信息到数据库 { memset((void*)strSQL,0,200);sprintf(strSQL,“insert into book values(%s,%s,%s,%s,%d,%d)”,change_char(p->book.book_name),change_char(p->book.book_aut),change_char(p->book.book_pre),change_char(p->book.book_num),p->book.book_mux,p->book.book_con);if(mysql_real_query(&mysql,strSQL,strlen(strSQL))!= 0) printf(“记录插入失败!n”); } void del_sql_stu(StuNode *p)//将读者信息从数据库中删除 { memset((void*)strSQL,0,200);sprintf(strSQL,“delete from reader where stu_name='%s'”,change_char(p->stu.stu_name));if(mysql_real_query(&mysql,strSQL,strlen(strSQL))!= 0) printf(“记录删除失败!n”);} void del_sql_book(BookNode *p)//将图书信息从数据库中删除 { memset((void*)strSQL,0,200);sprintf(strSQL,“delete from book book_name='%s'”,change_char(p->book.book_name));if(mysql_real_query(&mysql,strSQL,strlen(strSQL))!= 0) printf(“记录删除失败!n”); } /* void savestu()//保存读者信息文件 { ofstream outfile(“./stu.txt”,ios::out); if(!outfile){ cerr<<“open error!”< return;} StuNode *p; for(p=headstu;p!=NULL;p=p->next)//数据写入文件 { outfile< stu.stu_name<<“ ”< stu.stu_phone; outfile<<“ ”< stu.password<<“ ”< stu.stu_num; where outfile<<“ ”< stu.debt; outfile<<“ ”< stu.lendbook.lend_time; outfile<<“ ”< stu.lendbook.back_time; outfile<<“ ”< stu.lendbook.count; outfile<<“ ”< } outfile.close();} void savebook()//保存图书信息文件 { ofstream outfile(“./book.txt”,ios::out); if(!outfile){ cerr<<“open error!”< return;} BookNode *p; for(p=headbook;p!=NULL;p=p->next)//数据写入文件 { outfile< book.book_name<<“ ”< book.book_num; outfile<<“ ”< book.book_pre<<“ ”< book.book_aut; outfile<<“ ”< book.book_mux; outfile<<“ ”< book.book_con; outfile<<“ ”< void loadstu()//从学生数据数据库reader中读取 { int i = 0;memset((void*)strSQL,0,100); strcpy(strSQL,“select * from reader”); mysql_query(&mysql,strSQL); //查询 results = mysql_store_result(&mysql); //获取记录 num_fields = mysql_num_fields(results); //获取字段数 fileds = mysql_fetch_fields(results); //获取字段数组 while((rows = mysql_fetch_row(results))!= NULL) //循环显示 { while(i < num_fields) { StuNode *p=new StuNode; p->stu.stu_name =(rows[i]?rows[i++]:“NULL”); p->stu.stu_phone =(rows[i]?rows[i++]:“NULL”); p->stu.password =(rows[i]?rows[i++]:“NULL”); p->stu.stu_num =(rows[i]?rows[i++]:“NULL”); p->stu.debt = atof(rows[i]?rows[i++]:“NULL”); p->stu.lendbook.lend_time =(time_t)(rows[i]?rows[i++]:“NULL”); p->stu.lendbook.back_time =(time_t)(rows[i]?rows[i++]:“NULL”); p->stu.lendbook.count = atoi(rows[i]?rows[i++]:“NULL”); p->next=headstu;//建立用户链表 headstu=p; } i = 0;} } void loadbook()//从书数据库中读取 { int i = 0;memset((void*)strSQL,0,100); strcpy(strSQL,“select * from book”); mysql_query(&mysql,strSQL); //查询 results = mysql_store_result(&mysql); //获取记录 num_fields = mysql_num_fields(results); //获取字段数 fileds = mysql_fetch_fields(results); //获取字段数组 while((rows = mysql_fetch_row(results))!= NULL) //循环显示 { while(i < num_fields) { BookNode *p=new BookNode; p->book.book_name =(rows[i]?rows[i++]:“NULL”); p->book.book_aut =(rows[i]?rows[i++]:“NULL”); p->book.book_pre =(rows[i]?rows[i++]:“NULL”); p->book.book_num =(rows[i]?rows[i++]:“NULL”); p->book.book_mux = atoi(rows[i]?rows[i++]:“NULL”); p->book.book_con = atoi(rows[i]?rows[i++]:“NULL”); p->next=headbook;//建立用户链表 headbook=p; } i = 0;} } /* void loadstu()//从学生数据文件读取 { ifstream infile(“./stu.txt”,ios::in); if(!infile){ cout< return;} if(infile.eof()){ cout< infile.close();} else { while(infile.peek()!=EOF)//数据从文件读出 { StuNode *p=new StuNode; infile>>p->stu.stu_name>>p->stu.stu_phone; infile>>p->stu.password>>p->stu.stu_num; infile>>p->stu.debt>>p->stu.lendbook.lend_time; infile>>p->stu.lendbook.back_time>>p->stu.lendbook.count; if(p->stu.stu_name!=“") { p->next=headstu;//建立用户链表 headstu=p; } else delete p; } infile.close();} } void loadbook()//从书数据文件读取 { ifstream infile(”./book.txt“,ios::in); if(!infile){ } cout< while(infile.peek()!=EOF)//数据从文件读出 { BookNode *p=new BookNode;infile>>p->book.book_name>>p->book.book_num;infile>>p->book.book_pre>>p->book.book_aut;infile>>p->book.book_mux>>p->book.book_con; if(p->book.book_name!=”“){ p->next=headbook;//建立图书链表 headbook=p;} else delete p; } } */ } infile.close();/****************************************(*******************************************/ void MenuAdmin(){ 4)界面部分 cout< $“NONE< $“NONE< $“NONE< 删除书目 $“NONE< $“NONE< cout< 借书 $“NONE< $“NONE< cout< 还书 $“NONE< $“NONE< 查询图书 $“NONE< $“NONE< $“NONE< $“NONE< $“NONE< $“NONE< 查询用户 $“NONE< $“NONE< 用户交费 $“NONE< $“NONE< $“NONE< $“NONE< 0 退出 $“NONE< $“NONE< void MenuStu(){ 选 择 (输 入 相 应 数 cout< cout< $“NONE< cout< 借书 $“NONE< $“NONE< cout< 还书 $“NONE< $“NONE< 查询图书 $“NONE< $“NONE< 个人信息 $“NONE< $“NONE< 0 退出 $“NONE< $“NONE< int getch()//密码不回显函数1 { int c=0; struct termios org_opts, new_opts; int res=0; //-----store old settings----------- res=tcgetattr(STDIN_FILENO, &org_opts); assert(res==0); //----set new terminal parms-------- memcpy(&new_opts, &org_opts, sizeof(new_opts)); new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL); tcsetattr(STDIN_FILENO, TCSANOW, &new_opts); c=getchar(); //------restore old settings--------- res=tcsetattr(STDIN_FILENO, TCSANOW, &org_opts); assert(res==0); return c;} string set_passwd()//密码不回显函数2 { string result;char pd[128];int i;getch();/* 当帐号和密码一起输入,且刚输完帐号后就要输入密码时,set_passwd会把帐号结束时的回车赋‘n’拿过来作为自己的第一个输入,这样容易造成密码输入的错 误,为避免 这种情况的发生,所以就可以在for循环之前假如了getch()把‘n’吸收掉 */ for(i=0;;i++) { pd[i]=getch(); if(pd[i]=='n') { pd[i]=' '; break; } if(pd[i]==127) { printf(”b b“); i=i-2; } else printf(”*“); if(i<0) pd[0]=' '; } stringstream stream;stream << pd;//将char输入流 stream >> result;//从stream中抽取前面插入的char值 return result;} /****************************************(5)主函数部分*******************************************/ int main(){ mysql_init(&mysql);//数据库初始化 if(!mysql_real_connect(&mysql,strHost,strUser,strPasswd,strDb,0,NULL,0))//连接数据库 { printf(”连接数据库失败!/n“); return 0; } loadstu();loadbook(); mysql_free_result(results);//释放数据库结果集 BookManage bookmanage;StuManage stumanage; Admin admin;int i;string s;int num,flag;string s1,s2,ss;StuNode *p;system(”clear“);//清理屏幕 cout< ~Welecome to come in~“NONE< switch(i){ case 0: break; case 1: while(1) { cout<<”请输入管理员登录名:“< cin>>s1; if(s1==”0“) return 0; cout<<”请输入密码:“< s2=set_passwd(); cout< if(admin.adm_name==s1) { while(1) { if(admin.adm_passw==s2) break; else { cout< s2=set_passwd();cout< if(s2==”0“)return 0; //cin>>s2 } } } if(s1!=admin.adm_name) cout< else break; } while(1){ MenuAdmin();int t;cin>>t;switch(t){ ”< “< case 0: //savestu();savebook(); mysql_close(&mysql);//关闭数据库链接 return 0;break; case 1:bookmanage.addbook();//增加书本 system(”clear“);break;//清理屏幕 case 2: cout<<”按书名删除请输入 0 “< cin>>flag; if(flag==0) {cout<<“请输入书名:”;cin>>s;} else if(flag==1) {cout<<“请输入书编号:”;cin>>s;} else cout< cout<<“请输入要删除书的数目:”< cin>>num; bookmanage.delbook(s,num,flag);//删除书本 system(“clear”);//清理屏幕 break; case 3: cout<<“按书名借书请输入 0 ”< cin>>flag; if(flag==0) {cout<<”请输入书名:“;cin>>s;} else if(flag==1) {cout<<”请输入书编号:“;cin>>s;} else cout< cout<<”请输入借书人的编号:“<第三篇:用mysql数据库实现的C++图书管理系统