数据结构课程设计实验报告.docx
《数据结构课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计实验报告.docx(35页珍藏版)》请在冰豆网上搜索。
数据结构课程设计实验报告
数据结构
课程设计报告
学院:
信息科学与工程学院
班级:
通信工程1301班
题目:
活期储蓄帐目管理系统
指导老师:
康松林
完成日期:
2015年7月16日
一、问题描述与基本要求
1.1问题描述
设计一个活期储蓄帐目管理系统
活期储蓄处理中,储户开户、销户、存入、支出活动频繁。
1.2基本要求
系统设计要求:
1、能比较迅速地实现插入,以实现储户开户的功能,储户开户时需输入的信息包括储户姓名,密码。
2、能比较迅速地通过储户的账户序号和密码找到储户的账户,并删除该账户,以实现销户的功能。
3、能比较迅速地通过储户的账户序号和密码找到储户的账户(密码不对时,可选择是否重新输入密码)实现账户登录的功能。
登录成功后,再通过修改链表结点数据域中的对应元素,以实现存款、取款、显示余额等功能,若取款时账户余额不足,输出提示信息“取款失败!
你账户上的金额不足!
”,并显示账户当前余额,并且提示重新输入合适的取款金额。
4、查找活期储蓄帐目管理系统当前存在的储户,当输出活期储蓄帐目管理系统没有账户时,输出提示信息“活期储蓄帐目管理系统没有账户”,当有账户时,输出所有账户的相关信息,包括储户姓名,帐号,密码,账户余额。
二、数据结构的设计
2.1数据结构的选择
课程设计题目的要求是,要较简单迅速地实现开户、销户、存款、取款、输出用户信息的功能,于是我很自然地想到了可以用单链表的结构,通过编写相应功能函数来实现建立新结点、删除结点、修改结点中数据域的内容、输出结点数据域中的内容等功能,即可满足课程设计题目的要求。
2.2单链表的定义
先定义单链表结点的数据域,数据域包括储户姓名、账户序号、账户密码、账户金额等储户信息,然后再定义链表结点,链表结点包括结点数据域和结点链域,最后再定义指向链表结点的指针。
以下为单链表的相关定义:
typedefstructListData//定义结点数据域
{
charname[3];//储户姓名
intaccount;//账户序号
charpassword[5];//账户密码
intmoney;//账户金额
}ListData;
typedefstructnode//定义链表结点
{
ListDatadata;//结点数据域
structnode*next;//结点链域
}ListNode;
typedefListNode*LinkList;//指向链表结点的指针
2.3重要函数的定义及说明
1、voidInitList(LinkList&L)//建立空链表
2、voidInsertList(LinkList&L)//插入链表结点,实现开户功能
(需要输入储户姓名和密码,以确定开户对象)
3、voidDeleteList(LinkList&L)//删除链表结点,实现销户功能
(需要输入账号和密码,以确定销户对象)
4、voidDeposit(LinkList&L,LinkListp)//储户存款、取款、显示余额(要先通过账号和密码登录,若取款时账户余额不足,输出提示信息,显示账户当前余额,并且提示重新输入取款金额。
)
5、voidSearch(LinkListL)//链表查找,实现用户登录功能
(需要输入账号和密码,以确定登录对象,密码输出错误时可选择是否重新输入密码)
6、voidPrintList(LinkListL)//输出链表,实现储户姓名,账号序号,密码,现有余额等相关信息。
(当输出活期储蓄帐目管理系统没有账户时,输出提示信息,当有账户时,输出所有账户的相关信息。
)
以下为重要函数的定义:
voidInitList(LinkList&L)//建立空链表
{
L=(ListNode*)malloc(sizeof(ListNode));
L->next=NULL;
}
voidInsertList(LinkList&L)//链表插入结点,实现开户功能,需输入储户姓名和密码
{
LinkListp;
p=(ListNode*)malloc(sizeof(ListNode));
printf("请输入你要开户的姓名(不超过4个字符):
");
scanf("%s",p->data.name);
number=number+1;
p->data.account=number;
printf("你开户的账号为:
%d\n",p->data.account);
printf("请输入你账号的密码(不超过6个字符):
");
scanf("%s",p->data.password);
p->data.money=0;
p->next=NULL;
if(L->next==NULL)//前插法
L->next=p;
else
{
p->next=L->next;
L->next=p;
}
printf("开户成功!
\n");
}
voidDeleteList(LinkList&L)//删除链表结点,实现销户功能(需要输入账号和密码)
{
LinkListp=L,q;
charmima[5];
ints;
printf("请输入你要销户的账号:
");
scanf("%d",&s);
printf("请输入该账号的密码:
");
scanf("%s",mima);
while(p->next!
=NULL)
{
if(p->next->data.account==s)
break;
p=p->next;
}
if(p->next!
=NULL)
{
while(strcmp(p->next->data.password,mima)!
=0)
{
printf("密码错误!
请重新输入:
");
scanf("%s",mima);
}
q=p->next;
p->next=q->next;
free(q);
printf("销户成功。
\n");
}
elseprintf("你所要销户的的账号不存在。
\n");
}
voidDeposit(LinkList&L,LinkListp)//储户存款、取款、显示余额
{
intm;
intn;
while
(1)
{
if(p!
=NULL)
{
printf("\n请输入数字选择功能:
1、存款2、取款3、查询余额4、退出账号:
");
scanf("%d",&m);
if(m==1)
{
printf("请输入你的存款金额:
");
scanf("%d",&n);
p->data.money=p->data.money+n;
printf("存款成功!
\n");
}
elseif(m==2)
{
printf("请输入你的取款金额:
");
gg:
scanf("%d",&n);
if((p->data.money-n)>=0)
{
p->data.money=p->data.money-n;
printf("取款成功!
\n");
}
else
{
printf("取款失败!
你账户上的金额不足!
\n");
printf("你的账户余额为:
%d\n",p->data.money);
printf("请输入合适的取款金额:
");
gotogg;
}
}
elseif(m==3)
{
printf("你账户的余额为:
%d\n",p->data.money);
}
elseif(m==4)
{
printf("账号退出成功。
\n");
return;
}
}
}
}
voidSearch(LinkListL)//链表查找,实现用户登录功能(需要输入账号和密码)
{
LinkListp=L->next;
inti;
charmima[5];
printf("请输入你要登录的账号:
");
scanf("%d",&i);
tt:
printf("请输入你的密码:
");
scanf("%s",mima);
while(p!
=NULL)
{
if(p->data.account==i)
break;
p=p->next;
}
if(p==NULL)
printf("不存在该账户\n");
else
{
if(strcmp(p->data.password,mima)==0)
printf("登录成功。
\n");
else
{
while(strcmp(p->data.password,mima)!
=0)
{
charj;
printf("密码错误\n");
printf("是否重新输入(是,从键盘输入Y)、(否,从键盘上输入N):
");
scanf("\n%c",&j);
if(j=='N')
{return;}
elseif(j=='Y')
{gotott;}
}
}
Deposit(L,p);
}
}
voidPrintList(LinkListL)//输出链表,实现储户信息输出
{
LinkListp=L->next;
if(p==NULL)
{
printf("活期储蓄帐目管理系统没有账户\n");
}
elseprintf("姓名帐号密码账户余额\n");
while(p!
=NULL)
{
printf("%s\t",p->data.name);
printf("%d\t%s\t\t%d\n",p->data.account,p->data.password,p->data.money);
p=p->next;
}
printf("请先输入enter键,再重新选择功能\n");
}
三、软件模块结构图
3.1大体模块关系图
3.2各模块具体分析
链表插入模块具体分析如下:
链表删除模块具体分析如下:
链表查找、存款、取款模块具体分析如下:
链表输出模块具体分析如下:
注:
以上具体分析中,无箭头的线段表示函数的调用关系,椭圆中的数据为输入、输出或传递的值,箭头表示值的方向。
四、程序流程图
^
注:
因为整个程序流程图太长,一页画不下,所以上图为大体流程图,上图中1—>A,2—>B,3—>C,4—>D间流程省略了,以下为1—>A,2—>B,3—>C,4—>D间详细流程图。
1—>A
2—>B
3—>C
4—>D
五、源程序
#include
#include
#include
intnumber=0;//定义的全局变量,用于开户
typedefstructListData//定义结点数据域
{
charname[3];//储户姓名
intaccount;//账户序号
charpassword[5];//账户密码
intmoney;//账户金额
}ListData;
typedefstructnode//定义链表结点
{
ListDatadata;//结点数据域
structnode*next;//结点链域
}ListNode;
typedefListNode*LinkList;//指向链表结点的指针
voidInitList(LinkList&L)//建立空链表
{
L=(ListNode*)malloc(sizeof(ListNode));
L->next=NULL;
}
voidInsertList(LinkList&L)//链表插入结点,实现开户功能,需输入储户姓名和密码
{
LinkListp;
p=(ListNode*)malloc(sizeof(ListNode));
printf("请输入你要开户的姓名(不超过4个字符):
");
scanf("%s",p->data.name);
number=number+1;
p->data.account=number;
printf("你开户的账号为:
%d\n",p->data.account);
printf("请输入你账号的密码(不超过6个字符):
");
scanf("%s",p->data.password);
p->data.money=0;
p->next=NULL;
if(L->next==NULL)//前插法
L->next=p;
else
{
p->next=L->next;
L->next=p;
}
printf("开户成功!
\n");
}
voidDeleteList(LinkList&L)//删除链表结点,实现销户功能(需要输入账号和密码)
{
LinkListp=L,q;
charmima[5];
ints;
printf("请输入你要销户的账号:
");
scanf("%d",&s);
printf("请输入该账号的密码:
");
scanf("%s",mima);
while(p->next!
=NULL)
{
if(p->next->data.account==s)
break;
p=p->next;
}
if(p->next!
=NULL)
{
while(strcmp(p->next->data.password,mima)!
=0)
{
printf("密码错误!
请重新输入:
");
scanf("%s",mima);
}
q=p->next;
p->next=q->next;
free(q);
printf("销户成功。
\n");
}
elseprintf("你所要销户的的账号不存在。
\n");
}
voidDeposit(LinkList&L,LinkListp)//储户存款、取款、显示余额
{
intm;
intn;
while
(1)
{
if(p!
=NULL)
{
printf("\n请输入数字选择功能:
1、存款2、取款3、查询余额4、退出账号:
");
scanf("%d",&m);
if(m==1)
{
printf("请输入你的存款金额:
");
scanf("%d",&n);
p->data.money=p->data.money+n;
printf("存款成功!
\n");
}
elseif(m==2)
{
printf("请输入你的取款金额:
");
gg:
scanf("%d",&n);
if((p->data.money-n)>=0)
{
p->data.money=p->data.money-n;
printf("取款成功!
\n");
}
else
{
printf("取款失败!
你账户上的金额不足!
\n");
printf("你的账户余额为:
%d\n",p->data.money);
printf("请输入合适的取款金额:
");
gotogg;
}
}
elseif(m==3)
{
printf("你账户的余额为:
%d\n",p->data.money);
}
elseif(m==4)
{
printf("账号退出成功。
\n");
return;
}
}
}
}
voidSearch(LinkListL)//链表查找,实现用户登录功能(需要输入账号和密码)
{
LinkListp=L->next;
inti;
charmima[5];
printf("请输入你要登录的账号:
");
scanf("%d",&i);
tt:
printf("请输入你的密码:
");
scanf("%s",mima);
while(p!
=NULL)
{
if(p->data.account==i)
break;
p=p->next;
}
if(p==NULL)
printf("不存在该账户\n");
else
{
if(strcmp(p->data.password,mima)==0)
printf("登录成功。
\n");
else
{
while(strcmp(p->data.password,mima)!
=0)
{
charj;
printf("密码错误\n");
printf("是否重新输入(是,从键盘输入Y)、(否,从键盘上输入N):
");
scanf("\n%c",&j);
if(j=='N')
{return;}
elseif(j=='Y')
{gotott;}
}
}
Deposit(L,p);
}
}
voidPrintList(LinkListL)//输出链表,实现储户信息输出
{
LinkListp=L->next;
if(p==NULL)
{
printf("活期储蓄帐目管理系统没有账户\n");
}
elseprintf("姓名帐号密码账户余额\n");
while(p!
=NULL)
{
printf("%s\t",p->data.name);
printf("%d\t%s\t\t%d\n",p->data.account,p->data.password,p->data.money);
p=p->next;
}
printf("请先输入enter键,再重新选择功能\n");
}
voidmain()
{
LinkListL;
InitList(L);
printf("************************************************************\n");
printf("欢迎进入活期储蓄账目管理系统,以下是相关功能及编号:
\n");
printf("1.储户开户(输入储户姓名,密码)\n");
printf("2.储户销户(输入账户序号,密码)\n");
printf("3.储户的账号存款、取款、余额查询\n");
printf("4.查看所有储蓄账户信息(输出储户姓名,帐户序号,密码,账户余额)\n");
printf("5.退出账目管理系统\n");
printf("************************************************************\n");
charj;
hh:
printf("\n请选择你需要的功能:
");
scanf("%c",&j);
getchar();
if(j>'5')
printf("输入有误,请重新选择操作:
\n");
if(j=='5')
{printf("您将退出账目管理系统!
\n");
exit(0);}
switch(j)
{
case'1':
InsertList(L);getchar();break;
case'2':
DeleteList(L);getchar();break;
case'3':
Search(L);getchar();break;
case'4':
PrintList(L);getchar();break;
default:
break;
}
gotohh;
}
六、调试分析
6.1程序错误修改及完善的过程
我这次的课程设计题目是根据我的学号选择的,当看到这个题目时,我觉得还算比较简单,因为我之前数据结构实验就做过单链表的插入、删除、查找、输出,而这次活期储蓄帐目管理系统要求的开户、销户、存款、取款、输出储户信息等功能,即可用单链表的相关功能函数来实现,于是我修改了之前写过的单链表的一些函数,以满足这次题目的要求,但在实验过程中仍出现了一些错误。
最终经过我的仔细检查和修改,最终编写出了符合要求的程序,还增加了一些功能。
1、由于之前编写过类似程序,所以写完程序后很快就可以运行了,但是运行结果存在问题,比如创建的新用户的账户序号不是从1按顺序递增的,而是永远是1,不会改变,错误如下图所示:
我仔细检查了一下InsertList函数的定义,意识到了错误所在,我原本以为用“p->data.account=0;p->data.account++;”这两条语句就可以达到开户时账户序号递增的目的,后来才意识到这样编写程序,每次新建用户都是重新赋0值,再自加,结果完全不对。
于是我定义了一个全局变量intnumber=0,然后将原来的“p->data.account=0;p->data.account++”“number=number+1;p->data.account=number;”运行后得到了如下的正确的结果:
2、我编写完程序后,觉得程序太过简单,又想到题目是活期储蓄帐目管理系统,那账户应该是有密码保证安全性的,于是我又在单链表结点的数据域中加入了一个新的元素password[5],并且还修改了后面相关函数的定义,确保在销户时,必须账户序号和密码相对应时才能销户成功,在存款、取款时也只有当账户序号和密码相对应时才能登录成功,选择存款、取款或显示余额等功能。
因此,函数定义中除了密码正确时的相关操作,还应有密码错误时的提示信息和相关操作。
于是,我在DeleteList函数和Search函数中加入了判断p->data.password与mima是否相等的语句,重要语句如下:
DeleteList函数定义中:
Search函数定义中:
修改了相关函数定义后,调用程序,又出现了如下错误:
errorC2065:
'strcmp':
undeclaredidentifier,我才意