基于C语言实现的宾馆住宿信息管理系统

primadonna

发布日期: 2018-11-06 11:36:30 浏览量: 3524
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

一、系统需求分析

本课程设计的名称为宾馆住宿信息管理系统。该系统能够处理宾馆运营过程中产生的客房分类信息、客房基本信息以及客人住宿信息。本系统包括三个主要功能模块:数据维护、数据查询以及数据统计,两个辅助功能模块:文件模块以及帮助模块,同时本系统还提供良好的人机交互界面,在程序运行时更会给予大量的提示帮助管理者更好的使用本系统,本系统还提供数据的存储功能,能够将系统运行时产生的数据存入到相应的数据文件中。

具体功能如下图1.1:

二、总体设计

  • 第一步:加载文件中存储的三类基本数据到系统内存中,将有关数据存入链表

  • 第二步:文本菜单界面初始化,包括主菜单的显示,子菜单弹出窗口的设计,相应鼠标操作的热区设置

  • 第三步:系统各个功能函数的选择和运行,该模块用到一个循环机制,当用户在子菜单中选择功能,调用相应的功能函数,若该功能函数返回一个返回值,该返回值作为循环的条件,若为TRUE,则函数执行完后清屏继续下一循环,若为FALSE,说明用户选择退出系统,退出循环,该模块结束

  • 第四步:处理退出系统后的数据,询问用户是否保存相关数据到文件中,清理系统内存,释放节点空间,关闭输入输出句柄

三、数据结构设计

3.1 客人基本信息链节点结构

  1. typedef struct hoteler_node {
  2. char ID_number[20]; /*身份证号*/
  3. char name[20]; /*客人姓名*/
  4. char hotel_number[6]; /*入住房间房间编号*/
  5. char time[18]; /*入住时间*/
  6. char exit_time[18]; /*退房时间,空串代表在住*/
  7. float day_num; /*入住天数,0表示在住*/
  8. float fee; /*应缴费用*/
  9. float charged; /*实缴费用*/
  10. struct hoteler_node *next; /*指向下一结点的指针*/
  11. }HOTELER_NODE;

3.2 客房基本信息链节点结构

  1. typedef struct room_node {
  2. char hotel_number[6]; /*房间编号*/
  3. char tel_number[20]; /*房间电话号码*/
  4. char type; /*房间类别,'2'表示双人间,'1'表示单人间,'T'表示豪华套间*/
  5. float area; /*房间面积*/
  6. float price; /*每日住宿单价*/
  7. char enroll; /*是否有客人入住,'y'or'n'*/
  8. struct hoteler_node *hnext; /*指向客人基本信息支链*/
  9. struct room_node *next; /*指向下一结点的指针*/
  10. }ROOM_NODE;

3.3 客房分类信息链节点结构

  1. typedef struct type_node {
  2. char type; /*客房类别,'2'表示双人间*/
  3. int max_number; /*最多入住人数*/
  4. int num; /*客房套数*/
  5. int unfilled_num; /*客房未住满套数*/
  6. struct room_node *rnext; /*指向客房基本信息支链*/
  7. struct type_node *next; /*指向下一结点的指针*/
  8. }TYPE_NODE;

3.4 屏幕窗口信息链节点结构

  1. typedef struct layer_node {
  2. char LayerNo; /*弹出窗口层数*/
  3. SMALL_RECT rcArea; /*弹出窗口区域坐标*/
  4. CHAR_INFO *pContent; /*弹出窗口区域字符单元原信息存储缓冲区*/
  5. char *pScrAtt; /*弹出窗口区域字符单元原属性值存储缓冲区*/
  6. struct layer_node *next; /*指向下一结点的指针*/
  7. }LAYER_NODE;

3.5 标签束结构

  1. typedef struct label_bundle {
  2. char **ppLabel; /*标签束字符串数组首地址*/
  3. COORD *pLoc; /*标签定位数组首地址*/
  4. int num; /*标签个数*/
  5. }LABEL_BUNDLE;

