c语言atm取款机 链表,C语言模拟ATM机

《C语言模拟ATM机》由会员分享,可在线阅读,更多相关《C语言模拟ATM机(33页珍藏版)》请在人人文库网上搜索。

1、一、 实验目的通过设计一个ATM机模拟操作的程序,全面运用课程的主要知识点,巩固对模块化程序设计、文件操作的理解,提高软件编程能力。二、 实验要求要求每人独立完成设计,编写一个ATM机模拟操作程序。提交实验报告、源程序、程序运行截图。1. 程序具有以下功能:1) 登录系统:输入卡号(16位)、密码(6位),只有卡号、密码同时正确(帐户信息存放在文件中)才能进入系统;2) 操作功能:l 查询:查询帐户的存款余额。按任意键返回主菜单;l 修改密码:连续输入两次新密码(两次输入结果完全相同)后,新密码取代旧密码,并存放到帐户信息文件中。之后可返回主菜单;l 取款:输入50或100的倍数模拟为取款金额。

2、,请注意:取款金额不得超过帐户余额,操作后帐户余额应相应减少。之后可返回主菜单;l 存款:输入50或100的倍数模拟为存款金额,现假设存款金额不得超过20000元,操作后帐户余额应相应增加。之后可返回主菜单;l 转帐:先输入一个帐户号(已保存在帐户信息文件中),然后显示一部分用户名(如:张*山),储户确认无误后,再输入50或100的倍数模拟为转帐金额,请注意:转帐金额不得超过帐户余额,操作后帐户余额应相应减少。之后可返回主菜单;l 退出:退出系统。2. 定义如下结构体类型:l “日期”结构体Date:成员有:year(年)、month(月)、day(日);l “帐户”结构体Account:成员。

3、有:no(帐户号)、name(姓名)、balance(余额)l “存取款记录”结构体Record,:成员有:no(帐户号)、date(日期)、number(数量,可正可负,正表示存款,负表示取款)3. 帐户信息存放在accounts.txt文件,储户存取款记录保存在records.txt中;4. 采用模块化程序设计方法来实现,即main()显示主菜单、调用相关函数实现相应功能,起主控作用。5. 附加功能:l 储户一天内输错密码的次数不能超过3次,否则无法进入系统;l 应避免输入存款金额、取款金额为负数等异常情况的出现。三、 程序已经实现的功能点实验要求均已实现。此外还有:1. 卡号、密码位数输。

4、错时,提示并返回重新输入,2. 简化取款时的输入3. 转账时,转账账户为原账户时,提示并返回重新输入4. 在多个模块中添加了退出功能,无需回到主菜单即可退出系统5. 在查询模块中加入了存取记录明细查询四、 程序运行截图及说明1. 登陆模块1) 卡号不为16位时,输出提示并返回重新输入2) 卡号不存在时,输出提示并返回重新输入3) 密码位数输错时,输出提示并返回重新输入密码,不作为密码错误处理,也无需重新输入卡号4) 密码连续输错三次时,锁定卡号,今日无法登录2. 登录后的系统主菜单3. 查询模块1) 查询模块主菜单2) 查询明细4. 取款模块1) 当余额不足50时,无法进入取款模块2) 取款模。

5、块主菜单3) 便捷取款4) 手动输入取款金额输错时,返回重新输入5) 取款后的菜单6) 取款完成后选择显示余额5. 存款模块1) 解决输入错误问题2) 存款成功6. 密码修改模块1) 原密码输错时,返回重新输入,不提供退出功能2) 密码位数输错、两次输入新密码不一致时,返回重新输入3) 输入无误时7. 转账模块1) 转入卡号位数输错时,提示并返回重新输入2) 未查找到该卡号时,输出提示,提供退出功能,键入除*外任意键重新输入3) 转入卡号与当前卡号相同时,输出提示4) 输出转入卡账户的部分用户名5) 解决转账金额输错的问题6) 转账成功五、 采用的主要技术1. 宏定义:由于本程序的printf。

6、语句较多,为了便于编写,故用PR代替2. 链表:账户信息采用链表结构,内存动态分配,使用内存无限制,可以扩展到所有可以使用的内存3. switch多分支选择结构4. 文本文件的读写5. 利用time.h头文件,简便地获取系统日期6. system()函数和fflush()函数的简单使用六、 设计心得1. 各函数的功能要相对独立,逐步求精。2. 如果函数的参数为指针,且仅作为输入参数,则应在类型前加const,以防止该指针在函数体内被意外修改附:程序代码/*运行本程序前,请在本程序根目录下建立文件“accounts.txt”,格式如下:*卡号1(16位)姓名1账户余额1密码1*卡号2(16位)姓。

7、名2账户余额2密码2*/#include #include #include #include #define PR printftypedef structshort int year;short int month;short int day;Date;/日期typedef struct Accountchar no17;char name20;double balance;char password7;struct Account* next;Account;typedef structchar no17;Date date;double number;Record;/记录Account。

