1、 安徽科技学院 网络工程专业 《数据结构》课程设计 实验报告 学 院: 理学院 班 级:112班 组 长: 学 号: 成 员 开课学期: 2012年09月03号 实验日期: 2012年11月19号至12月16日 指导教师: 目录 1.《数据结构》课程设计目的和要求------------------------------------------------------
2、3 1.1.地位目的----------------------------------------------------------------------------------------------3 1.2内容要求----------------------------------------------------------------------------------------------3 1.3.与其它课程的联系----------------------------------------------------------
3、3 1.4.课程报告撰写----------------------------------------------------------------------------------------4 2任务书------------------------------------------------------------------------------------------------------4 3.正文-----------------------------------------------------
4、4 3.1.需求分析-----------------------------------------------------------------------------------------------4 3.2.概要设计-----------------------------------------------------------------------------------------------5 3.3.详细设计------------------------
5、6 3.4.程序源代码清单------------------------------------------------------------------------------------6 3.5.调试分析----------------------------------------------------------------------------------------------15 3.6.调试结果-------------
6、16 4.总结与体会----------------------------------------------------------------------------------------------20 6.参考文献-------------------------------------------------------------------------------------------------20
7、 1.《数据结构》课程设计目的要求 一、本课程的地位、目的 《数据结构》课程设计是计算机科学技术专业集中实践性环节之一,是学习完《数据结构》课程后进行的一次全面的综合练习。开设该课程设计的主要目的是: 1. 使学生进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序 中的使用方法。 2. 使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软件设计的能力。 3. 使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设计的基本能力。 二、课程设计的内容和要求 根据
8、课程设计的时间和个人能力,在老师的协助下选择适当难度的课程设计课题,用C/C++语言实现。 具体内容如下: 1、 需求分析 以无歧义的陈述说明程序设计的任务,强调的是程序要做什么?明确规定: 输入的形式,输出的形式和值的范围;程序所能达到的功能;测试的数据。 2、 概要设计 说明程序中用到的所有抽象数据类型的定义,主程序的流程以及各程序模块 之间的层次(调用)关系。 3、 详细设计 实现概要设计中定义的所有数据类型,对每个操作只需要写出伪代码算法,画出函数的调用关系图。 4、 调试分析 调试过程中遇到的问题并且是如何解决的以及对设计实现的回顾讨论和分析;算法的时空分析(包
9、括基本操作和主要算法的时空复杂度的分析)和改进设想;经验和体会等 5、 用户使用说明 说明用户如何使用你编写的程序,详细列出每一步的操作步骤。 6、 测试结果 列出测试结果,包括输入的数据和相应的输出数据。 三、与其它课程的联系 先修课程为《C语言程序设计》和《数据结构》等。 四、课程设计报告撰写 课程设计报告包括:封面、任务书、目录、正文和参考文献等。 正文包括以下几方面的内容: 1.需求分析 2.概要设计 3.详细设计 4.调试分析 5.测试结果 6.体会与总结 2.任务书 【题目描述】 设计一个ATM机仿真程序,该程序应该具有一下功能:
10、1) 可以让用户开设新的账户; (2) 可以完成对账户的查询功能; (3) 可以完成账户的存款功能; (4) 可以完成账户的取款功能; (5) 可以完成账户的密码进行修改功能 【题目要求】 (1)存储结构采用顺序表或链表; (2)用C语言知识和本学期所学算法实现各模块; (3)主函数设计一个菜单,通过菜单进入各模块测试。 3.正文 3.1需求分析 需设计的程序是模拟ATM机进行查询、存款、取款操作的一个程序,同时还添加了密码修改,模拟银行工作人员进行开户的功能。因为此程序是模拟对用户财产安全进行操作的程序,要求本程序要保证用户的信息的安全性,如输入密码时要用字符
11、覆盖,输入密码有上限,减少可能存在的程序漏洞。 要求此程序满足: 1. 正确性和健壮性:即此程序对一切合法的操作都能得出满足规格说明要求的结果,对 不合法的操作也要有正确的处理措施,使程序严谨,保证用户的信息和财产安全。 2.可读性:程序要尽量简明扼要,便于相关人员调试和修改。 3.时空效率:要求本程序执行时间尽可能短,占用的储存空间尽可能的少。 实验名称 ATM机仿真程序 实验场所 软件工程1号机房 3.2概要设计:程序的流程图如下所示: 开始界面 对原帐户操作 开户 出口 1 输入卡号 否 开户成功
12、 开户失败 是 输入密码 帐户操作菜单 否 是 选择语言 出口2 修改密码 取款 存款 查询 操作成功 开始界面 3.3详细设计: 本程序是ATM仿真程序,对于用户的所有信息是通过一个线性表COUNT来存储的,本程序总共设计了main menu(int)、languagemen()、query(float,int)、withdraw(float,int)、kaihu(psqlist p),changepw(psqlist,int,int),caozuo(
13、psqlist)等子函数来共同完成的,具体分析如下: 在主函数main() 里分成了四个模块。模块一是完成事先设置了10个用户的所有信息。模块2、3、4在一个开始界面(通过一个switch语句来完成),分别为开户、对原有用户操作和退出整个程序 模块2是完成对新用户的操作,通过函数kaihu( )来完成,给新用户注册一个卡号,接下来就是让用户设置密码,要输入两次,具体要用到getchar(),和putchar()等函数,当两次输入不一样时提示用户重新输入,用户完成后会退出kaihu( )函数,返回开始界面。 模块3是对用户账户操作的一个函数,首先要输入卡号和密码,当不正确时返回上一界面,当
14、输入正确时设置了两种语言选择,选择语言后进入操作菜单函数mainmenu,可划分为五个小模块;模块一是查询账户余额函数query;模块二是存款函数deposit;模块三是取款函数withdraw;模块四是密码修改函数changepw;模块五是返回上一界面函数exit()。 本程序通过各个模块的组合连接共同在一起完成ATM仿真程序的开户、查询、存款、取款、修改密码等有关操作。 3.4程序源代码清单: #include"stdio.h" #include"string.h" #include"stdlib.h" #include"conio.h" #include"ctype.h"
15、 void mainmenu(int); //-------------账户菜单 int languagemenu(); //-------------语言选择 void query(float,int); //---------查询当前余额 float deposit(float,int);//--------存钱 float withdraw(float,int);//-----------取钱 int true1(int a[]); //密码确认函数 typedef struct { float money; int key[
16、6]; }datatype; typedef struct { //储存用户信息的线性表 datatype data[50]; int length; }sqlist,*psqlist; psqlist init_sqlist() //线性表的初始化 { psqlist count; count=(psqlist)malloc(sizeof(sqlist)); if(count) count->length=0; return count; } psqlist kaihu(psqlist p)//-----------------开户函
17、数 { system("cls"); psqlist pl=p; int i,j; pl->length=pl->length+1; while(1) { char a[7]={'\0'},b[7]={'\0'}; printf("您的卡号是:%d\n",pl->length); printf("请设置您的账号密码"); for(i=0;i<6;i++) { a[i]=getch(); putchar('*'); } printf("\n");
18、 printf("请再一次输入您的密码"); for(i=0;i<6;i++) { b[i]=getch(); putchar('*'); } if(strcmp(a,b)==0) { for(j=0;j<6;j++) pl->data[pl->length].key[j]=(int)b[j]-48; printf("\n"); printf("=============================
19、\n"); printf("密码设置成功\n"); printf("请输入您要预存的金额:"); scanf("%f",&(pl->data[pl->length].money)) ; printf("恭喜您开户成功\n"); break; printf("=============================\n"); } else { printf("\n"); printf("==========
20、\n"); printf("两次密码输入不一致\n"); printf("按任意键键后从新输入\n"); printf("=============================\n"); getch(); } system("cls"); } printf("按任意键继续\n"); getch(); system("cls"); return pl; } psqlist cha
21、ngepw(psqlist q,int k,int islan)//------密码修改函数 { psqlist pa=q; int i; char b[7]={'\0'}, p[7]={'\0'}; if(islan) { while(1) { system("cls"); printf("==============================\n"); printf("Please enter your new password:"); for(i=0;i<6;i++)
22、 { b[i]=getch(); putchar('*'); } printf("\n"); printf("Please enter your new password once again:"); for(i=0;i<6;i++) { p[i]=getch(); putchar('*'); } printf("\n"); if(strcmp(b,p)==0)
23、 { for(i=0;i<6;i++) pa->data[k].key[i]=(int)p[i]-48; printf("Congratulations on your password successfully changed\n"); printf("==============================\n"); break; } else { printf("The two codes are not the same\n");
24、 printf("Press any key to boot from the new input\n"); printf("==============================\n"); getch(); } } } else { while(1) { system("cls"); printf("==============================\n"); printf(
25、"请输入您的新密码:"); for(i=0;i<6;i++) { b[i]=getch(); putchar('*'); } printf("\n"); printf("请再一次输入您的新密码:"); for(i=0;i<6;i++) { p[i]=getch(); putchar('*'); } printf("\n"); if(strcmp(b,p)=
26、0) { for(i=0;i<6;i++) pa->data[k].key[i]=(int)p[i]-48; printf("恭喜您密码修改成功\n"); printf("==============================\n"); break; } else { printf("两次密码输入不一样\n"); printf("按任意键后从新输入\n");
27、 printf("==============================\n"); getch(); } } } printf("按任意键继续\n"); getch(); return pa; } int caozuo(psqlist count) //对账户的操作菜单函数 { system("cls"); int exit=0,k,m,language; char in; printf("请输入卡
28、号:"); scanf("%d",&k); if (k<=0) printf("此卡无效"); else if( k <=count->length) { m=true1(count->data[k].key); if(m) { printf("\n"); printf("按任意键确定密码:"); getch(); language=languagemenu(); while(!exit) { mainmenu(
29、language); in=getch(); switch(in) { case '1':query(count->data[k].money,language);break; case '2':count->data[k].money=deposit(count->data[k].money,language);break; case '3':count->data[k].money=withdraw(count->data[k].money,language);break; case '4':count=change
30、pw(count,k,language);break; case '5':return 0; } } } else printf("密码输入已达上限"); } else printf("此卡无效"); getch(); return 1; } int main (){ int i,j,y; char on; psqlist count=init_sqlist(); for(j=1;j<11;j++) { count->data[j].money=(float)(1000+10
31、0*j);//输入用户的最初帐户金额 for(i=0;i<6;i++) //输入用户账号的密码 count->data[j].key[i]=j-1; count->length++; } int exit1=0; while(!exit1) { system("cls"); printf("=========================\n"); printf("1.开户 \n
32、"); printf("2.对原卡进行操作 \n"); printf("3.exit1 \n"); printf("=========================\n"); on=getch(); switch(on) { case'1':count=kaihu(count); break; case'2':caozuo(count); break; case'3':return 0;
33、} } system("pause"); return 0; } int true1(int a[]) //判断密码正误 { char b[7]={'\0'}; int p[6], i=0,j=0; printf("请输入密码:"); while(j<3) { for(i=0;i<6;i++) { b[i]=getch(); putchar('*'); } for(i=0;i<6;i++) p[i]=(int)b[i]-48;
34、 i=0; while(i<6) { if(a[i]==p[i]) i++; else break; } j++; if(i==6) break; printf("\n"); if(j<=2) printf("密码错误请从新输入:"); } if(i==6) return 1; return 0; } int languagemenu() { char input; system("cls");
35、//-----------清除屏幕 printf("*************************\n"); printf("* 1. 中文 *\n"); printf("* 2. English *\n"); printf("*************************\n"); input=getch(); while(1) { switch(input) { case'1':return 0; case'2':return 1; default:input=getch()
36、 } } } void mainmenu(int is_lan) { system("cls"); //-----------清除屏幕 if(is_lan) { printf("**************************\n"); printf("| 1. Query |\n"); printf("| 2. Deposit |\n"); printf("| 3. Withdraw |\n"); printf("| 4. change pass
37、word |\n"); printf("| 5. Exit |\n"); printf("**************************\n"); } else { printf("*************************\n"); printf("* 1. 查询 *\n"); printf("* 2. 存钱 *\n"); printf("* 3. 取钱 *\n"); printf("* 4. 修改密码
38、 *\n"); printf("* 5. 退出 *\n"); printf("*************************\n"); } } void query(float money,int lan) { system("cls"); //-----------清除屏幕 if(lan) { printf("========================\n"); printf("rest ¥ %.2f\n",money); printf("press any key to continue
39、\n"); printf("========================\n"); } else { printf("========================\n"); printf("此账户有 ¥ %.2f\n",money); printf("按任意继续\n"); printf("========================\n"); } getch(); } float deposit(float money,int is_lan) { float input; system("cls"); //
40、清除屏幕 if(is_lan) { printf("*************************\n"); printf("the number of money: ¥"); scanf("%f%*c",&input); printf("press any key to continue\n"); printf("*************************\n"); } else { printf("*************************\n"); printf("输入您要存的钱的数目
41、 ¥"); scanf("%f%*c",&input); printf("按任意键继续\n"); printf("*************************\n"); } getch(); return money+input; } float withdraw(float money,int is_lan) { float input; if(is_lan) { while(1) { system("cls"); printf("========================\n"); print
42、f("the number of money: ¥");
scanf("%f%*c",&input);
if(input 43、system("cls");
printf("========================\n");
printf("输入您要取钱的数目: ¥");
scanf("%f%*c",&input);
if(input 44、return money-input;
}
3.4调试分析:
由于本程序需要完成查询、取款、存款以及修改密码、开户等功能,所以在写程序时需要把各个模块先调试好,再把各模块在main函数里用switch语句连接起来。
在调试各个模块时我们遇到了不同的问题,最后在通过查阅资料和网络以后问题得到了解决。我们遇到的问题如下:
问题一:对原账户的操作。既然是ATM机仿真程序,自然要保证用户的账户信息安全。如当输入密码时,在开始的时候,编号的子程序只能让用户输入密码,而且密码同时也会显示在屏幕上,这样就使得密码信息容易暴露,造成密码泄露,后来通过网上查询和我们的仔细思 45、考,经过调试,我们最终用for(i=0;i<6;i++){a[i]=getch();putchar(*);}解决了问题。在经过查询、取款等程序以后,我们应该以用户的需要来设置继续或者退出,这个问题我们的解决方案时:在每个子程序结束时用一个getch();语句来继续,再把各个子程序用switch语句封装在一个mainmenu函数里面,通过不断地调试和改进,最终达到了需求。
问题二:账户的问题,既然是atm机仿真程序
程序,那么就要能够存储新老用户的信息。设计的方案:用线性表来存储用户的账号信息,在主函数main里事先设计一些用户的信息,包括用户账号的密码和账上金额等,以供调试时来用。另外是开 46、新户问题,要保证能够开户成功而且也能够保存信息以供接下来对账户的相关操作又是一个问题。解决方案:把开户单作为一个子函数,对用户设定密码时同样使用for(i=0;I,6;i++){a[i]=getch();putchar(‘*’);这个循环语句来完成。为保证账户开户能够成功,设置了让用户要输入两次面膜的操作,两次一样时,用户才可输入要预存的金额,之后提示开户成功接着退出。两次不一样时,会提示按任意键后继续,用getch()来完成这个操作。
最后,把开户函数和对原有用户操作放在函数中,用语句来完成连接操作。就这样通过对各个模块的调试分析和改进,最后完成了ATM机仿真程序,达到了设计要求的所有功能 47、
3.5测试结果:
========================
1.开户
2.对原卡操作
3.exit1
========================
1
您的卡号是:11
请设置您的账号密码******
请再一次输入您的密码******
密码设置成功请输入您要预存的金额3000
恭喜您开户成功
按任意键键继续
========================
1.开户
2.对原卡操作
48、 3.exit1
========================
2
请输入卡号:11
请输入密码:******
密码错误请从新输入:******
密码错误请从新输入:******
=========================
* 1.中文 *
* 2.English *
* 3.exit *
=========================
1
*****************************
* 1.查询 49、 *
* 2.存钱 *
* 3.取钱 *
* 4.修改密码 *
* 5.出口 *
*****************************
1
========================
此账户有 ¥ 3000.00
按任意继续
========================
A
*****************************
* 1.查询 50、 *
* 2.存钱 *
* 3.取钱 *
* 4.修改密码 *
* 5.出口 *
*****************************
3
==========================
输入您要取钱的数目:¥300
按任意键继续
******************************
W
*****************************
* 1.查询