标签束信息包括标签字符串数组内容,标签位置,标签个数。用一个字符型的二重指针变量ppLabel指向标签字符串数组内容,用一个COORD类型的字符指针变量pLoc指向标签串数组输出时的首位置坐标,用整型变量num表示标签的个数。

3.6 热区结构

  1. typedef struct hot_area {
  2. SMALL_RECT *pArea; /*热区定位数组首地址*/
  3. char *pSort; /*热区类别(按键、文本框、选项框)数组首地址*/
  4. char *pTag; /*热区序号数组首地址*/
  5. int num; /*热区个数*/
  6. }HOT_AREA;

热区信息包括热区的位置,类别,序号及个数。因此用一个SMALL_RECT结构类型的指针变量pArea指向热区的定位范围;用字符指针变量pSort指向热区的类别类型,其中数字’0’表示按钮型热区,’1’表示文本框热区,’2’表示选项框热区;用字符指针变量pTag指向热区的序号,热区编号一般为1,2,3,4,5……这些自然数表示多个热区的排列顺序,整型变量num表示热区个数。

3.7 客房分类信息

中文字段名 类型及长度 举例
客房类别 char ‘2’ 双人间,’T’ 豪华套间
最多入住人数 int 2
客房套数 int 36
客房未住套数 int 12

3.8 客房基本信息

中文字段名 类型及长度 举例
房间编号 char[6] “10312” 一号楼312房间
电话号码 char[20] “02787541258-312”
房间类别 char ‘2’ 双人间
房间面积 float 23.5
每日住宿单价 float 238.0
是否有客人入住 char ‘y’ 已有客人入住 ‘n’ 未住

3.9 客人住宿信息

中文字段名 类型及长度 举例
身份证号 char[20] “420101198505050005”
客人姓名 char[20] “zhangming”
入住房间 char[6] “10312” 一号楼312房间
入住时间 char[18] “2008/03/05-13:00”
退房时间 char[18] “” 空串表示在住
入住天数 float 0 表示在住
应缴费用 float
实缴费用 float

3.10 三方向的十字链表

四、详细设计

数据保存见下图,其中p1、p2、p3分别为客房分类信息节点、客房基本信息节点、客人住宿信息节点,写入记录时分别写入对应的存储数据文件。

数据备份功能和数据保存功能类似,只不过在用fwrite函数写入文件记录时应该写入相应的备份数据文件。

数据恢复功能可拆解成两个子模块。第一个模块,创建链表,将备份数据文件中的数据加载到链表中,第二个模块,调用已有的数据保存功能,将链表中数据保存入存储数据文件中。其中,创建链表的流程图如下:为排版方便,图中简化了流程图,其中遍历主链为一个循环,从链表头指针遍历到尾指针,遍历支链也为一个循环语句,从主链的每一条支链的头指针遍历到尾指针直到结束或者发现满足条件的节点退出循环。其中h_t是链表节点成员hotel_number的缩写,即宾馆编号。

录入客房分类信息如下图,其中创建分类信息节点p1是通过用户输入对节点p1赋值,若主链表中不存在和录入节点中相同的分类信息,则将分类信息节点p1插入主链表的尾部,如果主链表中已经存在同样的分类信息,则输出提示。

修改客户分类信息如下图所示。

删除客户分类信息如下图所示。

录入客房基本信息如下图所示。

修改客房基本信息如下图所示。

删除客房基本信息如下图所示。

录入客人住宿信息如下图所示。

修改客人住宿信息如下图所示。

删除客人住宿信息如下所示。

按客房类别查询客房分类信息,遍历主链表,发现pType->type==type则输出结果。

按客房编号查询,按客房类别及客房单价查询客房基本信息,遍历二重链表,发现满足条件的则输出。

按客人ID,按客人住宿时间范围查询,遍历三重链表,发现满足条件的则输出相关信息。

数据统计模块中,客房总数与入住情况统计、各类客房年度各月份营业额统计以及统计所有信息都为基本的链表遍历,与查询功能类似,不再赘述。

