南京航空航天大学《C++语言程序设计》课程设计报告题目:图书库存管理班级:0116202学号:011620231姓名:苏瑞辅成绩:指导教师:潘梅园日期:2017年5月18日-1-目录一、程序功能................................................-2-二、新增功能................................................-3-三、数据结构................................................-5-四、函数调用关系图....................................-9-五、精选算法................................................-9-六、源程序..................................................-13-七、典型测试数据......................................-24-八、问题的处理方法..................................-35-九、做课程设计作业的感受......................-36--2-一、程序功能1.追加图书记录输入书号、书名和库存量,在库存列表尾部追加一条记录。此功能每次只能追加一本图书记录,用于初期建立库存记录。2.删除图书记录输入一本书的书号,首先在库表中查询该图书是否存在,若存在,则显示该图书记录,并提问是否删除该图书,根据回答(y/n)确定是否删除该图书;若不存在,提示该书不存在。3.显示所有图书记录每行显示一本图书记录信息。4.查询图书输入一本图书的书号,查询该书是否存在,若存在,则显示该书记录信息,否则提示该书不存在。5.图书入库输入一本书的书号,查询该书是否存在,若存在,则修改已有图书记录的库存量;若不存在,则追加一条图书记录。6.图书销售输入一本书的书号及销售数量。若该图书存在,并且库存量充足,则修改库存量;否则提示该书不存在或库存不足等信息。-3-7.批量导入图书记录用户输入一个文件名,系统自动地讲该文件中的图书记录追加到库存列表中,从而实现批量导入图书。8.导出图书记录提示用户输入一个文件名,系统自动将库存表中的全部图书记录信息写入该文件正文,文件格式与上述导入文件格式相同。9.排序提供六种排序的选择,分别对三个关键字按升序或降序排列。使用了冒泡法、选择法和插入法几种排序方法。10.删除全部图书记录提示用户是否确认(y/n),确认后删除全部图书记录。0.退出提示用户是否确认退出(y/n),退出时将数据导出到bookdata.txt.二、新增功能1.增加数据检查机制,防止添加重复数据(1)菜单一(追加图书记录)追加图书记录的时候先判断是否有该记录,如果已经有的话,则自动与原来的数据进行合并,即进行入库操作,并向用户提示“与原来的数据进行了合并”。-4-(2)菜单五(批量导入图书记录)批量导入图书记录实际上就是对追加图书记录的批量操作,同样需要数据检查机制,以防止数据重复。在本程序中,对每一个批量导入的数据进行检查,如果出现重复,则自动与先前的数据进行合并。(3)系统初始化的时候会自动地从bookdata.txt中导入数据,虽然这个数据中有重复数据的可能性比较小(因为我们是导出的数据,而这个数据用户是看不到的,对用户来说是透明的),但是为了避免错位,同样加入数据检查机制,具体操作和菜单五的相同。2.丰富排序功能(1)在课本上的按书号排序的基础上,本程序拓展出了六种排序的方案,即分别对书号、书名和数量进行升序或降序排列。(2)本功能的子菜单设计与主菜单的设计思想相同。(3)对书名、书号和数量三个关键字进行升序排列分别使用了冒泡法、选择法和插入法。(4)在对书号、书名和数量进行降序排列的时候所采用的方法是对先前升序排列的结果进行逆置(时间换空间)。3.查询图书时候的分页功能查询所有图书的时候每5条记录一页显示,按任意键后显示下一-5-页。4.输入文件的名字如果不包含.txt则自动添加,通过return_file_name函数实现。三、数据结构1.BOOK类(1)私有数据成员a.charbkNo[10]//书号,字符数组b.charbkName[20]//书名,字符数组c.intbkNum//库存量,即数量(2)公有成员函数a.intgetNum()//获取库存量b.voidsetNum(intbkNum)//设置库存量c.voidsetData(char*bkNo,char*bkName,intbkNum)//写入库存信息d.voidshow()//显示一本图书信息e.voidprint(ofstream&out)//将库存记录写入文件(3)友元的说明friendclassBookDatebase;//通过设置此友元,使访问变得更容易,但是类的隐蔽性也被破坏。-6-2.BookDatebase类(1)私有数据成员a.Book*bkptr//Book型的指针b.intcurLen,maxLen//线性表的最大长度和当前长度(2)公有成员函数a.BookDatebase(intn=10)构造函数,用来初始化线性表。并从bookdata.txt中导入数据。b.~BookDatebase()析构函数,用来释放线性表。并把数据导出到bookdata.txt.c.voidsetCurLen(inti)设置现在线性表的长度,在删除全部数据的时候会用到这个函数。d.intisIn(char*bkNo)判断书籍记录是否存在,此功能使用频率较高,主要作用是数据检查,防止出错。e.Book&getBook(inti)返回图书的引用,这一做法有两个好处,一是简化写法,二是增强程序的可读性。返回值是一个引用,可以直接操作原来的数据。-7-f.voidappendBook(char*bkNo,char*bkName,intbkNum)在线性表的末尾追加一条库存记录,在追加之前判断线性表是否已经满了,如果已经满了,则扩充线性表。g.voidalterBook(inti,intbkNum,boolflag=true)修改图书记录,根据图书的位置更改图书的数量,利用flag参数判断是增加还是减少。h.voiddeleteBook(inti)删除图书记录,参数为图书的位置。要完成这一功能更,只需要把后面所有的图书记录前移即可。i.voidshowAllBook()展示所有图书记录,同时每五个分一页,实现分页显示的功能只需要在i被5整除的时候暂停即可。j.voidreadFromFile(char*fileName)从文件导入书籍,调用appendbook的函数,如果出现重复书籍,则与原来的数据进行合并。如果没有添加.txt可以自动补全。k.voidwriteToFile(char*filename)向文件输出数据,和输入数据的格式相同。如果文件名中没有添加.txt可以自动补全。l.voidreverse()-8-逆置数组,降序的功能是通过把升序的数组你逆置实现的。m.voidsort(intchoice)排序数组,根据choice进行不同的排序选择。升序是分别通过冒泡法、插入法和选择法实现的。降序的功能是通过对升序后的数据逆置实现的。-9-四、函数调用关系图五、精选算法1.利用冒泡法对书号进行排序-10--11-2.利用选择法对书名进行排序-12-3.利用插入法对数量进行排序-13-六、源程序#includeiostream#includefstream#includeiomanip#includecstring#includecstdlibusingnamespacestd;classBook{charbkNo[10];//书号,字符串类型charbkName[20];//书名,字符串类型intbkNum;//数量,整型public:intgetNum()//得到库存量{returnbkNum;}voidsetNum(intbkNum)//得到数量{this-bkNum=bkNum;}voidsetData(char*bkNo,char*bkName,intbkNum)//设置书名、书号和数量{strcpy(this-bkNo,bkNo);strcpy(this-bkName,bkName);this-bkNum=bkNum;}voidshow()//展示这一条记录{coutsetw(10)leftbkNosetw(20)leftbkNamesetw(10)leftbkNumendl;}voidprint(ofstream&out)//向文件输出这一条记录{outsetw(10)leftbkNosetw(20)leftbkNamesetw(10)leftbkNumendl;}-14-friendclassBookDatebase;//将BookDatabase设置成友元,可以直接操作};classBookDatebase{Book*bkPtr;//Book型指针,用于数据的访问intcurLen,maxLen;public:BookDatebase(intn=10)//构造函数,初始化数组,将bookdata.txt中的数据导入{bkPtr=newBook[n];curLen=0;maxLen=n;readFromFile(bookdata.txt);}~BookDatebase()//析构函数,释放数组,将数据导出到bookdata.txt{writeToFile(bookdata.txt);delete[]bkPtr;}voidsetCurLen(inti)//设置现有的数据长度,在删除数据的时候会使用{curLen=0;}intisIn(char*bkNo)//判断数据库中是否存在这条记录,若存在,则返回位置,不存在,返回-1{for(inti=0;icurLen;i++)if(strcmp(bkPtr[i].bkNo,bkNo)==0)returni;return-1;}Book&getBook(inti)//返回图书的引用,可以直接通过返回值操作原来的数据{return*(bkPtr+i);}voidappendBook(char*bkNo,char*bkName,intbkNum)//追加图书,若重复,自动与原来的数据进行合并{if(maxLen==curLen)-15-{Book*newPtr=newBook[maxLen+10];for(inti=0;icurLen;i++){newPtr[i]=bkPtr[i];}maxLen+=10;delete[]bkPtr;bkPtr=newPtr;}getBook(curLen++).setData(bkNo,bkName,bkNum);}voidalterBook(inti,intbkNum,boolflag=true)//修改图书,根据flag参数判断是增加数量还是减少数量{if(flag)getBook(i).setNum(getBook(i).getNum()+bkNum);elsegetBook(i).setNum(getBook(i).getNum()-bkNum);}voiddeleteBook(inti)//删除图书,把后面的数据前移实现数据的删除{curLen--;while(icurLen){*(bkPtr+i)=*(bkPtr+i+1);i++;}}voidshowAllBook()//展示所有图书记录,每5个一页{for(inti=0;icurLen;i++){if(i%5==0){if(i)system(pause);system(cls);char*m[12]={-16-1.追加图书记录,2.删除图书记