8、 *head = NULL;/账户信息链表表头Account *now_acc = NULL;/当前账户 /*函数申明*/void InitializeAccount();/导入账户信息/-char LockAccountTopic(const char *no);/检测账户是否被锁定void LockAccount(const char *no);/锁定账户/-void Login();/登录Account* FindbyNo(const char *no);/查找卡号对应账户信息在链表中的地址/-void Demand();/查询主菜单void PrintBalance();/输出余额vo。

9、id Printetail();/输出明细/-void Modifiy();/修改密码/-void Withdrawal();/取款主界面void WithdrawalOt(long money);/取款/-void Depositing();/存款/-void Transfer();/转账char *CoverUpName(const char *name);/掩盖部分用户名/-void Log(double money, const char *no);/将存款记录写入文件中void Save();/保存账号信息void FreeData();/释放链表空间/-int main()char。

10、 choose;InitializeAccount();/导入账户信息Login();/登录dosystem(cls);PR(tt n);PR(tt 请选择服务 n);PR(tt+-+-+ +-+-+n);PR(tt|5|33转 账| |查 询32|1|n);PR(tt+-+-+ +-+-+nn);PR(tt +-+-+n);PR(tt |取 款32|2|n);PR(tt +-+-+nn);PR(tt +-+-+n);PR(tt |存 款32|3|n);PR(tt +-+-+nn);PR(tt+-+-+ +-+-+n);PR(tt|0|33退出系统| |修改密码32|4|n);PR(tt+-+。

11、-+ +-+-+nn);PR(请选择服务:);fflush(stdin);choose = getchar();switch (choose)case 1: Demand(); break;/查询case 2: Withdrawal(); break;/取款case 3: Depositing(); break;/存款case 4: Modifiy(); break;/修改密码case 5: Transfer(); break;/转账case 0: FreeData(); return 0;/退出default:printf(输入错误,请重新选择n); /解决用户可能的输入错误system(p。

12、ause); while (1);return 0;/*导入账户信息*/void InitializeAccount()FILE *fp;Account temp;PR(系统初始化中,请稍侯.n);if (!(fp = fopen(accounts.txt, r)PR(07);/响铃PR(读取帐户信息失败,请在本程序根目录建立帐户信息文件(accounts.txt)。格式如下:n);PR(卡号1(16位)姓名1账户余额1密码1n);PR(卡号2(16位)姓名2账户余额2密码2n);PR(n);exit(0);while (fscanf(fp, %s %s %lf %s, temp.no, te。

13、mp.name, &temp.balance, temp.password) = 4)/读入账户信息Account *t = head;head = (Account*)malloc(sizeof(Account);*head = temp;head-next = t;fclose(fp);system(cls);/清除“系统初始化中,请稍侯.”提示/*登录*/void Login()dochar no17;system(cls);PR(nnnnttt请输入16位卡号:);fflush(stdin);gets(no);if (strlen(no) != 16)PR(卡号应为16位n);syst。

14、em(pause);system(cls);continue;if (LockAccountTopic(no)/当该卡号被锁定时PR(07);/响铃PR(nn您的登陆密码今日连续输错三次,已被临时锁定,次日将自动解锁,或当日持本人有效证件到柜台办理密码重置。nn);system(pause);continue;if (!(now_acc = FindbyNo(no)/将卡号对应信息在链表的地址赋给now_acc/当卡号不存在时PR(nn此卡号不存在,请重新输入!nn);system(pause);continue;char a = 2;/计算剩余可输错密码次数dochar password7;。

15、system(cls);PR(nnnnttt请输入16位卡号:%sn, now_acc-no);PR(nnttt请输入6位密码:);fflush(stdin);scanf(%s, password);if (strlen(password) != 6)PR(密码应为6位n);system(pause);system(cls);continue;if (!strcmp(now_acc-password, password)return;/密码正确,回到主函数if (a = 0)/输错密码三次,锁定账户PR(nn您的登陆密码今日连续输错三次,已被临时锁定,次日将自动解锁,或当日持本人有效证件到柜台。

16、办理密码重置。nn);LockAccount(no);break;PR(07);/响铃PR(密码输入错误,您还可以尝试%c次nn, a-);system(pause); while (1); while (1);/*检测账户是否被锁定*/char LockAccountTopic(const char *no)/被锁定则返回0FILE *fp;char CruuentTime11;/当前日期char ArchiveTime11;/锁卡档案日期char t17;if (!(fp = fopen(LockAccount.txt, a+)/课本上讲以“a”方式打开文件,若文件不存在,会出错。VS20。

17、13实测,并不会出错,而是新建。为免第一次使用本程序时,根目录下没有LockAccount.txt而导致出错,故此处不采用“r”方式。PR(07);/响铃PR(LockAccount.txt无法打开nn);exit(0);rewind(fp);/获取当前日期time_t rawtime;struct tm * timeinfo;time(&rawtime);/获取时间,以秒计,从1970年1月一日起算,存于rawtimetimeinfo = localtime(&rawtime);/转为当地时间,tm 时间结构strftime(CruuentTime, 11, %Y-%m-%d, timein。

18、fo);/格式化时间fgets(ArchiveTime, 11, fp);/获取锁卡档案时间if (strcmp(ArchiveTime, CruuentTime)/若无锁卡档案,或锁卡档案日期与当前日期不同,则无账户被锁定fclose(fp);return 0;while (fscanf(fp, %s, t) = 1)if (!strcmp(t, no)/锁卡档案中,包含此卡号,返回1fclose(fp);return 1;fclose(fp);return 0;/锁卡档案中,不含此卡号,返回0/*查找卡号对应账户信息在链表中的地址*/Account* FindbyNo(const char。

19、 *no)for (Account *i = head; i; i = i-next)if (!strcmp(i-no, no)return i;return NULL;/*锁定账户*/void LockAccount(const char *no)FILE *fp;char CruuentTime11;/当前日期char ArchiveTime11;/锁卡档案日期if (!(fp = fopen(LockAccount.txt, r)PR(07);/响铃PR(error on open LockAccount.txt file!nn);exit(0);/获取当前日期time_t rawtim。

20、e;struct tm * timeinfo;time(&rawtime);/获取时间,以秒计,从1970年1月1日起算,存于rawtimetimeinfo = localtime(&rawtime);/转为当地时间,tm 时间结构strftime(CruuentTime, 11, %Y-%m-%d, timeinfo);/格式化时间fgets(ArchiveTime, 11, fp);fclose(fp);if (strcmp(ArchiveTime, CruuentTime)/若档案日期与当前日期不同,则说明档案已过期或无档案,新建记录。if (!(fp = fopen(LockAccou。

21、nt.txt, w)PR(07);/响铃PR(error on open LockAccount.txt file!nn);exit(0);fprintf(fp, %sn, CruuentTime);else/若记录日期与当前日期相同,则追加记录if (!(fp = fopen(LockAccount.txt, a)PR(07);/响铃PR(error on open LockAccount.txt file!nn);exit(0);/添加记录fprintf(fp, %sn, no);fclose(fp);/*查询函数主菜单*/void Demand()char choose;dosystem。

22、(cls);PrintBalance();PR(ttttt +-+-+n);PR(ttttt |查询明细32|1|n);PR(ttttt +-+-+nn);PR(tt+-+-+ +-+-+n);PR(tt|0|33退出系统| | 返 回 32|2|n);PR(tt+-+-+ +-+-+nn);PR(请选择服务:);fflush(stdin);choose = getchar();switch (choose)case 1: Printetail(); break;/查询明细case 2: return;/返回case 0: FreeData(); exit(0);/退出系统default:pr。

23、intf(输入错误,请重新选择n); /解决用户可能的输入错误system(pause); while (1);/*输出余额*/void PrintBalance()system(cls);PR(nnnnnnnnntt+-+-+n);PR(tt| 您的账户余额 32|%-15.2f|n, now_acc-balance);PR(tt+-+-+nnnnnnn);/*输出明细*/void Printetail()FILE *fp;Record temp;int flag = 1;/当有记录时,置0if (!(fp = fopen(records.txt, r)PR(无存取记录,请进行存取后再使用本。

24、功能nn);system(pause);return;system(cls);PR(+-+-+n);PR(| 日期 | 存取金额 |n);PR(+-+-+n);while (fscanf(fp, %s%d-%d-%d%lf, temp.no, &temp.date.year, &temp.date.month, &temp.date.day, &temp.number) = 5)if (!(strcmp(temp.no, now_acc-no)flag = 0;PR(|%d-%d-%d|%-14.2f|n, temp.date.year, temp.date.month, temp.date.。

25、day, temp.number);PR(+-+-+n);PR(| 日期 | 存取金额 |n);/未免记录太多看不到表头,在最后加个表头PR(+-+-+n);if (flag)system(cls);/无记录时,清除表头PR(该卡号未有任何存取记录nn);system(pause);return;system(pause);/当有存取记录时,输出后等待/*将存款记录写入文件中*/void Log(double money, const char *no)FILE *fp;Date CruuentTime;/当前日期if (!money)/存取为零时return;if (!(fp = fopen。

26、(records.txt, a)PR(07);/响铃PR(error on open records.txt file!);exit(0);/获取当前日期time_t rawtime;struct tm * timeinfo;time(&rawtime);/获取时间,以秒计,从1970年1月1日起算,存于rawtimetimeinfo = localtime(&rawtime);/转为当地时间,tm 时间结构CruuentTime.year = timeinfo-tm_year + 1900, CruuentTime.month = timeinfo-tm_mon + 1, CruuentTi。

27、me.day = timeinfo-tm_mday;fprintf(fp, %sn%d-%d-%dn%fn, no, CruuentTime.year, CruuentTime.month, CruuentTime.day, money);fclose(fp);/*取款主界面*/void Withdrawal()char choose;if (now_acc-balance balance balance -= money;Save();Log(-money, now_acc-no);PR(取款成功nn);system(pause);/*存款*/void Depositing()long mo。

28、ney;doPR(请输入存款金额(50的倍数),单次存款金额不得超过20000元:);fflush(stdin);scanf(%ld, &money);if (money 20000 | money % 50)/解决输入金额为负数、超过20000、不是50的倍数的情况PR(07);/响铃PR(输入有误,请重新输入n);system(pause);continue;PR(正在处理,请稍候.n);now_acc-balance += money;Save();/保存账户数据Log(money, now_acc-no);/保存存取数据PR(存款成功nn);system(pause);break; w。

29、hile (1);/*保存账户信息*/void Save()FILE *fp;int i = 1;char ch;if (!(fp = fopen(accounts.txt, w)PR(07);/响铃PR(读取帐户信息失败!accounts.txt无法打开n);exit(0);for (Account *i = head; i; i = i-next)/写入账户信息fprintf(fp, %s %s %f %sn, i-no, i-name, i-balance, i-password);fclose(fp);/*修改密码*/void Modifiy()char oldpass7, newpa。

30、ss17, newpass27;doPR(请输入原密码:);fflush(stdin);gets(oldpass);if (strlen(oldpass) != 6)PR(密码应为6位n);system(pause);continue;if (strcmp(oldpass, now_acc-password)/解决密码输入有误,出于安全性的考虑,原密码输入错误时不提供返回功能PR(密码有误,请重新输入nn);system(pause);continue;elsebreak; while (1);doPR(请输入六位新密码:);fflush(stdin);scanf(%s, newpass1);。

31、if (strlen(newpass1) != 6)PR(密码应为6位n);system(pause);continue;PR(请再次输入新密码:);fflush(stdin);scanf(%s, newpass2);if (strcmp(newpass1, newpass2)/两次输入密码不一致时PR(密码不一致(输入*取消修改)n);fflush(stdin);if (getchar() = *)break;else/输入一致时strcpy(now_acc-password, newpass1);/修改密码Save();/保存用户数据PR(密码修改成功!nn);system(pause);。

32、break; while (1);/*转账*/void Transfer()Account* aimsite;/转入卡号在链表中的地址long money;/转账金额if (now_acc-balance no)/解决转账双方卡号相同的情况PR(双方账户相同,请核对后重试(输入*取消转账)n);if (getchar() = *)return;continue;if (aimsite = FindbyNo(aim)break;/找到转入卡号对应信息时elsePR(未找到该卡号,输入*取消转账n);if (getchar() = *)return;continue; while (1);PR(汇。

33、款目标用户名为:%sn, CoverUpName(aimsite-name);PR(是否确认无误?(输入*确认,否则退出));fflush(stdin);if (getchar() != *)return;doPR(请输入转账金额(50的倍数):);fflush(stdin);scanf(%lu, &money);if (now_acc-balance balance -= money;aimsite-balance += money;Save();/保存账户数据Log(-money, now_acc-no);/当前账户存取记录Log(money, aimsite-no);/转入卡存取记录PR。

34、(转账成功nn);system(pause);break; while (1);/*掩盖部分用户名*/char *CoverUpName(const char *name)char temp20;strcpy(temp, name);int words = 0;/用于存放姓名的字数for (char* i = temp; *i; i += 2)words+;/计算姓名的字数switch (words)case 2:temp0 = *, temp1 = *;/当姓名字数为2时,掩盖姓strcpy(temp + 1, temp + 2);/消除一个*号break;case 3:temp2 = *, temp3 = *;/当姓名字数为3时,掩盖名字中的第一个字strcpy(temp + 3, temp + 4);/消除一个*号break;default:temp0 = *, temp1 = *, temp2 = *, temp3 = *;/姓名字数大于3时,掩盖姓和名字中的第一个字strcpy(temp + 2, temp + 4);/消除两个*号return temp;/*释放链表空间*/void FreeData()Account* t;while (head)t = head;head = head-next;free(t);。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值