目录
前言. 1
正文. 1
1 课程设计分析. 1
1.1 课程设计的教学目的和任务. 1
1.2 课程设计的主要内容. 2
2问题描述及基本要求. 2
3 可行性分析. 3
3.1 技术可行性分析. 3
3.2 可用性分析. 3
4 系统功能介绍. 3
4.1 管理员拥有的功能. 3
4.2 学生拥有的功能. 3
5 算法思想. 4
6 模块划分. 4
6.1 单链表的实现. 4
6.2 单链表的遍历操作. 5
6.3 单链表的查找操作. 5
6.4 单链表的插入操作. 5
7 算法的时间复杂度分析. 6
8 系统流程图. 6
9 算法测试. 6
10 小结. 7
参考文献. 8
前言
在当今这个教育发展迅速的社会上,越来越多新的学校建立起来了。由于学校的地点问题,导致很多的学生不得不住在学校,而学校要想容纳那么多的学生住在学校,就必须建筑宿舍,随着住宿的学生数量增多,学生住宿的问题就出现了,怎样快速安排学生的宿舍房间与床位,记录学生的宿舍号还有对应的床位号,这些对于人工来说是特别麻烦的,所以如果有一个能管理学生宿舍的系统就很好了,这个系统有利于学校管理学生的住宿问题,也有利于宿舍的管理。
这个宿舍管理系统应用的地方有很多,还要有宿舍的单位都可以引进这个系统,宿舍管理系统对于宿舍管理员管理住宿人员的住宿问题很方便,所以这个系统的开发很有必要。
本次设计的“宿舍管理系统”的设计方法是采用C++语言来编写此系统,此系统的主要内容有查看宿舍住宿情况、添加住宿人员、删除住宿人员、修改住宿人员信息等功能,这些功能基本包括了宿舍管理系统所需要的功能。经过上网搜集资料、自己动手整理以后此次课程设计终于设计成功。
正文
1 课程设计分析
1.1 课程设计的教学目的和任务
(1)使学生进一步理解和掌握所学的各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序中的使用方法。
(2)使学生初步掌握软件开发过程的问题定义、分析、设计、编码、测试、调试等基本方法和基本技能。
(3)使学生掌握查询计算机资料以及有关参考资料,并提高学生程序设计的基本能力。
(4)使学生能用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。
1.2 课程设计的主要内容
(1) 问题分析和任务定义
根据课程设计的要求,充分的分析和理解所要设计题目的问题,明确问题的要求是什么?限制条件是什么?
(2) 逻辑设计
对设计题目的问题描述中涉及的对象定义对应的数据类型,并按照以数据结构为中心的原则划分模块,定义主程序模块和各抽象数据类型。逻辑设计的结果应写出每个抽象数据类型的定义,各个主要模块的算法,并画出模块之间的调用关系图。
(3) 物理设计
定义问题相应的存储结构并写出该设计各函数的伪代码算法。在这个过程中,要综合考虑系统功能,使得系统结构清晰、合理、简单和易于调试,抽象数据类型的实现尽可能做到数据封装,基本操作的规格说明尽可能明确具体。详细设计的结果是对数据结构和基本操作作出进一步的求精,写出数据存储结构的类型定义,写出函数形式的算法框架。
(4)程序编码
把详细设计的结果进一步求精为程序设计语言程序。同时加入一些注解和断言,使语言程序中逻辑概念清楚。
(5) 程序调试与测试
采用自底向上,分模块进行,即先调试低层函数。能够熟练掌握调试工具的各种功能,设计测试数据确定疑点,通过修改程序来证实它或绕过它。调试正确后,认真整理源程序及其注释,形成格式和风格良好的源程序清单和结果。
(6) 结果分析
分析程序运行结果包括正确的输入及其输出结果和含有错误的输入及其输出结果。并且分析算法的时间、空间复杂性。
2问题描述及基本要求
由于现在学校学生宿舍管理的工作通常为手工操作,使得工作人员在管理宿舍中耗费时间长,工作效率也很低。因此,为了提高学校学生宿舍管理的效率,减轻学校有关工作人员的工作负担,决定进行本次课程设计,开发学生宿舍管理系统。本次课程设计的主要目的是为学校学生管理提供快捷方法,为教育人员或工作者节省大量需要手工登记的操作,对学生公寓情况进行及时跟踪管理,提高管理学生宿舍的效率,推动使学生宿舍管理自动化。
基本要求是以单链表的存储方式存储学生的学号,姓名、班级、宿舍号等信息,并且可以用单链表的插入、查找、删除等操作来实现系统添加新的学生信息,或者删除不住宿的学生信息,也可按照学生的某一项信息进而查找这个学生的所有信息。也可以利用单链表的遍历操作来实现查看系统中存储的所有学生的信息。因为所学知识的限制,所以此系统设计的功能少,这是我们的缺点,这个缺点有待改进。
3 可行性分析
3.1 技术可行性分析
技术可行性的分析是要考虑到将来可能用到的硬件以及软件方面的需求是否满足用户的需要,由于现在科技发展迅速,计算机网络技术和数据库技术已发展成熟,并且系统的很多开发技术都已经渐渐走向成熟,加上现在社会上这种类似的系统成功开发案例也有很多,所以,事实证明,此系统的开发是可行的。
3.2 可用性分析
“学生宿舍管理系统”对于学校管理学生宿舍是很方便的,可以提高宿舍管理效率,还有这个系统对于学校其他方面的工作不会有影响,而且现在学校的老师们的综合素质都比较高,所以对于宿舍管理系统的使用不会有任何的阻拦,再加上如果此系统如果真能开发出来,能达到预期的效果,我相信学校的领导也会大力支持此系统在学校范围内使用,所以综上所述,宿舍管理系统的是可用的。
可行性分析结论:此系统的成功开发将进一步促进学校管理的现代化与自动化,也为学校能全面自动化管理积累了经验,更通过一系列的分析,从长远的立场上看,此系统的开发还是很有必要的。
4 系统功能介绍
4.1 管理员拥有的功能
管理员可以在此系统添加或删除学生信息,按姓名、学号、班级、宿舍号查找学生信息。
4.2 学生拥有的功能
学生只能在此系统中按姓名、学号、班级、宿舍号查找学生的信息。
5 算法思想
本次课程设计的题目是“学生宿舍管理系统”,此系统的算法思想是是利用了单链表存储的思想。其中在单链表中存储了学生的多种基本信息以及利用单链表的查找操作可以使系统按照姓名、学号、班级、宿舍号查找学生信息的函数,还有利用单链表的遍历操作使系统输出学生信息,利用单链表的删除操作来删除系统中的学生信息。这些系统的功能都是在单链表的基础上实现的。
单链表是用一组任意的存储单元存放线性表的元素,这组存储单元可以连续也可以不连续,甚至可以零散分布在内存中的任意位置。为了能正确表示个元素之间的逻辑关系,每个存储单元在存储数据元素时,还必须存储其后级元素所在的地址信息,这个地址信息成为指针,这两部分组成了数据元素的存储映像,称为结点。结点的结构如下图所示:
图 1单链表的结点结构
其中,data是数据域,用来存放数据元素;next是指针域,用来存放该节点的后继结点的地址。
6 模块划分
6.1 单链表的实现
单链表的基本思想就是用指针表示结点之间的逻辑关系,在单链表中,设一个结点为p,则结点p由两个域组成:存放数据元素的部分和存放后继结点地址的指针部分,分别用p->data和p->next来标识,且它们各有各自的值:p->data的值是一个数据元素,p->next的值是一个指针。单链表是由头指针唯一制定,整个单链表的操作必须从头指针开始进行。在本次课程设计的系统中,p->data的值是学生的学号、姓名、班级和宿舍号,p->next的值是下一位同学的基本信息。
图 2指针与结点之间的关系
6.2 单链表的遍历操作
所谓遍历单链表是指按序号依次访问单链表中的所有结点且仅访问一次。在此系统中,用单链表的遍历操作来实现系统输出全部学生的信息。这里可以设置一个工作指针p先指向头结点,然后依次指向其他学生结点,直到指针指向空为止,当指针p指向某学生结点时输出该学生结点的数据域。
图 3遍历单链表的操作示意图
6.3 单链表的查找操作
单链表的查找操作可以分为两种方法:一个是按位查找,另一个是按值查找。本次课程设计中运用的是单链表的按值查找。
按位查找:在存储学生信息的单链表中,即使知道被访问结点的位置i,也不能像顺序表那样直接按序号访问,只能从头指针出发顺next域逐个结点往下搜索。当工作指针p指向某结点时判断是否为第i个结点,若是,则查找成功;否则,将工作指针p后移。对每个结点依次执行上述操作,直到p为NULL时查找失败。查找算法的基本语句是工作指针p后移,该语句执行的次数与被查结点在表中的位置有关。在查找成功的情况下,若查找位置为i(1<=i<=n),则需要执行i-1次,等概率情况下,平均性能为O(n)。
按值查找:在单链表中实现按值查找操作,需要对单链表中的元素依次进行比较,如果查找成功,返回元素的序号,如果查找不成功,返回0表示查找失败。按值查找的基本语句是将结点p的数据域与待查值进行比较,具体的比较次数与待查值结点在单链表中的位置有关。在等概率情况下,平均时间性能为O(n)。
其伪代码如下:
执行选项2: //按学号查找
cout<<"请输入学生的学号:";
输入学生的学号;
输入错误:
cout << "你输入的学号不正确,请输入一个不超过八位数的学号" << endl;
cout << "学号:";
继续输入
输入正确:
输入该学生全部信息
没有该学号:
cout << "没有找学号为:"<< stu_num <<"的学生记录!" << endl;
返回初始界面;
执行选项3: //按宿舍号查找
cout<<"请输入宿舍号:";
输入正确:
输出该宿舍号所有学生的信息;
没有该宿舍号:
cout << "没有找到宿舍为:"<< house_name <<"的学生记录!" << endl;
返回初始界面;
执行选项4: //按姓名查找
cout<<"请输入学生姓名:";
输入学生姓名 ;
输入正确:
输出该学生所有信息;
没有该学生:
cout << "没有找到姓名为:"<< stu_name <<"的学生记录!" << endl;
返回初始界面;
执行选项5: //按班级查找
cout<<"请输入班级名称:";
输入学生班级 ;
输入正确:
输出改班级所有学生信息;
没有改班级:
cout << "没有找到该班级为:"<< class_name <<"的学生记录!" << endl;
返回初始界面;
6.4 单链表的插入操作
单链表的插入操作是将值为x的新结点插入到单链表的第i个位置,即插入到ai-1与ai之间。因此,必须先扫描单链表,找到ai-1的存储地址p,然后生成一个数据域为x的新结点s,将结点s的next域指向结点ai,将结点p的next域指向新结点s,从而实现三个结点ai-1、x、ai之间的逻辑关系的变化,而本次课程设计用到单链表的插入方法是头插法:头插法是每次将新申请的结点插在头结点的后面,其执行过程如图所示:
7 算法的时间复杂度分析
通过对单链表存储、查找、删除等操作的分析,再结合此系统联系实际,得出此系统平均时间复杂度为T(n)=O(n).
8 系统流程图
根据系统所要满足的功能以及算法,画出该系统的流程图。
流程图如下:
图 4系统流程图
9 算法测试
算法一经测试,就会进入初始界面,系统初始界面如下:
图 2系统初始界面
根据你输入的选择,系统会做出相应的运算,在测试中我们首先在初始界面键盘输入数字1,而输入数据的学生基本信息为学号:12345678,姓名:张三,班级:计算机17,宿舍号:520,得出的结果如下图所示:
图 3系统测试图
将得出的测试图与预计效果图一对比,得出的结果一致,说明本次课程设计的学生宿舍管理系统成功。
10 小结
本次课程设计历经了两个星期,在这两个星期刚开始的几天里,我并没有把这次课程设计当回事,所以当老师说让我们选题目的时候我并没有立马就去选题目,我却是用玩度过了这宝贵的时间,当班上的同学把题目都选好的时候,并且已经准备开始做课程设计的时候,我也没有着急,当老师说要上交题目的时候,我才随便在书上选了一个别人没有选的题目上交了,就当在敷衍老师。可是当我在真正开始做本次课程设计的时候我却无从下手了,一点思路都没有,当时我想从网上搜一篇关于课程设计的论文复制一下到我的说明书上,结果老师说这次课程设计的说明书要查重的,查重的相似度不能超过35%,还要进行答辩,当时我就慌了,因为我真的对于这次课程设计没有做任何的准备,甚至连书上的知识我都没有看,我真的不知道该怎么办。
也就是说这个历经两个星期的课程设计,我第一个星期是玩过来的,到了第二个星期我才意识到这次设计的重要性,这时候我在书上查看了有关的知识,到网上搜集了一些资料,看到了一个关于“学生宿舍管理系统”的题目,这时我的脑袋里灵光一闪,我决定做这个“学生宿舍管理系统”。于是我从第二个星期开始就一直在搜集关于宿舍管理系统方面的资料,然后再联系实际,在同学、老师的帮助和我自己的努力下,终于在本次课程设计即将结束的时候,我把本次课程设计所需要的文件完成了。这时我既有成就感又有愧疚,成就的是我终于把本次课程设计完成了,愧疚的就是我在这次课程设计的第一个星期里一直在玩,这让我意识到我自身的一个严重的缺点,就是贪玩,做任何事情都是不到最后关头从不着急,这是个很不好的缺点,所以我决定以后一定要改掉这个坏毛病,以后做任何事情都要积极完成,不能拖。
参考文献
[1] 严蔚敏,吴为民.数据结构.北京.清华大学出版社.1997.
[2]张铭,王腾蛟,赵海燕.数据结构与算法.北京:高等教育出版社.2008.
[3]唐宁九,游洪跃,朱宏,杨秋辉.数据结构与算法(C++版).北京:清华大学出版社.2009.
[4]李春葆,喻丹丹.数据额结构习题与解析.第3版.北京.清华大学出版社.2006.
[5]王红梅,胡明,王涛.数据结构(C++版).第2版.北京:清华大学出版社.2011.
[6]王红梅,胡明.数据结构考研辅导.北京:清华大学出版社.2009.
附录:
算法代码如下:
#include <iostream>
#include <string>
#include <fstream>
#include <ctime>
using namespace std;
class student
{
private:
long int stu_num; //学生学号,宿舍号
char stu_name[40]; //学生姓名
char class_name[40]; //学生所在班级
char house_name[20]; //学生宿舍
public:
student()
{
stu_num=0;
stu_name[0] =0;
class_name[0] =0;
house_name[0] =0;
}
student::student(long a, char * b,char *c,char *d)
{
Setdata(a , b, c, d); //定义Setdata函数
}
char * Getstuname(void) //按学生姓名查找
{
return stu_name ; //返回学生的姓名
}
long Getstunum(void) //按学生学号查找
{
return stu_num; //返回学生的学号
}
char * Gethousename(void) //按学生宿舍号查找
{
return house_name; //返回学生的宿舍号
}
char * Getclassname(void) //按班级查找
{
return class_name; //返回学生所在班级
}
void Setdata(long a, char *b,char *c,char *d)
{
stu_num = a;
strcpy(stu_name, b); //将stu_name的值复制给b
strcpy(class_name, c); //将class_name的值复制给c
strcpy(house_name, d); //将house_name的值复制给d
}
void Show(void)
{
cout<<"学号:"<<stu_num<<"\t"<<"姓名:"<<stu_name<<"\t";
cout<<"班级:"<<class_name<<"\t\t"<<"宿舍:"<<house_name<<"\n";
}
};
void main(void)
{
student s1;
int flags=0;
long stu_num; //定义学号数据类型
char stu_name[40]; //定义姓名数据类型
char class_name[40]; //定义班级数据类型
char house_name[20]; //定义宿舍号数据类型
time_t t;
time(&t);
ifstream file1; //建立数据库
ofstream file3;
char flag = 'y';
cout<< "---------------------------------学生宿舍管理系统-------------------------------"<<endl;
cout<< "\t\t\t 系统时间:" << ctime(&t);
while( flag=='y' || flag=='Y') //由flag控制循环
{
cout<<"--------------------------------------------------------------------------------\n";
cout<<"\t\t 1:注册学生信息!\n"; //选项1
cout<<"\t\t 2:按学号查看学生信息!\n"; //选项2
cout<<"\t\t 3:按宿舍号查看学生信息!\n"; //选项3
cout<<"\t\t 4:按姓名查看学生信息!\n"; //选项4
cout<<"\t\t 5:按班级查看学生信息!\n"; //选项5
cout<<"\t\t 6:显示全部学生信息\n"; //选项6
cout<<"\t\t 7:按学号修改学生信息\n"; //选项7
cout<<"\t\t 8:按学号删除学生信息!\n"; //选项8
cout<<"\t\t 9:退出系统!\n"; //选项9
cout<<"--------------------------------------------------------------------------------\n";
cout<<"请输入选择:";
char choice;
cin>>choice;
switch(choice) //判断选择
{
case '1':
file3.open("c:\\stu.dat",ios::app|ios::binary);
input: flags=0;
cout<<"输入学生学号:";
cin>>stu_num;
while (stu_num<0 || stu_num>99999999)
{
cin.clear();
rewind(stdin);
cout << "你输入的学号不正确,请输入一个不超过八位数的学号" << endl;
cout << "学号:";
cin >> stu_num;
}
file1.open("c:\\stu.dat",ios::in | ios::binary | ios::beg);//按读方式打开文件
while(!file1.eof())
{
int n;
file1.read((char *)&s1,sizeof(student));
n=file1.gcount();
if(n==sizeof(student))
{
if(s1.Getstunum()==stu_num)
flags=1;
}
}
file1.clear();
file1.close();
if (flags==1)
{
cin.clear();
cout << "学号重复,请重输入!" << endl;
goto input;
}
cout<<"输入姓名:"; cin>>stu_name;
cout<<"输入班级:"; cin>>class_name;
cout<<"输入宿舍:"; cin>>house_name;
s1.Setdata(stu_num,stu_name,class_name,house_name);
file3.write((char*)&s1,sizeof(s1));
file3.clear();
file3.close();
break;
case '2': //按学号查找
cout<<"请输入学生的学号:";
cin>>stu_num;
while (stu_num<0 || stu_num>99999999)
{
cin.clear();
rewind(stdin);
cout << "你输入的学号不正确,请输入一个不超过八位数的学号" << endl;
cout << "学号:";
cin >> stu_num;
}
file1.open("c:\\stu.dat",ios::in | ios::binary | ios::beg);//按读方式打开文件
while(!file1.eof())
{
int n;
file1.read((char *)&s1,sizeof(student));
n=file1.gcount();
if(n==sizeof(student))
{
if(s1.Getstunum()==stu_num) //显示学生信息
{
s1.Show();
flags=1;
}
}
}
file1.clear();
file1.close();
if (flags==0)
cout << "没有找学号为:"<< stu_num <<"的学生记录!" << endl;
flags=0;
break;
case '3': //按宿舍号查找
cout<<"请输入宿舍号:";
cin>>house_name;
file1.open("c:\\stu.dat",ios::in | ios::binary | ios::beg);//按读方式打开文件
while(!file1.eof())
{
int n;
file1.read((char *)&s1,sizeof(student));
n=file1.gcount();
if(n==sizeof(student))
{
if(strcmp(s1.Gethousename(),house_name)==0)
{
s1.Show();
flags=1;
}
}
}
file1.clear();
file1.close();
if (flags==0)
cout << "没有找到宿舍为:"<< house_name <<"的学生记录!" << endl;
flags=0;
break;
case '4': //按姓名查找
cout<<"请输入学生姓名:";
cin>>stu_name;
file1.open("c:\\stu.dat",ios::in | ios::binary | ios::beg);//按读方式打开文件
while(!file1.eof())
{
int n;
file1.read((char *)&s1,sizeof(student));
n=file1.gcount();
if(n==sizeof(student))
{
if(strcmp(s1. Getstuname(),stu_name)==0)
{
s1.Show();
flags=1;
}
}
}
file1.clear();
file1.close();
if (flags==0)
cout << "没有找到姓名为:"<< stu_name <<"的学生记录!" << endl;
flags=0;
break;
case '5': //按班级查找
cout<<"请输入班级名称:";
cin>>class_name;
file1.open("c:\\stu.dat",ios::in | ios::binary | ios::beg);//按读方式打开文件
while(!file1.eof())
{
int n;
file1.read((char *)&s1,sizeof(student));
n=file1.gcount();
if(n==sizeof(student))
{
if(strcmp(s1. Getclassname(),class_name)==0)
{
s1.Show();
flags=1;
}
}
}
file1.clear();
file1.close();
if (flags==0)
cout << "没有找到该班级为:"<< class_name <<"的学生记录!" << endl;
flags=0;
break;
case '6': //显示全部学生信息
file1.open("c:\\stu.dat",ios::in | ios::binary);//按读方式打开文件
while(!file1.eof())
{
int n;
file1.read((char *)&s1,sizeof(student));
n=file1.gcount();
if(n==sizeof(student))
{
s1.Show();
flags=1;
}
}
file1.clear();
file1.close();
if (flags==0)
cout << "数据库没有记录!" << endl;
flags=0;
break;
case '7': //按学号修改学生信息
flags=0;
cout<<"请输入要修改学生的学号:";
cin>>stu_num;
while (stu_num<0 || stu_num>99999999)
{
cin.clear();
rewind(stdin);
cout << "你输入的学号不正确,请输入一个不超过八位数的学号" << endl;
cout << "学号:";
cin >> stu_num;
}
file1.open("c:\\stu.dat",ios::in | ios::binary | ios::beg);//按读方式打开文件
while(!file1.eof())
{
int n;
file1.read((char *)&s1,sizeof(student));
n=file1.gcount();
if(n==sizeof(student))
{
if(s1.Getstunum()==stu_num)
{
file3.open("c:\\stu.dat",ios::out|ios::binary);
cout<<"输入姓名:"; cin>>stu_name;
cout<<"输入班级:"; cin>>class_name;
cout<<"输入宿舍:"; cin>>house_name;
s1.Setdata(stu_num,stu_name,class_name,house_name);
file3.write((char*)&s1,sizeof(s1));
file3.close();
flags=1;
}
}
}
file1.clear();
file1.close();
if (flags==0)
{
cout << "没有此学生记录,不能进行修改!" << endl;
break;
}
break;
case '8': //按学号删除学生信息
default: flag = 'n';
break;
}
}
cout << "谢谢您的使用!" << endl;
}