自动存取款机模拟系统
模拟实现一个自动存取款的系统,系统以文本菜单形式工作,要求具备以下功能:
登录功能:用户输入账户名和密码,可以登录ATM。
查询功能:登陆后,可以查询存款余额。
取款功能:登陆后,可以取款。注意:取款额不能超过存款余额。
转账功能:登陆后,可以向其他账户转账。
存款功能:登陆后,可以向账户中存款。
1.系统以文本菜单的形式显示
2.数据存储采用文件形式
3.标准的C输入输出
4.功能完善
代码如下:
#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 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(); //求余额
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);
}
Accp ff() //将存账号的文件里的内容输出到链表中
{
FILE *fp; //文件指针
int n=0;
Accp head=NULL;
Accp p2,p;
fp=fopen("account","a+"); //以只读的方式打开文件
if(fp==NULL)
{
printf("cannot open file\n");
}
else
{
while(!feof(fp)) //判断文件位置标志是否移动到文件末尾
{
n++;
p=(Accp)malloc(N); //向内存申请一段空间
fread(p,N,1,fp); //将fp所指向的文件中的内容赋给p
if(n==1)
{
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;
printf(" 自动存取款机模拟系统\n");
printf("当前账户为:%s\n",_name);
printf("| 1.取款 |\n");
printf("| 2.转账 |\n");
printf("| 3.余额 |\n");
printf("| 4.存款 |\n");
t=getch(); //利用不回显函数,输入t,可以不用手动按回车键
switch(t)
{
case '1':get_money();break;
case '2':transfer_money();break;
case '3':find_money();break;
case '4':add_money();break;
default :;break;
}
}while(1); //永远为真
}
void signin() //登陆或注册
{
system("cls");
color(12);
HideCursor(); //隐藏光标
char t;
printf("----------------------------\n");
printf("请输入(1:登陆;2:注册.\n)");
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;;
printf("***************************");
printf(" 登陆状态 ");
printf("* 请输入您的账号:");
gets(_name);
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) //如果输入的密码正确
{
printf("正在登陆....");
Sleep(500); //暂停0.5秒
system("cls");
color(10);
printf("登陆成功!");
break; //跳出循环
}
else //如果输入的密码错误
{
printf("正在登陆....");
Sleep(500);
system("cls");
color(10);
printf("-------------------------\n");
printf("| 密码错误!是否继续? |\n");
printf("| 1.是 2.否 |\n");
printf("-------------------------");
while(1)
{
t=getch(); //输入t
if(t=='1')
{
system("cls"); //清屏
color(10);
break;
}
else if(t=='2') //如果输入t为n,进入开始界面
{
signin();break;
}
}
}
}
else //如果p为空,即输入的账号不正确
{
printf("正在登陆....");
Sleep(500);
system("cls");
color(10);
printf("-------------------------\n");
printf("| 账号错误!是否继续? |\n");
printf("| 1.是 2.否 |\n");
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;;
printf("**************************\n");
printf(" 正在注册\n");
printf("* 请输入账号:");
gets(name);
printf("\n* 请输入密码:");
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;
printf("\n* 请确认您的密码:");
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);
printf("正在注册....\n");
Sleep(500);
system("cls");
color(12);
printf("注册成功!\n");
Sleep(500); //暂停0.5秒
break; //跳出循环
}
else //如果输入的两次密码不同
{
printf("正在注册....");
Sleep(500);
system("cls");
color(12);
printf("| 注册失败!是否继续注册? |\n");
printf("| 1.是 2.否 |\n");
printf("-----------------------------\n");
while(1)
{
c=getch();
if(c=='1')
{
system("cls");
color(12);
break;
}
else if(c=='2')
{
signin();
break;
}
}
}
}while(1); //永远为真
save_account(p1); //调用函数,将p1所指向的内容存储到文件中
printf("正在自动为您登陆....\n");
Sleep(500);
menu(); //注册成功后进入主菜单
}
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); //向内存申请一段空间
printf("请输入您需要存入的金额:\n");
scanf("%f",&p->money);
getchar(); //吸收回车键
_tzset();
_strtime(time);
strcpy(p->time,time);
_strdate(date);
strcpy(p->date,date);
printf("正在操作,请稍后....\n");
Sleep(500);
save_money(p);
system("cls");
printf("| 存入成功!是否继续? |\n");
printf("| 1.是 2.否 |\n");
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();
printf("余额为:%f\n",sum);
printf("按任意键回到主菜单");
getch();
menu();
}
void get_money() //取款
{
do
{
system("cls");
color(11);
monp p;
float money,sum;
char t;
char time[10],date[10];
printf("请输入您要取的金额:\n");
scanf("%f",&money);
getchar();//吸收回车键
sum=Sum();
if(money>sum) //如果要取的金额大于余额
{
printf("余额不足,请重新输入!\n");
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);
printf("正在操作,请稍后....\n");
Sleep(500);
system("cls");
printf("| 取款成功!是否继续? |\n");
printf("| 1.是 2.否 |\n");
while(1)
{
t=getch();
if(t=='1')
{
break;
}
else if(t=='2')
{
menu();break;
}
}
}while(1);
}
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];
printf("请输入您要转入的账号:\n");
gets(name);
printf("请输入您要转出的金额:\n");
scanf("%f",&money);
getchar(); //吸收回车键
sum=Sum();
if(money>sum) //如果要转出的金额大于余额
{
printf("余额不足!\n");
Sleep(500);
continue; //结束本次循环
}
fp1=fopen(name,"rb"); //以只读的方式打开名字为name的二进制文件
if(fp1==NULL) //如果文件不存在
{
printf("账户不存在!\n");
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);
printf("正在操作,请稍后....\n");
Sleep(500);
system("cls");
printf("| 转账成功!是否继续? |\n");
printf("| 1.是 2.否 |\n");
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(fp==NULL)
{
printf("cannot open file");
}
else
{
while(!feof(fp)) //判断标记是否移动到文件末尾
{
n++;
p=(monp)malloc(M); //向内存申请一段空间
fread(p,M,1,fp); //将fp所指向的文件中的一段大小为M的 内容赋给p
if(n==1)
{
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); //关闭文件
}
main() //简洁明了的主函数~~~
{
signin(); //调用函数
}