个人作业三——ATM管理系统
一 作业信息
| 博客班级 | https://edu.cnblogs.com/campus/ahgc/AHPU-se-JSJ18/ |
| ---- | ---- | ---- |
| 作业要求 | https://edu.cnblogs.com/campus/ahgc/AHPU-se-JSJ18/homework/11478 |
|作业目标| 理解作业内容,完成编译|
|学号|3180701316|
二 题目要求
编写一个ATM管理系统,语言不限,要求应包括以下主要功能:
(1)开户,销户
(2)查询账户余额
(3)存款
(4)取款
(5)转账(一个账户转到另一个账户)等...
三 代码提交
`#include<stdio.h>
include<string.h>
include<stdlib.h>
include<conio.h>
include<windows.h>
include<time.h>
define N sizeof(struct Account)
define M sizeof(struct Money)
struct Account //账户信息
{
char name[10]; //账号昵称
char password[18]; //密码
struct Account *next; //指针域
};
typedef struct Account Acc;
typedef Acc *Accp;
struct Money //钱
{
float money;
char time[10];//时间
char date[10];//日期
struct Money *next;
};
typedef struct Money mon;
typedef mon *monp;
//函数声明区
void HideCursor(); //隐藏光标
void toxy(int x, int y); //将光标移动到X,Y坐标处
void color(short x); //设置颜色
void menu(); //菜单
Accp ff(); //将文件中的内容读出
void signin(); //登陆或注册
void login(); // 注册账号
void logon(); // 账号登陆
void amend_password(); //修改密码
void add_money(); //存款
void find_money(); //查询
void get_money(); //取款
void transfer_money(); //转账
void save_account(Accp p); //将p所指向的内容存入文件中
void save_money(monp p); //将p所指向的内容存入文件中
float Sum(); //求余额
void over(); //退出系统
void list(); //账单明细
monp ss();
char _name[20],_password[18]; //全局变量记住当前登陆账户
void color(short x)
{
if(x>=0&&x<=15)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x);
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x);
}
}
void HideCursor() //隐藏光标
{
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void toxy(int x, int y) //将光标移动到X,Y坐标处
{
COORD pos = { x , y };
HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(Out, pos);
}
Accp ff() //将存账号的文件里的内容输出到链表中
{
FILE *fp; //文件指针
int n=0;
Accp head=NULL;
Accp p2,p;
fp=fopen("account","a+"); //以只读的方式打开文件
if(fpNULL)
{
printf("cannot open file\n");
}
else
{
while(!feof(fp)) //判断文件位置标志是否移动到文件末尾
{
n++;
p=(Accp)malloc(N); //向内存申请一段空间
fread(p,N,1,fp); //将fp所指向的文件中的内容赋给p
if(n1)
{
head=p;
p2=p;
}
else //创建链表
{
p2->next=p;
p2=p;
}
}
p2->next=NULL;
}
fclose(fp); //关闭文件
return head; //返回头指针
}
void menu() //菜单
{
system("cls"); //清屏
do{
color(14); //看着舒服的颜色
char t;
toxy(50,5);
printf(" 自动存取款机模拟系统");
toxy(50,6);
printf("当前账户为:%s",_name);
toxy(48,8);
printf("| 1.取款 |");
toxy(48,10);
printf("| 2.转账 |");
toxy(48,12);
printf("| 3.余额 |");
toxy(48,14);
printf("| 4.明细 |");
toxy(48,16);
printf("| 5.存款 |");
toxy(48,18);
printf("| 6.修改密码 |");
toxy(48,20);
printf("| 7.退出系统 |");
t=getch(); //利用不回显函数,输入t,可以不用手动按回车键
switch(t)
{
case '1':get_money();break;
case '2':transfer_money();break;
case '3':find_money();break;
case '4':list();break;
case '5':add_money();break;
case '6':amend_password();break;
case '7':over();break;
default :;break;
}
}while(1); //永远为真
}
void signin() //登陆或注册
{
system("cls");
color(12);
HideCursor(); //隐藏光标
char t;
toxy(50,5);
printf("自动存取款机模拟系统");
toxy(44,8);
printf("----------------------------");
toxy(45,10);
printf("请输入(1:登陆;2:注册.)");
toxy(44,12);
printf("----------------------------");
while(1)
{
t=getch();
switch(t)
{
case '1':logon();break;
case '2':login();break;
default :break;
}
}
}
void logon() // 账号登陆
{
system("cls"); //清屏
color(10); //设置颜色
Accp p,head;
head=ff(); //调用函数 ,返回值为头结点的指针
do{
p=head;
char t,c,k;
int i=0;;
toxy(50,5);
printf("自动存取款机模拟系统");
toxy(45,6);
printf("***********************");
toxy(45,8);
printf(" 登陆状态 ");
toxy(45,10);
printf(" 请输入您的账号:");
gets(_name);
toxy(45,12);
printf(" 请输入您的密码:");
for(;😉 //此处为输入密码不回显操作
{
k=getch(); //输入k
if(k'\r') //如果输入k为回车,则跳出循环
{
break;
}
else if(k'\b') //如果输入k为删除键
{
if(i>0) //如若密码还没完全删除
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
}
else //如果输入的k既不是删除键,也不是回车键
{
_password[i]=k; //把k的值赋给_password[i];
printf(""); //输出号,保护用户隐私
i++; //密码位数加1
}
}
_password[i]='\0';
while(p!=NULL&&strcmp(p->name,_name)!=0) //遍历链表,寻找当前输入的账户的账号
{
p=p->next;
}
if(p!=NULL) //如果p不为空
{
if(strcmp(p->password,_password)0) //如果输入的密码正确
{
toxy(48,16);
printf("正在登陆....");
Sleep(500); //暂停0.5秒
system("cls");
color(10);
toxy(48,10);
printf("登陆成功!");
break; //跳出循环
}
else //如果输入的密码错误
{
toxy(48,16);
printf("正在登陆....");
Sleep(500);
system("cls");
color(10);
toxy(46,8);
printf("-------------------------");
toxy(46,9);
printf("| |");
toxy(46,10);
printf("| 密码错误!是否继续? |");
toxy(46,12);
printf("| 1.是 2.否 |");
toxy(46,13);
printf("| |");
toxy(46,14);
printf("-------------------------");
while(1)
{
t=getch(); //输入t
if(t'1')
{
system("cls"); //清屏
color(10);
break;
}
else if(t'2') //如果输入t为n,进入开始界面
{
signin();break;
}
}
}
}
else //如果p为空,即输入的账号不正确
{
toxy(48,16);
printf("正在登陆....");
Sleep(500);
system("cls");
color(10);
toxy(46,8);
printf("-------------------------");
toxy(46,9);
printf("| |");
toxy(46,10);
printf("| 账号错误!是否继续? |");
toxy(46,11);
printf("| |");
toxy(46,12);
printf("| 1.是 2.否 |");
toxy(46,13);
printf("| |");
toxy(46,14);
printf("-------------------------");
while(1) //死循环防止其他按键干扰
{
c=getch();
if(c'1')
{
system("cls");
color(10);
break;
}
else if(c=='2')
{
signin();break;
}
}
}
}while(1); //永远为真
Sleep(500); //暂停0.5秒
menu(); //账号密码均正确,进入主菜单
}
void login() //注册账号
{
system("cls");
color(10);
Accp p1;
p1=(Accp)malloc(N); //向内存申请一段空间
do{
color(10);
char name[20],password[18],againpassword[18],c,k;
int i=0;;
toxy(50,5);
printf("自动存取款机模拟系统");
toxy(45,6);
printf("**************************");
toxy(45,8);
printf(" 正在注册");
toxy(45,10);
printf("* 请输入账号:");
gets(name);
toxy(45,12);
printf("* 请输入密码:");
for(;;) //此处为输入密码不回显操作
{
k=getch(); //输入k
if(k=='\r') //如果输入k为回车,则跳出循环
{
break;
}
else if(k=='\b') //如果输入k为删除键
{
if(i>0) //如若密码还没完全删除
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
}
else //如果输入的k既不是删除键,也不是回车键
{
password[i]=k; //把k的值赋给_password[i];
printf("*"); //输出*号,保护用户隐私
i++; //密码位数加1
}
}
password[i]='\0';
i=0;
toxy(45,14);
printf("* 请确认您的密码:");
for(;;) //此处为输入密码不回显操作
{
k=getch(); //输入k
if(k=='\r') //如果输入k为回车,则跳出循环
{
break;
}
else if(k=='\b') //如果输入k为删除键
{
if(i>0) //如若密码还没完全删除
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
}
else //如果输入的k既不是删除键,也不是回车键
{
againpassword[i]=k; //把k的值赋给_password[i];
printf("*"); //输出*号,保护用户隐私
i++; //密码位数加1
}
}
againpassword[i]='\0';
if(strcmp(password,againpassword)==0) //如果输入的两次密码均正确
{
strcpy(p1->name,name);
strcpy(p1->password,password);
toxy(48,16);
printf("正在注册....");
Sleep(500);
system("cls");
color(12);
toxy(48,10);
printf("注册成功!");
Sleep(500); //暂停0.5秒
break; //跳出循环
}
else //如果输入的两次密码不同
{
toxy(48,16);
printf("正在注册....");
Sleep(500);
system("cls");
color(12);
toxy(46,8);
printf("-----------------------------");
toxy(46,9);
printf("| |");
toxy(46,10);
printf("| 注册失败!是否继续注册? |");
toxy(46,11);
printf("| |");
toxy(46,12);
printf("| 1.是 2.否 |");
toxy(46,13);
printf("| |");
toxy(46,14);
printf("-----------------------------");
while(1)
{
c=getch();
if(c=='1')
{
system("cls");
color(12);
break;
}
else if(c=='2')
{
signin();
break;
}
}
}
}while(1); //永远为真
save_account(p1); //调用函数,将p1所指向的内容存储到文件中
toxy(48,12);
printf("正在自动为您登陆....");
Sleep(500);
menu(); //注册成功后进入主菜单
}
/修改密码
方法比较笨,这里是先将储存在文件中的账户信息
输出在一个链表中,遍历链表,寻找当前登陆的账户账号,修改该节点的p->password,
再将修改后的链表存到文件中,需要注意的是修改之后再存到文件中需要将该文件中的内容
清空/
void amend_password() //修改密码
{
system("cls"); //清屏
color(14); //看着舒服的颜色
HideCursor();
Accp p,head; //隐藏光标,看着更舒服
head=ff();
FILE fp;
do
{
color(14);
HideCursor(); //隐藏光标,看着舒服
p=head;
char password[18],newpassword[18],t,k;
int i=0;
toxy(50,5); //将光标移动到坐标为(50,5)的位置
printf("自动存取款机模拟系统");
toxy(50,8);
printf("修改密码");
toxy(48,10);
printf("请输入旧密码:");
for(;😉 //此处为输入密码不回显操作
{
k=getch(); //输入k
if(k'\r') //如果输入k为回车,则跳出循环
{
break;
}
else if(k'\b') //如果输入k为删除键
{
if(i>0) //如若密码还没完全删除
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
}
else //如果输入的k既不是删除键,也不是回车键
{
password[i]=k; //把k的值赋给_password[i];
printf(""); //输出号,保护用户隐私
i++; //密码位数加1
}
}
password[i]='\0';
i=0;
toxy(48,12);
printf("请输入新密码:");
for(;😉 //此处为输入密码不回显操作
{
k=getch(); //输入k
if(k'\r') //如果输入k为回车,则跳出循环
{
break;
}
else if(k'\b') //如果输入k为删除键
{
if(i>0) //如若密码还没完全删除
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
}
else //如果输入的k既不是删除键,也不是回车键
{
newpassword[i]=k; //把k的值赋给_password[i];
printf(""); //输出*号,保护用户隐私
i++; //密码位数加1
}
}
newpassword[i]='\0';
while(p!=NULL&&strcmp(p->name,_name)!=0)//遍历链表,寻找当前登陆账户的账号
{
p=p->next;
}
if(p!=NULL) //如果p不为空
{
if(strcmp(p->password,password)0) //如果旧密码输入正确
{
strcpy(p->password,newpassword); //将旧密码改为新密码
break; //跳出循环
}
else //如果旧密码输入错误
{
system("cls");
color(12);
toxy(46,8);
printf("--------------------------");
toxy(46,9);
printf("| |");
toxy(46,10);
printf("| 密码错误!是否继续? |");
toxy(46,11);
printf("| |");
toxy(46,12);
printf("| 1.是 2.否 |");
toxy(46,13);
printf("| |");
toxy(46,14);
printf("--------------------------");
while(1)
{
t=getch(); //输入t
if(t'1')
{
system("cls");
color(12);
break;
}
else if(t'2')
menu();
}
}
}
}while(1); //永远为真
p=head->next; //使p指向第二个结点
fp=fopen("account","w"); //先清空原文件内容再将修改后的信息写入文件
if(fpNULL)
{
printf("cannot open file\n");
}
if(fwrite(head,N,1,fp)!=1) //将head所指向的数据写入fp所指向的文件
{
printf("file write error\n");
}
fclose(fp); //关闭文件
fp=fopen("account","a"); // 打开account文件,方式为追加
while(p!=NULL) //p不为空就执行循环体
{
if(fwrite(p,N,1,fp)!=1) //将p所指向的1个大小为N的数据结构写入fp所指向的文件
{
printf("file write error\n");
}
p=p->next; //使p指向下一个结点
}
fclose(fp); //关闭文件
toxy(48,14);
printf("修改成功!正在跳转...");
Sleep(500); //暂停0.5秒
}
void save_account(Accp p1) //将p1所指向的内容存储到文件中
{
FILE *fp; //文件指针
fp=fopen("account","a"); //以追加的方式打开文件
if(fp==NULL)
{
printf("cannot open file\n");
}
if(fwrite(p1,N,1,fp)!=1) //将p1所指向的1个大小为N的数据结构写入fp所指向的文件中
{
printf("file write error\n");
}
fclose(fp); //关闭文件
}
void add_money() //存款
{
do
{
system("cls"); //清屏
color(11);
monp p;
char t;
char time[10],date[10];
p=(monp)malloc(M); //向内存申请一段空间
toxy(48,8);
printf("请输入您需要存入的金额:");
scanf("%f",&p->money);
getchar(); //吸收回车键
_tzset();
_strtime(time);
strcpy(p->time,time);
_strdate(date);
strcpy(p->date,date);
toxy(48,10);
printf("正在操作,请稍后....");
Sleep(500);
save_money(p);
system("cls");
toxy(46,8);
printf("-------------------------");
toxy(46,9);
printf("| |");
toxy(46,10);
printf("| 存入成功!是否继续? |");
toxy(46,12);
printf("| 1.是 2.否 |");
toxy(46,13);
printf("| |");
toxy(46,14);
printf("-------------------------");
while(1)
{
t=getch();
if(t'1')
{
break;
}
else if(t'2')
{
menu();
}
}
}while(1);
}
void find_money() //查询余额
{
system("cls");
color(13);
float sum=0;
sum=Sum();
toxy(46,12);
printf("余额为:%f",sum);
toxy(46,16);
printf("按任意键回到主菜单");
getch();
menu();
}
void get_money() //取款
{
do
{
system("cls");
color(11);
monp p;
float money,sum;
char t;
char time[10],date[10];
toxy(46,12);
printf("请输入您要取的金额:");
scanf("%f",&money);
getchar();//吸收回车键
sum=Sum();
if(money>sum) //如果要取的金额大于余额
{
toxy(46,14);
printf("余额不足,请重新输入!");
Sleep(500);
continue; //结束本次循环
}
p=(monp)malloc(M); //向内存申请一段空间
_tzset();
_strtime(time);
strcpy(p->time,time);
_strdate(date);
strcpy(p->date,date);
p->money=-money;
save_money(p);
toxy(46,14);
printf("正在操作,请稍后....");
Sleep(500);
system("cls");
toxy(46,8);
printf("-------------------------");
toxy(46,9);
printf("| |");
toxy(46,10);
printf("| 取款成功!是否继续? |");
toxy(46,12);
printf("| 1.是 2.否 |");
toxy(46,13);
printf("| |");
toxy(46,14);
printf("-------------------------");
while(1)
{
t=getch();
if(t'1')
{
break;
}
else if(t'2')
{
menu();break;
}
}
}while(1);
}
void list() //明细
{
system("cls");
color(10);
monp head,p;
int i=10;
head=ss();
p=head;
toxy(50,5);
printf(" 自动存取款机模拟系统");
toxy(54,6);
printf("账单明细");
toxy(30,7);
printf("-------------------------------------------------------------");
toxy(31,8);
printf("金 额 时 间 日 期");
toxy(30,9);
printf("-------------------------------------------------------------");
while(p!=NULL)
{
toxy(30,i);
if(p->money>=0)
{
printf("+%f %-24s%s",p->money,p->time,p->date);
}
else
{
printf("%f %-24s%s",p->money,p->time,p->date);
}
p=p->next;
i++;
}
toxy(50,i);
printf("请按任意键返回主菜单");
getch();
menu();
}
void transfer_money() //转账
{
do
{
system("cls");
color(10);
FILE *fp1;
monp p,head,p1;
float money,sum=0;
char name[20],t;
char time[10],date[10];
toxy(46,12);
printf("请输入您要转入的账号:");
gets(name);
toxy(46,14);
printf("请输入您要转出的金额:");
scanf("%f",&money);
getchar(); //吸收回车键
sum=Sum();
if(money>sum) //如果要转出的金额大于余额
{
toxy(46,16);
printf("余额不足!");
Sleep(500);
continue; //结束本次循环
}
fp1=fopen(name,"rb"); //以只读的方式打开名字为name的二进制文件
if(fp1NULL) //如果文件不存在
{
toxy(46,16);
printf("账户不存在!");
fclose(fp1);
Sleep(500);
continue;
}
fp1=fopen(name,"ab"); //以追加的方式打开名字为name的二进制文件
p=(monp)malloc(M); //向内存申请一段空间
p->money=-money;
_tzset();
_strtime(time);
strcpy(p->time,time);
_strdate(date);
strcpy(p->date,date);
save_money(p);
p1=(monp)malloc(M);
p1->money=money;
strcpy(p1->time,time);
strcpy(p1->date,date);
if(fwrite(p1,M,1,fp1)!=1) //将p1所指向的一个大小为M的节点 存入fp1所指向的文件中
{
printf("转账失败,请重试!");
continue;
}
fclose(fp1);
toxy(46,18);
printf("正在操作,请稍后....");
Sleep(500);
system("cls");
toxy(46,8);
printf("-------------------------");
toxy(46,9);
printf("| |");
toxy(46,10);
printf("| 转账成功!是否继续? |");
toxy(46,12);
printf("| 1.是 2.否 |");
toxy(46,13);
printf("| |");
toxy(46,14);
printf("-------------------------");
while(1)
{
t=getch();
if(t'1')
{
break;
}
else if(t=='2')
{
menu();
}
}
}while(1);
}
float Sum()
{
monp head=NULL,p;
float sum=0;
head=ss();
p=head;
while(p!=NULL)
{
sum+=p->money; //求和
p=p->next;
}
if(head==NULL)
sum=0;
return sum;
}
monp ss() //求余额
{
FILE *fp; //文件指针
monp p,head=NULL,p2,pre=NULL;
int n=0;
//float sum=0;
fp=fopen(_name,"ab+"); //以只读的方式打开名字为_name的二进制文件
if(fpNULL)
{
printf("cannot open file");
}
else
{
while(!feof(fp)) //判断标记是否移动到文件末尾
{
n++;
p=(monp)malloc(M); //向内存申请一段空间
fread(p,M,1,fp); //将fp所指向的文件中的一段大小为M的 内容赋给p
if(n1)
{
head=p;
p2=p;
}
else //创建链表
{
pre=p2;
p2->next=p;
p2=p;
}
p2->next=NULL;
}
}
fclose(fp); //关闭文件
if(pre!=NULL)
pre->next=NULL;
return(head); //返回sum值
}
void save_money(monp p) //将p所指向的内容存入文件中
{
FILE *fp; //文件指针
fp=fopen(_name,"ab"); //以追加的方式打开名字为_name的二进制文件
if(fp==NULL)
{
printf("cannot open file");
}
if(fwrite(p,M,1,fp)!=1) //将p所指向的一段大小为M的内容存入fp所指向的文件中
{
printf("write error");
}
fclose(fp); //关闭文件
}
void over() //退出软件
{
char t;
toxy(48,11);
printf("-----------------------");
toxy(48,12);
printf("| 您确定要退出吗? |");
toxy(48,14);
printf("| 1.确定 2.取消 |");
toxy(48,15);
printf("-----------------------");
while(1)
{
t=getch(); //输入t
switch(t)
{
case '1':
system("cls");
color(6);
toxy(48,10);
printf("正在安全退出....");
Sleep(1000); //暂停1秒
system("cls");
color(8);
toxy(48,10);
printf("已安全退出软件");
toxy(48,12);
printf("谢谢使用!");
toxy(48,14);
printf("by-by_");
exit(0); break; //终止程序
case '2':
menu(); break; //调用函数,进入菜单
default :break;
}
}
}
main() //
{
signin(); //调用函数
}
`
四 运行结果
主界面
注册
选择操作
存款
取款
转账
五 作业小结
psp2.1 | 任务内容 | 计划完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 8 | 8 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 20 | 20 |
Development | 开发 | 150 | 150 |
Analysis | 需求分析(包括学习新技术) | 14 | 6 |
Design Spec | 生成设计文档 | 6 | 6 |
Design Review | 设计复审 | 7 | 7 |
Coding Standard | 代码规范 | 4 | 3 |
Design | 具体设计 | 10 | 12 |
Coding | 具体编码 | 40 | 35 |
Code Review | 代码复审 | 10 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 3 | 3 |
Reporting | 报告 | 5 | 5 |
Test Report | 测试报告 | 5 | 12 |
Size Measurement | 计算工作量 | 2 | 3 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 10 | 5 |