按年份统计客房的入住率由于要考虑两个客人同时在住的情况,与链表遍历稍有点不同。在当前结点满足条件时,如果后续节点同时满足条件,应该减掉这部分入住天数,这样一来就不会出现重复统计入住天数的情况。

统计宾馆中住宿天数最多的10位客人住宿信息。用到一个结构数组用于排序,结构statistic中成员为要输出的客人信息。

五、运行测试与结果分析

系统欢迎界面,该界面用了一个时间暂延函数,让用户在刚打开的时候感觉有动画感。

数据加载模块,该模块用于将数据文件中的数据加载入链表中,并提示相关文件是否打开成功。

系统文本菜单界面初始化,包括主菜单的显示,系统名称的显示,以及系统时间动态显示:

子菜单的弹出窗口显示

录入客房基本信息,根据用户输入的类型是否已经存在弹出不同的提示框,若录入成功,会询问用户是否保存相关数据(与录入数据,修改数据,删除数据有关的操作之后都会询问用户是否保存),若遍历链表发现已经存在则弹出提示显示客房类型已经存在(录入客房基本信息以及客人住宿信息也是如此)。

修改客房分类信息,若链表中存在该客房类型,则由用户输入数据修改客房分类信息,若链表中不存在该客房分类信息,则弹出提示信息显示客房分类信息不存在(在之后的删除客房分类信息,修改客房基本信息,删除客房基本信息,修改客人住宿信息,删除客人信息也是如此)。

删除客房分类信息

录入客房基本信息

修改客房基本信息

删除客房基本信息

录入客人住宿信息

修改客人住宿信息

删除客人住宿信息,在链表中查找输入作为身份证号子串的节点,比如我输入198,会依次显示满足条件的客人信息(只列出两个满足的截图),然后询问用户是否删除:

按客房类别查询客房分类信息

按客房编号查询客房基本信息

按客房编号和每日住宿单价查询客房基本信息

按客人身份证号查询客人住宿信息

按客人姓名模糊查询

按客人入住时间范围查询客人基本信息,逐个显示,用户按下回车,清屏,显示下一个满足条件的客人信息

各类客房数目统计(按ASCIL码排序)

各类客房年度各月份营业额统计(由于不确定客房分类的数量,因此没有直接选择居中输出,由于录入数据较少,表单中较多项为0):

统计所有客房的营业额,入住天数,折扣:

统计所有信息(包括客房分类信息,客房基本信息,客人住宿信息,该模块的功能更倾向于程序测试,测试数据维护功能模块中的录入,修改以及删除):

数据保存,数据保存之前我们先选择录入客人住宿信息,然后选择数据保存,退出系统,重新登入系统,查询客人住宿信息:

数据备份,备份后备份数据文件大小应该和数据文件相同

数据恢复,在确保数据备份的情况下,选择清空链表信息、数据保存、数据恢复(图中的时间说明没有足够的时间录入完全相同的数据):

六、总结

刚开始写课设的时候,看着老师写的任务书完全没有思路,因为我们平时写的C语言程序都是一些简单的字符串处理、简单的数学运算以及一些简单的排序,界面也是系统默认的DOS黑框框控制台界面,从来没有尝试过写带有菜单的文本菜单界面,所以拿到课程设计任务书时候完全是一头雾水,一点头绪都没有,连一个头文件都写不出来,又由于暑假期间时不时的就有一些鸡毛蒜皮的小事叨扰,静不下心来写课程设计,索性就先把他放到了一边,可是总是得做的啊,等到只有半个月的时候,我自己算了一下,如果课设要写3000行的话,半个月我每天至少要写200行代码,我在联想一下之前写的最长的代码,也就是结构实验的那次,再想一下自己的码代码速度,我就知道自己要好好研究课设了,我首先问了上一届的学长怎么做的,他们说看看那本课程设计的书,所以我就把那本课程设计的书拿出来,把他课程设计部分从头看到尾,上面的代码一行一行的敲上去,隐约知道了怎么显示文本菜单界面,什么是弹出窗口,什么是控制台函数,什么是控制台程序,有了这些东西我课设剩下的部分我就感觉可以自己来写了,因为平时也经常训练,可是真正自己要写的时候,刚开始的时候一行代码也写不出来,为什么?因为缺乏系统性、逻辑性以及连贯性,所以我就先不着急写出代码,不着急实现我的功能,我先在纸上画一画我大概需要做的工作,怎么样把几大模块实现,有没有什么地方需要特殊的算法,有没有那些地方是知识盲区技术盲区,怎么根据改变的数据项来关联其他数据项。想好了这些写代码终于快了起来,也很快把整个系统写了出来。

