1、南京航空航天大学 C+ 语言程 序设计课程设计报告 题目: 图 书库存 管理 班级: 0116202 学号: 011620231 姓名: 苏瑞辅 成绩: 指导教 师: 潘梅园 日期:2017 年 5 月 18 日 - 1 - 目录 一、 程序功能 - 2 - 二、 新增功能 - 3 - 三、 数据结构 - 5 - 四、 函数调用 关系 图 - 9 - 五、 精选算法 - 9 - 六、 源程序 - 13 - 七、 典型测试 数据 - 24 - 八、 问题的处 理方 法 - 35 - 九、 做课程设 计作 业的感受 - 36 - - 2 - 一、 程序功能 1. 追加图 书记录 输入书号 、 书名
2、 和 库存量, 在库存 列 表尾部追 加一条 记 录。 此功 能每次只 能追加 一 本图书记 录,用 于 初期建立 库存记 录 。 2. 删除图 书记录 输入一本 书的书 号, 首先在库 表中查 询 该图书是 否存在, 若 存在, 则显示该 图书记 录 , 并提问 是否删 除 该图书, 根据回 答 (y/n)确 定是否删 除该图 书 ;若不存 在,提 示 该书不存 在。 3. 显示所 有图书记录 每行显示 一本图 书 记录信息 。 4. 查询图 书 输入一本 图书的 书 号, 查询 该书是 否 存在, 若 存在, 则 显示该书 记录信息 ,否则 提 示该书不 存在。 5. 图书入 库 输入一本
3、 书的书 号 , 查询该 书是否 存 在, 若存 在, 则 修 改已有图 书记录的 库存量 ; 若不存在 ,则追 加 一条图书 记录。 6. 图书销 售 输入一本 书的书 号 及销售数 量。 若该 图 书存在, 并 且库存 量 充足, 则修改库 存量; 否 则提示该 书不存 在 或库存不 足等信 息 。 - 3 - 7. 批量导 入图书记录 用户输入 一个文 件 名, 系 统自动 地讲 该文件中 的图书 记 录追加到 库存列表 中,从 而 实现批量 导入图 书 。 8. 导出图 书记录 提示用户 输入一 个 文件名 , 系统 自动 将库存表 中的全 部 图书记录 信息写入 该文件 正 文,文件
4、 格式与 上 述导入文 件格式 相 同。 9. 排序 提供六种 排序的 选 择, 分别对 三个关 键字按升 序或降 序 排列。 使 用了冒泡 法、选 择 法和插入 法几种 排 序方法。 10. 删除全 部图书记录 提示用户 是否确 认 (y/n), 确 认后 删 除全部图 书记录 。 0. 退出 提示用户 是否确 认 退出 (y/n ) , 退出时 将数据导 出到 bookdata.txt. 二、 新增功能 1. 增加数 据检查机制,防止 添加重复数据 (1) 菜单一( 追加图 书 记录) 追加图书 记录的 时 候先判断 是否有 该 记录,如 果已经 有 的话, 则自动与 原来的 数 据进行合
5、 并, 即进 行入库操 作, 并向 用户提 示“与原 来的数 据 进行了合 并” 。 - 4 - (2) 菜单五( 批量导 入 图书记录 ) 批量导入 图书记 录 实际上就 是对追 加 图书记录 的批量 操 作, 同 样需要数 据检查 机 制, 以 防止数据 重 复。 在 本程序中 , 对每一 个批量导 入的数 据 进行检查 , 如 果出 现重复 , 则自 动与 先前的 数据进行 合并。 (3) 系统初始 化的时 候 会自动地 从 bookdata.txt 中导入数 据, 虽然 这个数据 中有重 复 数据的可 能性比 较 小 (因为我 们是导 出 的数 据,而 这个 数据 用 户是看 不到 的
6、, 对 用户来 说是 透明 的) ,但 是为了避 免错位 , 同样加入 数据检 查 机制, 具体操 作和 菜单五 的相同。 2. 丰富排 序功能 (1) 在课本上 的按书 号 排序的基 础上, 本 程 序拓展出 了六种 排 序的 方案,即 分别对 书 号、书名 和数量 进 行升序或 降序排 列 。 (2) 本功能的 子菜单 设 计与主菜 单的设 计 思想相同 。 (3) 对书名、 书 号和数 量 三个关键 字进行 升 序排列分 别使用 了 冒泡 法、选择 法和插 入 法。 (4) 在对书号、 书名和 数 量进行降 序排列 的 时候所采 用的方 法 是对 先前升序 排列的 结 果进行逆 置(时
7、间 换空间 ) 。 3. 查询图 书时候的分页功能 查询所有 图书的 时 候每 5 条 记录一 页 显示, 按任意 键后 显示下一 - 5 - 页。 4. 输入文件的名字如果不包含.txt 则自动添加,通过 return_file_name 函 数实现 。 三、 数据结构 1. BOOK 类 (1) 私有数据 成员 a. char bkNo10 /书 号,字 符数组 b. char bkName20 /书 名,字 符数组 c. int bkNum /库 存量, 即数量 (2) 公有成员 函数 a. int getNum() /获取 库存量 b. void setNum(int bkNum) /
8、设置 库 存量 c. void setData(char *bkNo, char *bkName, int bkNum) / 写入库 存信息 d. void show() /显 示一本 图书信 息 e. void print(ofstream / 通过 设置此 友元,使 访问变 得 更容 易,但是 类的隐 蔽 性也被破 坏。 - 6 - 2. BookDatebase 类 (1) 私有数据 成员 a. Book *bkptr /Book 型的指针 b. int curLen, maxLen / 线性表的最 大长度 和当前长 度 (2) 公有成员 函数 a. BookDatebase(int n
9、 = 10) 构造函数 , 用来 初 始化线性 表。 并 从 bookdata.txt 中 导入数 据。 b. BookDatebase() 析构函数 , 用来 释 放线性表 。 并把 数 据导出到 bookdata.txt. c. void setCurLen(int i) 设置现在线性表的长度,在删除全部数据的时候会 用到这 个函数。 d. int isIn(char *bkNo) 判断书籍记录是否存在,此功能使用频率较高,主 要作用 是数据检 查,防 止 出错。 e. Book class Book char bkNo10; / 书 号,字符串类 型 char bkName20; / 书
10、 名,字符串类 型 int bkNum; / 数 量,整型 public: int getNum() / 得 到库存量 return bkNum; void setNum(int bkNum) / 得 到数量 this-bkNum = bkNum; void setData(char *bkNo, char *bkName, int bkNum) / 设 置书名、书号 和数量 strcpy(this-bkNo, bkNo); strcpy(this-bkName, bkName); this-bkNum = bkNum; void show() / 展 示这一条记录 cout setw(10)
11、 left bkNo setw(20) left bkName setw(10) left bkNum endl; void print(ofstream - 14 - friend class BookDatebase; / 将BookDatabase设置成友元, 可以直接操作 ; class BookDatebase Book *bkPtr; /Book 型指针,用 于数据的访问 int curLen, maxLen; public: BookDatebase(int n = 10) / 构 造函数,初始 化数组,将bookdata.txt 中 的数据导入 bkPtr = new Book
12、n; curLen = 0; maxLen = n; readFromFile(“bookdata.txt“); BookDatebase() / 析 构函数,释放 数组,将数据 导出到bookdata.txt writeToFile(“bookdata.txt“); deletebkPtr; void setCurLen(int i) / 设 置现有的数据 长度,在删除 数据的时候会 使用 curLen = 0; int isIn(char *bkNo) / 判 断数据库中是 否存在这条记 录,若存在, 则返回位置, 不存在,返回 -1 for (int i = 0; icurLen; i+
13、) if (strcmp(bkPtri.bkNo, bkNo) = 0) return i; return -1; Book void appendBook(char *bkNo, char *bkName, int bkNum) / 追 加图书, 若重复, 自 动与原来 的数 据进 行合并 if (maxLen = curLen) - 15 - Book *newPtr = new BookmaxLen + 10; for (int i = 0; icurLen; i+) newPtri = bkPtri; maxLen += 10; deletebkPtr; bkPtr = newPtr;
14、 getBook(curLen+).setData(bkNo, bkName, bkNum); void alterBook(int i, int bkNum, bool flag = true) / 修 改图书 , 根据flag 参 数判断是 增加 数量 还是减少数量 if (flag) getBook(i).setNum(getBook(i).getNum() + bkNum); else getBook(i).setNum(getBook(i).getNum() - bkNum); void deleteBook(int i) / 删 除图书,把后 面的数据前移 实现数据的删 除 cur
15、Len-; while (icurLen) *(bkPtr + i) = *(bkPtr + i + 1); i+; void showAllBook() / 展 示所有图书记 录,每5 个一页 for (int i=0; icurLen; i+) if (i%5=0) if (i) system(“pause“); system(“cls“); char *m12 = - 16 - “1. 追加图书记 录“, “2. 删除图书记 录“, “3. 显示所有图 书记录“, “4. 查询图书“, “5. 图书入库“, “6. 图书销售“, “7. 批量导入图 书“, “8. 导出图书记 录“, “
16、9. 排序“, “10. 删除全部图 书记录“, “0. 退出“, NULL ; cout n; - 17 - while (n-) indata bkNo bkName bkNum; if (i = isIn(bkNo) = -1) appendBook(bkNo, bkName, bkNum); else alterBook(i, bkNum); indata.close(); void writeToFile(char *filename) / 把 数据写入到文 件,没有.txt 的时候可 以自动加上 ofstream outdata; outdata.open(filename); o
17、utdata curLen endl; for (int i = 0; icurLen; i+) getBook(i).print(outdata); outdata.close(); void reverse() / 数 组的逆置,在 降序排序的时 候会用到 Book temp; for (int i = 0; i curLen -1 - i; i+) temp = getBook(i); getBook(i) = getBook(curLen - 1 -i); getBook(curLen -1 - i) = temp; void sort(int choice) / 数 组排序,根据ch
18、oice 判断排 序方法 Book temp; int i, j; switch (choice) case 1: case 4: for (i = 1; icurLen; i+) for (j = 0; jcurLen - i; j+) if (strcmp(getBook(j).bkNo, getBook(j + 1).bkNo) = 1) - 18 - temp = getBook(j); getBook(j) = getBook(j + 1); getBook(j + 1) = temp; if (choice = 4) reverse(); break; case 2: case 5
19、: for (i = 0; i0; j-) if (getBook(j - 1).bkNumgetBook(j).bkNum) temp = getBook(j - 1); getBook(j - 1) = getBook(j); getBook(j) = temp; if (choice = 6) reverse(); ; void appendRecord(BookDatebase - 19 - char bkName20; int bkNum, i; cout bkNo bkName bkNum; if (i = bkdb.isIn(bkNo) = -1) bkdb.appendBook
20、(bkNo, bkName, bkNum); cout bkNo; if (i = bkdb.isIn(bkNo) = -1) cout flag; if (flag = y) bkdb.deleteBook(i); cout “ 删 除了一条记录“ endl; else cout “ 取 消了删除操作“ endl; void showAllRecord(BookDatebase void query(BookDatebase int i; cout bkNo; if (i = bkdb.isIn(bkNo) = -1) cout bkNo bkNum; if (i = bkdb.isIn(b
21、kNo) = -1) cout bkName; bkdb.appendBook(bkNo, bkName, bkNum); cout “ 增加 了一条记录“ endl; else bkdb.alterBook(i, bkNum); cout “ 成 功入库“ endl; void sellBooks(BookDatebase int bkNum, i; - 21 - cout bkNo bkNum; if (i = bkdb.isIn(bkNo) = -1) cout fileName; return_file_name(fileName); bkdb.readFromFile(fileNam
22、e); void writeToFile(BookDatebase cout fileName; return_file_name(fileName); bkdb.writeToFile(fileName); void sort(BookDatebase - 22 - char *menu = “1. 按书号排 序( 升 序)“, “2. 按书名排 序( 升 序)“, “3. 按数量排 序( 升 序)“, “4. 按书号排 序(降序)“, “5. 按书名排 序(降序)“, “6. 按数量排 序(降序)“, NULL ; for (int i = 0; menui; i+) cout choic
23、e; bkdb.sort(choice); void delAllRecord(BookDatebase cout flag; if (flag=y) bkdb.setCurLen(0); int menu_select() / 菜 单的选择 char *m12 = “1. 追加图书记 录“, “2. 删除图书记 录“, “3. 显示所有图 书记录“, “4. 查询图书“, “5. 图书入库“, “6. 图书销售“, “7. 批量导入图 书“, “8. 导出图书记 录“, “9. 排序“, “10. 删除全部图 书记录“, “0. 退出“, NULL ; int i, choice; - 23
24、 - do system(“cls“); cout choice; cout 10); return choice; int main() BookDatebase bkdb; int sel; char flag; while (1) switch (sel = menu_select() case 1: appendRecord(bkdb); cout flag; if (flag != y) / 如 果是y 的 话,则退出; 如果是 其他的话,则 结束本次循环 ,不能 退出 continue; - 24 - if (sel = 0) break; return 0; 七、 典型测试数据
25、1. 数据的 初始化 / 由此可见初始化完成 ,数据库(bookdata.txt )中的数据被成功导入。 2. 插入数 据 (1) 当插入的 数据不 存 在时 - 25 - 可见牛 津高阶 英 语词典 被成功 插 入。 (2) 当插入的 图书已 经 存在时 大学物 理与 原 有记录进 行了合 并 ,而没有 插入新 的 记录。 3. 删除图 书记录 - 26 - 如图所示 ,书号为 01 的书已 经被成 功 删除 4. 显示所 有图书记录 (这个功能 已经多 次 展示,但 分页显 示 的功能还 没有展 示) 这是第一 页 这是第二 页 每五个分 一页, 这 个功能测 试成功 。 - 27 - 5
26、. 查询图 书 如图,书 号为 04 的 图书已经 被成功 找 到并显示 出来。 6. 图书入 库 如图 大 学物理 已经被成 功入库 100 本。 (不 要问我 刚 才不是已 经 入了一次 了吗, 中 间不小心 把程序 的 运行窗口 关了, 老 师) - 28 - 如果记录 不存在 的 话,会自 动提示 输 入书名和 书号。 7. 图书销 售 如图,库 存不足 的 话会有提 示 如图,不 存在的 话 会有提示 - 29 - 如图,销 售了 50 本 大学物 理 ,只剩 下 56 本了。 8. 批量导 入图书记录 这是我准 备的文 件 。1.txt 为了验证程序可以合并相同的数 据,我故意写了
27、一 个已经存在的 数 据, 大学物 理 因为我的 程序可 以 自动的补 全.txt,所 以我只输 入了 1. - 30 - 结果不仅 合并了 大 学物理 这条数 据, 而且还新 增了两 条 数据, 中 国历史 和世 界 历史 。 9. 批量导 出数据 当输入文 件名的 时 候只输入 2, 而没有 txt 的 时候 文件被成 功导出 - 31 - 当输入文 件名的 时 候输入 3.txt 的时 候, 带.txt 文件也被 成功导 出 由此可见 ,我的 文 件名的处 理算法 是 可以经受 考验的 。 10. 排序 我的排序 菜单里 面 有 6 个子 菜单。 - 32 - 为了节省篇幅,我一次把几次
28、排序的结果列出来, 为了避免混乱 , 只列出每 次排序 后 的第一页 (我 这个 程序在输 出的时 候 会自动分 页, 前面已经 提到过 了) 。 - 33 - 显然,都 已经按 照 要求进行 了排序 。 - 34 - 11. 退出并 导出图书记录 显然,退 出之后 数 据被正确 的导出 到 了数据库 文件中 。 12. 删除全 部图书记录 这一个得是最后一个进行测试, 因为这一个测试了 ,别的就没有 办 法测试了 ,好了 , 开始吧。 - 35 - 数据库中 已经没 有 了任何数 据,测 试 通过。 八、 问题的处理方法 这次做课程设计的 过程中,遇到了很 多自己不会的问题 。但是 最后还是
29、一 一解决 了。我在写 这个程 序的过程中 解决问 题的主要用 到了如下 的方法 。 1. 一般情况 下都是 自 己的知识 不扎实 , 这个时候 我会去 查 一下书 , 温习一下 遗忘的 知 识点。 2. 如果还是 不能解 决 , 我就会去 百度一 下, 看看有 没有人 遇到相通 的问题, 看看别 人 是怎么解 决的问 题 。 3. 当然,我 还有很 多 16 院的 同学, 我可 以向他们 咨询一 下 ,毕竟 他们学得 时间长 一 些。 4. 最后, 如 果问题 是 在过于复 杂, 不 能 解决。 我 就会去 我 们学校的 C+ 同学交流群里面去求助,这是一个学生们自发组织起来的 C+交流 群,我 在 里面提问 一般都 是 有同学给 我解答 的 。 - 36 - 九、 做课程设计作业的感受 做课程设 计的过 程 中我学会 了一个 道 理, 就 是万事 万物都 要从脚下 出发, 不能眼 高手 低。 一 个库存 管理 系统看似 简单的 功 能, 可 是在做 得 时候也不 见得是 信 手拈来 , 还是 会遇到 很多的问 题, 还是需 要反复调 试。 我想无论 是做事 还 是做人 , 心都 要要 宁静, 不能浮 躁。 要沉下心 来 认真地去 做每一 件 事情,这 样才能 做 到最好。