系统的名称
影碟出租管理系统 可行性分析
通过对该影碟出租店的各个方面进行了具体的了解之后,现对该影碟出租店开发影碟出租管理系统的可行性进行分析。
(1)技术上可行:该系统所需硬件设备,市场上销售且价格较低,,软件上,操作系统采用Windows系列操作系统,数据库管理系统采用Visual Basic,这些软件在MIS开发中已被大量应用,技术上都比较成熟。因此在技术上是可行的。 (2)经济上可行:由于学校该影碟出租店已经到了一定的规模需要采用计算机来对影碟出租店的业务进行管理,因此对开发影碟出租管理系统大力支持,开发经费没有问题。
(3)管理上可行:该影碟出租店原先主要就是以会员为主要服务对象,每位会员均 收集信息
在对世面上的影碟出租店进行了初步的了解后,发现其业务主要是集中在影碟的管理和碟片的出租归还上。对影碟的管理工作量较大,采用手工的方式还容易出错,并且不能满足顾客对影碟的详细信息的查询功能。在现有的影碟出租中对会员的管理也很重要,传统的登记方式不仅费时而且不能对其出租日志进行系统的管理,造成了不必要的经济损失。
影碟出租信息系统的建立,需要进行用户的需求调查与分析,以确定系统目标,提出解决问题的详细方案,这是系统建设的重要环节。
该影碟出租店规模相对较小,但要有着完善的影碟信息,对每一张影碟都要有详细的记录信息,功能上对系统的需求是全面的。因此对用户的需求可分为四个方面:一方面是影碟出租店工作人员通过计算机来管理各类影碟,分类编号,调整影碟结构,增加影碟库存,适应顾客的需求;二方面是顾客们能通过计算机来查询浏览影碟出租店中的碟片,来确定自已需要的影碟,为租赁做好准备;三方面是工作人员对顾客们的会员的注册,注册能作好全面的掌握,及时得到每个
会员证的当前状态和历史租赁记录;四方面也是碟出租店的核心工作,对影碟的租赁管理。
这四个方面形成了碟出租店一个工作整体,采用计算机自动化信息处理,可方便快捷地共享信息、交流信息,高效地协同工作。
在软、硬件方面对系统的需求,软件要求易学,界面友好,容易掌握,可以很简单方便的管理各种影碟信息。硬件的配置要求不能太高,这样可以很好的适应当前的影碟出租店。在开发方式上对系统的需求,由于影碟出租店的商业利益较小,所以系统设计开发的周期要短,在短时间内完成,减少开发成本,提高开发效率,方便、简单、实用作为系统开发的指导思想。 功能需求
影碟租赁主要由影碟管理员、影碟、借阅信息顾客四大部分组成。影碟管理员主要是负责对影碟尽心组织整理,对出租的影碟的信息进行记录。影碟要进行多个备份,以满足多个顾客的需求。借阅信息是对用户的借阅情况进行记录。顾客是租借影碟,并在借后进行归还,缴纳租金。影碟管理员与影碟的关系是调配关系,顾客与影碟的关系是使用关系,影碟管理员与顾客的关系是服务关系。借阅信息与影碟的关系是包含关系,借阅信息与顾客的关系是记录关系。
一个比较理想的系统,应该满足以下要求: ⑴简单性、实用性
系统应该尽可能设计的比较简单,各功能实现清晰明了,同时应考虑实用性避免不必要的复杂化。结构简单尽可能使处理过程缩短,处理费用减少,系统收益增高。同时也利于使用者掌握和维护。
⑵完整性
系统是作为一个统一的整体而存在的,因此系统的功能要保持完整,数据采用要统一,传递语言要一致。
⑶灵活性
系统对外界环境的变化应有较强的适应力,即便在条件变化之后,仍能提供详尽的具有现实意义的有关信息。
⑷可靠性
系统必须是可靠的,只有这样,才能保证系统的高质量,才能得到使用者的
信任。
⑸经济性
系统应该给使用者带来相应的利益,提供更准确、更全面、更及时的信息,方便大大提高管理的效率。
系统要实现哪些功能,每个功能的具体描述
1)新片上架:录入碟片片名、编号等各种信息。并实现片子的增加、删除、修改的基本功能。
2)碟片查询:对片子进行分类查询的功能。
3)碟片借阅:对借出的片子进行管理,对租借的客户和所借出的片子的信息进行记录,对碟片的借阅进行普通客户和会员客户分类管理。
4) 碟片归还:对出租的片子进行金额结算,对普通客户和会员客户进行分类管
理。
数据字典
职工号会员号年龄联系方式片名借出时间归还时间租借押金已归还否租金费用编号发行时间内容描述账目余额可以唯一确定员工身份,由三位的整数表示对注册的顾客给予可以唯一确认,由五位的整数表示员工的年龄,有二位整数表示当顾客的借阅期限超出后,可以通过电话号码通知顾客影片的名称年+月+日年+月+日借走影片所抵押的金钱是\\否归还影碟时顾客要交的费用,由整数表示可以唯一识别影片年+月+日影片详细信息描述,包括影片的导演、主演、剧情,最多不能超过500字符用户可使用的金额,由浮点型表示=职工+工作时间+职工姓名+年龄=会员号管理员顾客
E-R图(侯璠)
顾客姓名会员影片编号已归还否片名借出时间租金应还时间借阅信息记录会员号顾客姓名电话号码服务顾客查询包含编号片名影碟信息发行时间内容描述租金查询调配管理员工作时间姓名年龄职工号
数据流图
客户客户请求查询片子信息片子信息文件片子信息片子信息出租管理客户信息会员卡入库管理片子信息归还信息出租信息店员会员管理会员信息文件出租信息店员请求账目信息结算信息归还信息租赁信息文件结算信息统计管理归还管理结算信息账目信息文件归还信息思考题
1、需求分析在软件开发中真的有那么重要吗?
在软件工程中,需求分析指的是在建立一个新的或改变一个现存的电脑系统时描写新系统的目的、范围、定义和功能时所要做的所有的工作。需求分析是软件工程中的一个关键过程。在这个过程中,系统分析员和软件工程师确定顾客的需要。只有在确定了这些需要后他们才能够分析和寻求新系统的解决方法。 在软件工程的历史中,很长时间里人们一直认为需求分析是整个软件工程中最简单的一个步骤,但在过去十年中越来越多的人认识到它是整个过程中最关键的一个过程。假如在需求分析时分析者们未能正确地认识到顾客的需要的话,那么最后的软件实际上不可能达到顾客的需要,或者软件无法在规定的时间里完工。
需求分析是一项重要的工作,也是最困难的工作。该阶段工作有以下特点:(1)用户与开发人员很难进行交流
在软件生存周期中,其它四个阶段都是面向软件技术问题,只有本阶段是面向用户的。需求分析是对用户的业务活动进行分析,明确在用户的业务环境中软件系统应该\"做什么\"。但是在开始时,开发人员和用户双方都不能准确地提出系统要\"做什么?\"。因为软件开发人员不是用户问题领域的专家,不熟悉用户的业务活动和业务环境,又不可能在短期内搞清楚;而用户不熟悉计算机应用的有关问题。由于双方互相不了解对方的工作,又缺乏共同语言,所以在交流时存在着隔阂。
(2)用户的需求是动态变化的
对于一个大型而复杂的软件系统,用户很难精确完整地提出它的功能和性能要求。一开始只能提出一个大概、模糊的功能,只有经过长时间的反复认识才逐步明确。有时进入到设计、编程阶段才能明确,更有甚者,到开发后期还在提新的要求。这无疑给软件开发带来困难。 (3)系统变更的代价呈非线性增长
需求分析是软件开发的基础。假定在该阶段发现一个错误,解决它需要用一小时的时间,到设计、编程、测试和维护阶段解决,则要花2.5、5、25、100倍的时间。
因此,对于大型复杂系统而言,首先要进行可行性研究。开发人员对用户的要求及现实环境进行调查、了解,从技术、经济和社会因素三个方面进行研究并论证该软件项目的可行性,根据可行性研究的结果,决定项目的取舍。
2、分析系统流程图,程序流程图和数据流图的区别和各自的特点。
系统流程图是概括的描绘物理系统的传统工具。它的基本思想是用图形符号以黑盒子形式描绘组成系统的每个部件(程序、文档、数据库、人工过程等)。系统流程图表达的是数据在系统各部件之间流动的情况,而不是对数据加工处理的控制过程,因此尽管系统流程图的某些符号和程序流程图的符号形式相同,但是他却是物理数据流图而不是程序流程图。
数据流图是结构化分析方法中使用的工具,它以图形的方式描绘数据在系统中流动和处理的过程,由于它只反映系统必须完成的逻辑功能,所以它是一种功能模型。在结构化开发方法中,数据流图是需求分析阶段产生的结果。
3、怎样写合乎规范的数据流图和数据词典 画数据流图原则:
(1)数据流图上所有图形符号只限于前述四种基本图形元素。 (2)顶层数据流图上的数据流必须封闭在外部实体之间。 (3) 每个处理框至少有一个输入数据流和一个输出数据流。
(4)在数据流图中,需按层给处理框编号。表明该处理所处层次及上下层的亲子关系。
(5) 规定任何一个数据流子图必须与它上一层的一个处理对应,两者的输入数据流和输出数据流必须一致。此即父图与子图的平衡。 (6)图上每个元素都必须有名字。 写数据字典:
数据字典由下列四类元素定义组成 (1)数据流
(2)数据流分量即数据元素 (3)数据存储
(4)处理
实验二:系统设计
层次图
影碟出租管理系统碟片管理子系统租借管理子系统用户管理子系统碟片上架碟片删除碟片修改租借管理归还管理查询碟片管理会员管理普通客户管理结构图
影碟出租管理系统管理员用户处理查询租借归还碟片信息 归还管理模块
程序流程图
开始客户归还请求会员客户?NY会员碟片归还非会员碟片归还Y是否继续归还?N归还租金结算付款结束 盒图
开始客户归还请求会员客户?YN会员碟片归还非会员碟片归还是否继续?归还租金结算付款结束
Jackson图
碟片租借管理系统归还管理子系统会员客户非会员客户会员租借会员租金结算付款非会员租借非会员租金结算付款
租借管理模块
程序流程图
开始客户请求会员客户?YY会员碟片租借N非会员碟片租借是否继续?N退出结束
2.2盒图
开始客户请求会员客户?Y会员碟片租借是否继续?N非会员碟片租借退出结束
2.3 jackson图
碟片租借管理系统租借管理会员租借非会员租借会员租借非会员租借
思考题
1、如何分辨事务中心数据流和变换中心数据流?
2、设计软件结构图时,如何把握内聚和耦合的度?
(1)尽量使用数据耦合,少用控制耦合和特征耦合,限制公共耦合的范围,完全不用内容耦合
(2)功能内聚10分、顺序内聚9分、通信内聚7分、过程内聚5分、时间内聚3分、逻辑内聚1分、偶然内聚0分
3、设计程序流程图时,循环嵌套以几层为好?
4、怎么判断盒图的正确性?
实验三: 编码实现
2.2类
1.CD类:该类拥有私有数据成员CDID(碟片编号)、CDname(碟片名称)、mainstar(主演明星)、country(国家)、style(碟片类型)、director(导演)、company(制作公司)、lend(借出数量)、inventory(库存量)。成员函数包含有参构造函数、重载流插入提取运算符、拷贝复制构造函数以及获取私有成员函数和更改私有成员函数,具体类信息如下:
class CD{ private:
string CDID; //碟片编号 string CDname; //碟片名称 string mainstar; //主演明星 string country; //国家 string style; //碟片类型 string director; //导演 string company; //制作公司 int lend; //借出数量 int inventory; //库存量
public:
CD(string ci=\"无\cna=\"无\无\cot=\"无\sty=\"无\无\无\
friend istream& operator>>(istream &is,CD &die); //重载输入运算符 friend ostream& operator<<(ostream &os,CD &die); //重载输出运算符 friend ofstream &operator<<(ofstream &ofs,CD&die); //重载文件插入运算符 CD(const CD &c); //复制构造函数 CD(CD &c,const CD &d); //复制构造函数 string getCDID(){return CDID;} string getCDname(){return CDname;}
string getmainstar(){return mainstar;} string getcountry(){return country;} string getstyle(){return style;} string getdirector(){return director;} string getcompany(){return company;}
int getlend(){return lend;}
};
int getinventory(){return inventory;} void setCDID(string ci){CDID=ci;} void setCDname(string cna){CDname=cna;} void setmainstar(string mst){mainstar=mst;} void setcountry(string cot){country=cot;} void setstyle(string sty){style=sty;} void setdirector(string dir){director=dir;} void setcompany(string com){company=com;} void setlend(int le){lend=le;}
void setinventory(int inv){inventory=inv;}
2.member类:该类拥有私有成员memberID(会员号)、membername(会员姓名)、sex(性别)、money(会费剩余)。成员函数包含有参构造函数、流重载插入运算符、拷贝构造函数以及获取私有成员函数和更改私有成员函数,具体类信息如下:
class member {
friend istream& operator>>(istream& is,member &me);//重载插入运算符 friend ostream& operator<<(ostream& os,member &me);//重载提取运算符 friend ofstream& operator<<(ofstream& ofs,member &me);//重载文件插入运算符
private:
string memberID; //会员号 string membername; //会员名字 string sex; //会员性别 float money; //会费剩余
public:
member(string mid=\"无\无\无\带参默认构造函数
member(const member &m); //拷贝构造函数 string getmemberID(){return memberID;} string getmembername(){return membername;} string getsex(){return sex;} float getmoney(){return money;}
void setmemberID(string mid){memberID=mid;} };
void setmembername(string mna){membername=mna;} void setsex(string se){sex=se;} void setmoney(float mon){money=mon;}
3.caozuo类:该类私有成员分别为:member hy[100](能存100个会员信息)、CD zu_dip[100][10](每个会员租借的碟片信息,且规定每人最多只能租借10种影碟)、CD dip[100](定义能存100种碟片信息)、int category(用来做影碟的下标)、int kind(用来做会员的下标)、int lendnumber[100](记录每个会员租借的碟片种类)、string time[100][10][20](用来记录每个会员租借的每一种碟片对应的租借时间信息)。成员函数主要有有参构造函数以及各种功能函数,详细信息如下所示:
class caozuo { private:
member hy[100]; //定义能存100个会员信息
CD zu_dip[100][10]; //每个会员对应租借的碟片信息,且规定最多只能租10种影碟 CD dip[100]; //定义能存100种碟片信息 int category; //用来做影碟的下标 int kind; //用来做会员的下标
int lendnumber[100]; //记录每个会员租借的碟片种类
string time[100][10][20]; //用来记录每个会员租借的每张碟片的租借时间信息
public:
caozuo(int c=0,int k=0) //初始化category和kind
};
{ }
void aiddp();//增加影碟信息 void gxdp();//更新影碟信息 void find_dp();//查询影碟信息 void delete_dp();//删除碟片信息 void put_all_dp();//输出全部影碟信息 void aidhy();//注册新会员 void gxhy();//更新会员信息 void find_hy();//查询会员信息 void aid_money();//会员费充值 void delete_hy();//删除会员信息 void put_all_hy();//输出全部会员信息 void rent_cd();//租赁影碟 void back_cd();//归还影碟
void dp_statistics();//统计影碟种类清单 void read_cd();//读取影碟文件上的信息 void read_hy();//读取会员文件上的信息
void read_lendcdcategory();//读取借碟片种类数据 void read_rent_cd();//读取已租出碟片的信息 void read_rent_time();//读取已租碟片的时间信息
category=c; kind=k;
2.3类的分析
在CD类中,主要就是碟片的基本信息,包括碟片的编号、名称、导演等等。在member类中就是会员的基本信息,主要就是会员的ID、姓名、性别和账户余额这些信息。在caozuo类中就是把CD类和member类作为它的私语成员然后集中处理他们之间的关系,主菜单里的各种功能也全部在该类中定义实现。在caozuo类中,定义了类数组member hy[100],其功能作用是可以存储100个会员信息。CD类数组 CD dip[100],其功能作用是可以存储100种碟片信息。另一个CD类二维数组CD zu_dip[100][10];其是与会员类数组绑定在一起的。例如hy[5]对应着zu_dip[5][i],i代表会员hy[5]借的第几种碟片,且其上线是10张。Member类中的私有成员category是用来标记当前共入库的碟片的种类,用来做
影碟CD类数组的下标。私有成员函数kind是用来标记当前已注册的会员数量,即用来做会员类数组的下标。类中定义的整形数组int lendnumber[100],是用来记录每个会员租借的碟片种类,例如lendnumber[5]=4,就是会员hy[5]租借了4种碟片。并且lendnumber[10]也就是用来标记zu_dip[100][10]中的列数的,即做列的下标。在caozuo类数组中还定义了一个string字符型二维数组string time[100][10][20],其中100是和会员hy[100]中的100是一一对应的,10是和zu_dip[100][10]中的10是一一对应的,20是字符长度。该string字符型二维数组主要是用来记录每个会员租借的每种碟片的租借时间信息。caozuo类组合了CD类和member类,使程序可以灵活地处理会员和碟片之间的关系。而该类中的成员函数也主要都是在处理CD类和member之间的关系,最具有体现性的就 是租赁函数和碟片归还函数。
3详细设计
1.类型统计功能:进入该功能,程序使用者可以查看某种类型的碟片信息。
信息存储功能:凡在执行程序中涉及到系统内存改变的地方都要把改变的信息写入文件保存起来,以达到存储功能。 例如碟片的写入文件操作
ofstream ofile; ofile.open(\"碟片信息.txt\"); for(int j=0;j ofile< cout<<\"添加成功!\"< cout<<\"********************************************************\"< cout<<\"********************************************************\"< cout<<\"********************************************************\"< caozuo a; a.read_cd(); //系统自动读取文件中的碟片信息,并放到系统内存中 a.read_hy(); //系统自动读取文件中的会员信息,并放到系统内存中 a.read_lendcdcategory(); //系统自动读取文件中每个会员借的碟片种类信息,并放到系统内存中 a.read_rent_cd(); //系统自动读取文件中的已租出碟片信息,并放到系统内存中 a.read_rent_time(); //系统自动读取文件中的已租出的每张碟片对应租借的时间信息,并放到系统内存中 模块设计 //--------------------碟片查询模块------------------------------ int check(void)//碟片查询 { FILE *a;//文件指针 char cd_name[10]; system(\"cls\");//清屏 } a=fopen(\"cd.txt\只读方式打开文件 for(int i = 0; i < cd_number; i++) { fread(&CD[i], sizeof(struct cd),1, a);//把a中一个cd结构体赋给CD[i] } printf(\"请输入碟片名:\\n\"); scanf(\"%s\ getchar();//取回车符 for(i = 0; i < cd_number; i++) { if((strcmp(CD[i].film_name, cd_name))==0) //若影片名相同 { if(CD[i].n==1) //借阅标记为1 { printf(\"可借阅\\n\"); fclose(a); return 1; } if(CD[i].n==0)//借阅标记为0 { printf(\"已借出\\n\"); fclose(a); return 1; } } } for(i = 0; i < cd_number; i++) { if((strcmp(CD[i].film_name, cd_name))!=0) //若影片名不同 { printf(\"无此片\\n\"); fclose(a); return 1; } } fclose(a);//关闭a文件 return 0; //返回菜单 //------------会员添加模块--------------------------------- void useradd(void)//添加会员 { system(\"cls\");//清屏 FILE *a; //文件指针 printf(\"请输入姓名:\\n\"); scanf(\"%s\ getchar(); a = fopen(\"rent.txt\追加方式打开 fwrite(&RENT[user_number], sizeof(struct rent), 1, a);//把a中一个rent结构体赋给RENT[user_number] printf(\" 添加成功 \\n\"); user_number++; fclose(a); } //-------------碟片借阅模块----------------------------- int rent(void) //碟片借阅 { system(\"cls\");//清屏 char user_name[10]; char cd_name[10]; FILE *a;//文件指针 FILE *b;//文件指针 int k=0; char choice; a = fopen(\"rent.txt\只读方式打开 b = fopen(\"cd.txt\只读方式打开 for (int i = 0; i < cd_number; i++) { fread(&CD[i], sizeof(struct cd),1,b);//把b中一个cd结构体赋给CD[i] } for (i = 0; i < user_number; i++) { fread(&RENT[i],sizeof(struct rent),1,a);//把a中一个rent结构体赋给RENT[i] } printf(\"请输入借阅人:\\n\"); scanf(\"%s\ getchar(); a: printf(\"请输入碟片名:\\n\"); scanf(\"%s\ getchar(); printf(\"请再次输入碟片名:\\n\"); scanf(\"%s\ k++; getchar(); printf(\"此人已借%d张\\n\ for (int j = 0; j < cd_number; j++) { if((strcmp(CD[j].film_name, cd_name))==0)//如果两个名相同 { CD[j].n=0; //修改借阅标记 } } printf(\"请输入借出日期:\\n\"); scanf(\"%d\ getchar(); printf(\"A: 再接一张\\n\"); printf(\"B: 退出\\n\"); scanf(\"%c\ getchar(); switch(choice)//多条件选择判断 { case 'A': goto a; break; case 'B': return 0; } fclose(a); fclose(b); return 0; } //--------------碟片归还模块--------------------------- void returnn (void) //碟片归还 { system(\"cls\");//清屏 char user_name[10]; char cd_name[10]; FILE *a; FILE *b; int i; int j; int k = 0; char choice; a = fopen(\"rent.txt\只读方式打开 b = fopen(\"cd.txt\只读方式打开 for (i = 0; i < cd_number; i++) { fread(&CD[i], sizeof(struct cd), 1, b);//把b中一个cd结构体赋给CD[i] } for (i = 0; i < user_number; i++) { fread(&RENT[i], sizeof(struct rent), 1, a); //把a中一个rent结构体赋给RENT[i] } printf(\"请输入借阅人:\\n\"); scanf(\"%s\ for (i = 0; i < user_number; i++) { if ((strcmp(user_name, RENT[i].username))==0) { a: printf(\"请输入要归还的碟片名: \\n\"); scanf(\"%s\ for (j = 0; j < cd_number; j++) { if((strcmp(CD[j].film_name, cd_name))==0) { CD[j].n = 1; break; } } } } printf(\"借出日期:%d\\n\ printf(\"请输入归还日期:\\n\"); scanf(\"%d\ getchar(); if (((RENT[i].return_time - RENT[i].rent_time) % 3)==0) //计算租金 { } //(每三天租金为1 不满三天以三天记) RENT[i].money = (RENT[i].return_time - RENT[i].rent_time) / 3; } else { RENT[i].money = (RENT[i].return_time - RENT[i].rent_time) / 3 + 1; } printf(\"租金:%d\\n\ printf(\"A: 再还一张\\n\"); printf(\"B: 退出\\n\"); scanf(\"%c\ getchar(); switch(choice) { case 'A': goto a; break; case 'B': return; } fclose(a); fclose(b); 思考题 1、如何做到养成良好的编程习惯? 一个好的程序的评价标准按次序主要有以下3条: 1) 可以正确的运行。 2) 容易理解。(可读性强) 3) 有效率。 养成良好的编程习惯应做到: 1、应该在每个程序的开始都加上注释,解释该程序的目的作者以及程序最后一次被修改的日期和时间等。 2、使用空行和空格符来增强程序的可读性。 3、按照约定,所以读者在為类命名时也应该遵循这个约定,这样会有效提高程序的可读性。 4、程序中键入一个左花括号{后应立即键入一个右花括号}然后将光标重新定位 在两个花括号中间,并在其中先进行缩进,再键入程序体。这一编程习惯有助于避免遗漏花括号。 5、界定类主体的花括号和右花括号{}之间,将每个类声明的整个主题都缩进一级。这种格式强调了类声明的结构,又使程序更易读。 实验四:软件测试 调试分析 调试中遇到的问题及解决方案 问题1:租赁碟片时,如果没有在库存中查找到要租的碟片,虽提示该碟片不存 在,却在结束时把押金扣掉了,其显示窗口如下 问题分析解决:该漏洞主要是因为收取押金的代码放到了最后,因而无乱是否租赁成功,都会收取押金20元,解决的办法就是找到要租赁的碟片并且确定要租赁时,这时再写收取押金的代码,问题就得到了解决。 问题2:注册一个新会员时,该会员没有租借碟片,归还碟片功能中输入该会员 的ID,程序中应该提示“该会员无租借记录”,但在该处却要输出归还碟片信息。其显示窗口如下 问题分析解决:该漏洞主要是无法判断会员是否有租借记录造成的,问题解决的方法就是在caozuo类中添加私有成员int型lendnumber[100]并初始化为0来记录每个成员是否有租借记录。当会员hu[i]归还碟片时,首先判断lendnumber[i]是否为0,若为0,则显示“该会员无租借记录”,否则就可以进行归还碟片功能。 问题3:当库存数量只有20张时,会员输入租借数量180,却成功了!而在随后 输出全部碟片信息时,库存数量也由原来的20变成了-160,其显示窗口如下 问题分析解决:该漏洞主要是在会员租借碟片时缺少对会员租借数量的判断,然后继续进行租借,改变系统内存,继而导致了输出的错误。问题的解决方法就是在会员输入租借数量时进行判断,如果该数量不在碟片库存范围之内,则输出“租借数量错误”,否则再继续进行租借操作。 问题4:当输出全部会员信息时,每输出一个会员,就会输出一行标题,标题行太多,其显示窗口如下 问题分析解决:该漏洞主要是因为把输出标题行放在了输出会员的循环了,因而每输出一个会员就会输出一行标题,解决该问题的方法就是把输出标题行的代码放到循环外面,只输出一次,这样标题行太多的问题就得到了解决。 问题5:当会员去归还碟片时,只能一次性全部归还,无法实现部分归还的功能。其显示窗口如下 问题分析解决:该漏洞主要是没有从用户角度考虑问题,没能是功能完善。问题的解决方法就是在会员归还碟片时,提示会员是全部归还还是部分归还,然后分两种情况进行归还碟片的功能。 问题6:此处日期的输入格式出错,没有提示用户正确的日期输入格式,在日期输入过后,提示是否继续租赁,此处无法接受命令,一直提示输入有误!其显示窗口如下 问题分析解决:该漏洞主要是界面不友好和输入菜单选项接受数字出错所致。解决该漏洞的方法就是在请输入租赁日期后面友好提示用户“日期的格式为:2013年4月12日”,这样就不会出现这样的错误了。 4.2经验和体会 在调试分析和测试结果这个过程中,首先就是要使用程序里的每一个功能,在涉及到输入时,要想到各种可能去输入,继而找出程序中的漏洞,找到漏洞以后,可以截屏保存下来留作更改代码的依据。在更改代码时,要能够根据漏洞找到出错的函数以及函数里的具体位置。找到后根据截屏上的漏洞来修改代码。若是在函数里找不到漏洞的地方,则可以通过调语句调过程,在监视窗口中一步一步查找漏洞,继而慢慢修改代码,完善程序功能。 5.用户使用说明 进入主菜单:顾客可以选择租赁影碟、归还影碟、影碟维护、顾客维护、信息查 询和类型统计这几种功能。 碟片借阅:顾客输入会员ID,输入需租碟片,输入数量及租借日期 碟片归还:输入会员ID,选择是全部归还还是部分归还,然后输入租借天数。 影碟维护:顾客可以选择增加、删除、更新三个功能 碟片增加:输入碟片编号、名称……等 碟片删除:输入要删除的碟片名称,然后删除该碟片 碟片更新:输入要更新的碟片名称,然后进行输入更新 顾客维护:顾客可以选择增加、删除、更新、会员费冲值四个功能 增加会员:输入注册的会员ID、性别……等 删除会员:输入要删除的会员ID,然后删除该会员 会员更新:输入要更新的会员ID,然后进行输入更新 会员费充值:输入会员ID,输入充值金额 信息查询:顾客可以选择查询碟片、会员、全部碟片和会员信息四个功能 查询碟片:输入碟片名称,显示该碟片的信息 查询会员:输入会员ID,查询会员信息 查看所有碟片:显示所有碟片信息 查看所有会员:显示所有会员信息 类型统计:输入你想查看的碟片类型,输出该类型的所有碟片 白盒测试 6.黑盒测试 7.1 运行程序,显示主菜单,显示窗口如下 如图,菜单中共有7个选项,键入3,进入影碟信息维护子菜单,显示窗口如下 此时共有三个功能选项,键入1,添加新影碟,显示窗口如下 键入1继续添加影碟两张,然后显示全部影碟信息,显示窗口如下 添加的三张影碟全部进入库存,程序添加新影碟及影碟信息显示功能测试成功!下面回到主菜单,键入4,显示窗口如下 键入1,注册新会员,其显示窗口如下 键入1,继续添加两位会员,然后进入信息查询系统,显示全部会员信息,其显示窗口如下 注册的三位新会员都已进入系统内存,会员注册及显示所有会员信息功能测试成功!回到主菜单,键入4,进入会员信息维护系统。然后键入2,删除一条会员信息,其显示窗口如下 删除成功后,键入2,退出删除操作系统,回到主菜单,再进入信息查询系统,显示全部会员信息,其显示窗口如下 此时显示所有会员信息时,编号为222的会员已被删除,会员删除功能测试成功! 回到主菜单,键入1,进行影碟租赁操作,其显示窗口如下 影碟租赁过后,回到主菜单,直接退出程序,测试其存储功能。其显示窗口如下 再次打开程序,分别显示其全部影碟信息和会员信息,其显示窗口如下 从这两个窗口中可以看出影碟杀破狼被借出2张,显示正确,会员张三借了2张影碟杀破狼,1张扣押金20元,信息中显示账户余额460元,而先前是500元,信息核对正确,但现在还不能断定程序存储功能测试成功,下面进行归还碟片测试,其显示窗口如下 碟片归还,一张碟片5天应该是2元,2张碟片应收取4元租金,租金收取正确。影碟归还成功后,再显示全部会员信息和碟片信息,其显示窗口如下 在这两个窗口中,影碟杀破狼的库存又回到了50,会员张三的账户余额也变成了496元。通过这些数据可以判断,影碟归还成功!同时也可以判断该程序的存储功能测试成功! 回到主菜单,进入查询系统,键入1,查询影碟信息,其显示窗口如下 此时库存为50,查询结果为可借阅,碟片查询功能测试成功!再在查询系统中键入2,查询会员信息,其显示窗口如下 会员查询功能测试成功! 回到主菜单,键入6,统计影碟类型,其显示窗口如下 影碟统计功能测试成功! 下面是各种友好报错功能测试,其显示窗口如下 1 主菜单选择功能时误键入字母r,程序报错成功! 2 在删除影碟时,输入库存中不存在的影碟,报错成功!后来选择是否重新输入时,输入3,程序报错成功! 3 影碟租赁时,非会员租赁时友好提示该会员不存在。 在程序大量运行时,各种友好提示和报错功能均测试成功! 经过各种功能的测试,该程序测试通过! 在编写白盒测试的测试用例时应注意哪些事项 (1)保证每个模块中的所有独立路径至少被执行一次; (2)对所有的逻辑值均需要测试真、假两个分支; (3)在上下边界及可操作范围内运行所有循环; (4)检查内部数据结构以确保其有效性。 调试与测试有什么关系?怎样把握这种关系? 调试是开发人员在编程结束之后验证程序是否实现而进行的。范围小,只针对自己编写的某一段代码或者某一个函数,针对性强。 软件测试从范围上要广于调试。是从验证功能层次上着手。根据不同的目的,会有若干种划分和不同的测试手法。比如说黑盒,白盒;自动化,人工;功能,性能;本地化,国际化等等。 软件测试的根基在于需求和用户,如果开发人员的编码或者设计是错误的,即便调试通 过,如果和需求相违背,软件测试这边也是无法通过的。 测试后应该做什么后续工作? 实验五:面向对象的分析与设计 一、确定参与者 这个例子中,可以确定“普通客户”和“商店管理员”是该系统的两个主要参与者,另外,系统需要使用外部的“邮件系统”通知预订者,因此“邮件系统”也是一个被动的参与者。 二、系统用例图 登录 注册会员 注册用户 管理客户 查询浏览管理各户资管理光碟购买光碟 商店管理员 登记出售光碟信息 预定光碟 普通用取消预约订 登记归还信邮件系统 三、用例描述 下面给出“音像店系统”例子中“登记借售信息”的用例描述。 用例:登记借售碟信息 1、 目标 本用例允许商店管理员登记普通客户的借售碟信息。 2、 时间流 2.1 基本流程 当普通用户希望借碟或买碟,管理员准备登记有关的借碟或售碟记录时,本用例开始执行。 (1) 系统请求商店管理员输入客户的条形码和所借或买碟的信息; (2) 商店管理员输入有关信息后,系统产生一个惟一的借碟或售碟 的记录号; (3) 系统显示新生成的租借或销售记录; (4) 商店管理员确认后,系统增加一个新的借售碟记录。 2.2 可选流程 (1) 客户没有注册 在主流程中,如果系统中没有客户的注册信息,系统将显示错误信息,用例结束。 (2) 所借光碟不存在 在主流程中,如果所借光碟已被借出或者系统中没有光碟,系统将显示错误信息,用例结束。 (3) 客户要购买录像带 在主流程中,如果客户要购买录像带或光碟。可以不用注册会员,但系统必须增加新的购买记录。 3、 特殊需求 用户可以预定录像带,并在指定日期来取。 4、 前提条件 用例开始之前,商店管理员必须系统登录成功。用户必须注册成为会员。 5、 后置条件 如果用例执行成功,该客户的借碟或销售光碟的记录被更新。否则,系统状态不变。 思考题 1、面向对象分析与设计与面向过程设计有何异同之处? 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。 2在进行面向对象分析与设计时,如何保证设计内容的准确性和一致性? 3面向对象分析中的类能否直接生成程序中的类 实验六 面向对象实现与测试 系统测试 系统的初步测试 在经过集成和编译之后,在默认系统环境下进行系统的初步测试,包括程序界面的测试、程序运行状态的测试、程序执行情况的测试和程序兼容性测试。 ⑴程序界面测试:对于程序界面的测试主要是看程序界面本身有无明显的错误。程序界面的设计是否得当,是否友好等。 ⑵程序运行状态的测试:包括反复运行程序,退出程序以观查程序运行的稳定性。 ⑶程序执行情况的测试:对程序每个功能进行逐一的测试,以发现程序存在的错误。 ⑷程序兼容性测试:将程序分别在不同的电脑环境中测试,以检查程序的兼容性能。通过基本的初步测试,使集成后的程序更加的完善,排除可能影响程序运行的错误。 系统测试及结果分析 软件开发进行测试的目的和意义 软件测试通常是指寻找和修正错误的过程。软件开发过程中的测试阶段是产品 发行阶段的“前奏”,该阶段是对错误的一系列核查。 上述定义与目前的实践是一致的,但是理想的测试应当与软件开发的所有阶段相关联,并且必须处理需求的有效性,对说明书进行核实,以及保证最终代码的正确运行。 测试结果分析及结论 系统设计结束后在单机上运行,从安全控制方法进行测试,系统主程序启动后,根据程序是否为存在口令,如果存在,程序则自动启动“口令”对话框,提示用户输入口令,可以避免无关人员使用工资数据或破坏工资数据。另外,在数据库的设计和操作方法,我们通过随机法进行测试,在不同的条件下,对不同的数据进行记录的查询、修改、打印。得到的随机结果基本无差错。 可以看出,在整个系统的设计过程中,我们不只一次的进行了测试,主要是因为对于一个软件的开发来说,测试是非常至关重要的。软件如果离开了测试 就无法算得上一个完的软件,也就无法带给用户一个稳定的系统。 系统运行与维护 系统正式运行前要做好该影碟出租店的员工培训工作,投入运行前期要手工和计算机系统同时操作,以防止操作不当给影碟店造成不必要的损失。 系统正式运行时要定期做好数据的备份工作。 思考题 1.C++与JAVA在面向对象实现中是一样的吗?有何区别? 2.在进行类测试时,如何设计测试用例更准确 3.面向对象测试和面向过程测试有何异同? 设计总结 首先,说一下需求分析,这一部很重要,一定要想好数据库需要的数据,及其功能。数据字典要准备充分。数据流图也要设计好。这是以后概念设计等的重要依据。 概念设计时,先弄分E-R图,再总E-R图。解决好属性、命名、结构上的冲突。消除不必要的冗余。 逻辑设计阶段要依据E-R图设计好二维表。要根据函数依赖,范式的概念规范好。 感觉自己做的系统,各个表的设计比较到位,设置的外键也方便了各表的连接。不足之处是有些复杂功能没能实现。比如,会员来租借,要能简单的实现租借的功能,包括租借,租借项,碟片等的更新。而不能一项一项的改。在这方面,自己设计了存储过程,但是碟片数量的出库,入库记录没能动态的弄好,即会员租借是,更新了租借,租借项后,碟片的数量不会跟着变化。 为了开发出真正满足用户需求的软件产品,首先必须知道用户的需求。对软件需求的深入理解是软件开发工作获得成功的前提条件,不论我们把设计和编码工作做得如何出色,不能真正满足用户需求的程序只会令用户失望,给开发者带来麻烦。需求分析使软件定义时期的最后一个阶段,它的基本任务是准确地回答“系统必须做什么?”这个问题。 需求分析的任务还不是确定系统怎样完成它的工作,而仅仅是确定系统必须完成那些工作,也就是对目标系统提出完整、准确、清晰、具体的要求。 需求分析是一项十分艰巨复杂的工作。在进行需求分析时的任务有确定对系统的综合要求、分析系统的数据要求、到处系统的逻辑模型和修正系统开发计划。 开发一个新的软件从无到有首先要进行问题的定义,确定要解决的问题。而后是可行性研究,可行性研究阶段的目的是确定问题是否有解十分值得去解决,任务是在尽可能短的时间内,花费尽可能少的时间搞清楚问题是否有解是否值得去做。如果问题没有可行的解,分析员应该建议停止这项开发工程,可以避免时间、资源、人力和金钱的浪费;如果问题值得解决,分析员该推荐一个较好的解决方案,并且为工程制定一个触不到计划。可行性研究占成本的5%-10%但他可能晚会之后90%的损失。可行性研究通过之后还要进行需求分析明确软件需要实现的功能。 通过这次设计,自己对课本的理解更透彻了,对于一个数据库系统的设计也有了大概的了解。 附录 #ifndef VIDEO_H #define VIDEO_H #include class video{ //影碟类 friend ostream &operator<<(ostream &os,video &vi); friend class application; public: video(string=\"\ video(video &vi); void input(); //private: string Vname; //碟片名称 string Country; //国家 int Type; //类型 string Producer; //制片人 string Director; //导演 string Star; //主演明星 int Number; //库存量 video *next; }; video::video(string vname,string country,int type,string producer,string director,string star,int number){ Vname=vname; Country=country; Type=type; Producer=producer; Director=director; Star=star; Number=number; } video::video(video &vi){ Vname=vi.Vname; Country=vi.Country; Type=vi.Type; Producer=vi.Producer; Director=vi.Director; Star=vi.Star; Number=vi.Number; } ostream &operator<<(ostream &os,video *vi){ os<<\"****************************************************************\"< #endif #ifndef CUSTOMER_H #define CUSTOMER_H #include string Cname; class Customer{ //顾客类 friend ostream & operator<< (ostream &os,const Customer &cu); friend class application; friend class video; public: Customer(string=\"\ //构造函数 int DeclineMoney(int ); //扣取消费额 bool RentVideo(string ); //出租影碟 bool ReturnVideo(string ); //归还影片 //private: string idPerson; //会员账号 string Name; //会员姓名 int LeftMoney; //会员剩余金额 int nCount; //所借碟片数量 VideoInfo Video[10]; //每个会员最多借10张影碟 Customer *next1; }; Customer::Customer(string idperson,string name,int leftmoney,int ncount,string videoname,int begintime,int endtime){ idPerson=idperson; Name=name; LeftMoney=leftmoney; nCount=ncount; for(int i=0;i ostream & operator<< (ostream &os,const Customer *cu){ os<<\"会员编号为:\\"< #ifndef MENU_H #define MENU_H #include class menu{ //菜单类 public: int showMainMenu(); private: }; int menu::showMainMenu(){ system(\"cls\"); cout<<\" ————————————————————————\"< #endif #ifndef APPLICATION_H #define APPLICATION_H #include class application{ //数据应用类 public: application(); ~application(); void load(); //数据输出 void save(); //数据保存到文件 void Rent(); //1.影碟租赁 void Return(); //2.影碟归还 void Checkall(); //3.查看各类型影碟信息 void search(int Type); //根据类型查找 void Check(string vidname); //4.查看影碟信息:根据碟片名称查找 void Addvideo(); //5.添加影碟 void Deletevideo(); //6.删除影碟 void Modifyvideo(string Vname); //7.修改影碟信息 void Customerinfo(string Cname);//8.会员信息:根据姓名查找 void Add(); //9.注册会员 void Delete(); //10.注销会员 void Modify(string Name); //11.更新会员信息与充值 void run(); private: string title; menu myMenu; video myvideo; Customer mycustomer; video *vid; Customer *cus; }; application::application(){ vid=0; cus=0; load(); } application::~application(){ video *v; v=vid; Customer *c; c=cus; while(v){ v=v->next; delete vid; vid=v; } vid=0; while(c){ c=c->next1; delete cus; cus=c; } vid=0; } void application::load(){ ifstream file; //碟片信息 video *v=vid; string Vname; //碟片名称 string Country; //国家 int Type; //类型 string Producer; //制片人 string Director; //导演 string Star; //主演明星 int Number=0; //库存量 file.open(\"video.txt\ file>>Vname>>Country>>Type>>Producer>>Director>>Star>>Number; while(file.good()){ v=new video(Vname,Country,Type,Producer,Director,Star,Number); v->next=0; //碟片结点加入链表 if(vid) //若已经存在结点 { video *v2; v2=vid; while(v2->next) //查找尾结点 { v2=v2->next; } v2->next=v; //连接 } else //若不存在结点(表空) vid=v; //连接 file>>Vname>>Country>>Type>>Producer>>Director>>Star>>Number; } file.close(); ifstream file1; //会员信息 Customer *c=cus; string idPerson; //会员账号 string Name; //会员姓名 int LeftMoney; //会员剩余金额 int nCount; //所借碟片数量 VideoInfo Video[10]; //每个会员最多借10张影碟 file1.open(\"Customer.txt\ file1>>idPerson>>Name>>LeftMoney>>nCount; for(int i=0;i else //若不存在结点(表空) cus=c; //连接 file1>>Video[i].BeginTime>>Video[i].EndTime>>Video[i].VideoName; } } file1.close(); } void application::save(){ ofstream file(\"video.txt\ ofstream file1(\"Customer.txt\ char c; cout<<\"\\n是否保存数据?[Y/N]:\"; cin>>c; if(toupper(c)!='Y') return; video *v=vid; while(v){ file< void application::Rent(){ int number; Customer *c1; c1=cus; cout<<\"请输入会员姓名:\"< } if(c1!=NULL){ cout< for(int i=0;i Checkall(); return ; } else return ; system(\"pause\"); } void application::Check(string vidname){ video *v1; v1=vid; while(v1){ if(v1->Vname==vidname) break; else{ v1=v1->next; } } if(v1!=NULL){ cout< } else{ v1=v1->next; } } if(v1!=NULL){ cout<<\"该碟片已存在,是否修改该碟片信息(Y/N) \"< cout<<\"类型(1.喜剧2.悲剧3.科幻片4.悬疑剧5.惊悚片6.其他):\";cin>>Type; cout<<\"制片人:\";cin>>Producer; cout<<\"导演:\";cin>>Director; cout<<\"主演:\";cin>>Star; cout<<\"库存量:\";cin>>Number; v=new video(Vname,Country,Type,Producer,Director,Star,Number); v->next=0; //碟片结点加入链表 if(vid) //若已经存在结点 { v2=vid; while(v2->next) //查找尾结点 { v2=v2->next; } v2->next=v; //连接 } else //若不存在结点(表空) { vid=v; //连接 } save(); cout<<\"\\\ ***添加成功***\\n\"< if(toupper(c)=='Y') { Addvideo(); return ; } else return ; } void application::Deletevideo(){ system(\"cls\"); char c; string Vname; cout<<\"\\n** 删除信息 **\\n\"; cout<<\"输入要删除的碟片名:\\"; cin>>Vname; cout< delete v1; } save(); cout<<\"\\***删除成功***\\n\"; cout<<\"是否继续删除(Y/N) \"< void application::Modifyvideo(string vidname){ video *v1; char c; v1=vid; while(v1){ if(v1->Vname==vidname) break; else{ v1=v1->next; } } if(v1!=NULL)//若找到结点 { system(\"cls\"); cout<<\"所要修改的碟片信息如下:\\n\"< case '4': cin>>v1->Producer; break; case '5': cin>>v1->Director; break; case '6': cin>>v1->Star; break; case '7': cin>>v1->Number;break; default: break; } }while(c!='8'); cout<<\"\ ***修改成功***\\n\"< int LeftMoney=0; //会员剩余金额 int nCount=0; //所借碟片数量 char a; cout<<\"\\n** 新增会员信息 **\\n\"; cout<<\"输入会员名:\\"; cin>>Name; cout< cout<<\"请输入会员编号:\\n\"; cin>>idPerson; cout<<\"初始金额:\"; cin>>LeftMoney; nCount=0; c=new Customer(idPerson,Name,LeftMoney,nCount); c->next1=0; if(cus){ c2=cus; while(c2->next1){ c2=c2->next1; } c2->next1=c; } else{ cus=c; } save(); cout<<\"\\\ ***注册成功***\\n\"< if(toupper(a)=='Y'){ Add(); return ; } else return ; } void application::Delete(){ system(\"cls\"); char a; string Name; cout<<\"\\n** 删除信息 **\\n\"; cout<<\"输入要删除的会员名:\\"; cin>>Name; cout< } else //未找到结点 cout<<\"未找到该会员!\\n\"; } void application::Modify(string Cname){ Customer *c1; char a; c1=cus; while(c1){ if(c1->Name==Cname) break; else{ c1=c1->next1; } } if(c1!=NULL)//若找到结点 { system(\"cls\"); cout<<\"所要修改的会员信息如下:\\n\"< cout< cout<<\"你选择了退出功能,程序将结束运行!\"; } } #endif #include 因篇幅问题不能全部显示,请点此查看更多更全内容