写代码的时候有一个技术盲区就是文件操作,因为系统的数据要保存在硬盘文件中,你不可能让用户一直开着系统一直用内存把数据养起来,你要确保用户每次打开系统里面的数据都是上次它使用时的数据,所以就需要数据保存相关功能。可是平时上课的时候对文件这章节是比较陌生的,只知道有这回事,却没怎么用过,所以为了验证怎么操作文件,怎么用那些文件操作函数,我特意写了几个测试程序,测试fopen,fwrite,fread,write,read,feof,fclose这些函数,其中有意思的是,我一直不知道fclose的重要性,一直以为这个fclose是可有可无的,然而事实上不是,如果不fclose的话,你这个文件再用其他文件操作函数打开的话它的文件指针没有重新只想文件头,会引发一连串不妙的结果,因为这个东西Debug真的是不容易的。

知乎上有一句话是这样子说的:80%的程序员把80%的时间花在Debug上,这确实是的。系统写完了,但是不代表课设就完了,你写的代码里隐藏着许许多多意想不到的bug,你要一一的去测试他们,如果没有bug那当然好,最可怕的是有bug,可能一个bug你会花上很多时间而毫无结果,那么这个时候怎么办?我学到的方法就是printf或者重构,说实话,现在很多IDE都支持强大的调试功能,变量,指针,堆栈这些功能应有尽有,那为啥还要用printf呢,主要是因为printf是直接输出在屏幕上,你不用去和程序运行状态一一比对,你很清楚那些地方是按照自己的思路进行的,那些地方是出乎自己预料的,知道了这些,就会简单很多。那万一你是在解决不了眼前的bug那怎么办?那说明你在思考这个问题的时候思路错了,还不如把这一段代码删除,重构,换一种思路重新写,重写一段代码可能要比花在调试上的时间少得多得多。

另外一个收获就是,当要写的代码数量较多时,应该尽量采用模块化设计,函数式设计,尽量不要使不同模块之间发生交互,这样做的好处是显而易见的:

  • 易于调试

  • 便于修改

  • 便于测试

做出来的程序总是觉得很丑,我特别想做一个输入输出框出来改善程序交互体验,看了老师写的那些函数自己动手写了一个出来,可是为什么不让他运行的,因为我做出来的这个输入输出框不是一个通用的函数,他只能根据特例来写,如果这样子写会增加庞大的代码量,可能自己现在的code水平和理解能力还是不行,所以还是挺有挫败感的。还有写完之后也去看了看Windows程序设计的书,想用Windows API写图形界面,但是时间上来不及而且Windows API函数太多,看的书也是以前的旧书,用现在的编译器一编译满天飞的error,看着满天飞的error,上网去找解决方案,好不容易弄懂了那些数据结构,什么是回调函数,有哪些消息队列,怎么写菜单,可是问题又来了,如何在短时间内把我在DOS文档界面下写的功能模块代码迁移到图形界面呢?这显然是短时间内完不成的,现在想来还是挺后悔的,一开始定的目标太低了,如果我刚开始就决定写图形界面,静下心来好好啃一啃,应该是能够做出更加好看的系统的。

上传的附件 cloud_download 基于C语言实现的宾馆住宿信息管理系统.7z ( 2.19mb, 469次下载 )
error_outline 下载需要9点积分

发送私信

生活就像骑自行车,只有不断前进,才能保持平衡

25
文章数
16
评论数
最近文章
eject