C语言进阶-第39讲:银行储蓄系统(二进制版)开发
银行储蓄系统:结构体版本、二进制版本
下面讨论二进制版较结构体版的不同,优势,两难,改进之处:
不同:
(一)全局变量
结构体版:
struct record users[upNum]; //银行所有用户
int N; //实际的用户数目
二进制版:
int N;
FILE *fp;
全局变量的结构体数组->子函数中定义指向结构体的指针
fp由局部变量->全局变量
(二)main函数
结构体版:
int main()
{printf("+----------------------+\n");printf("+ 欢迎光临CSDN银行 +\n");printf("+----------------------+\n");if (pass()){readData();work();writeData();}return 0;
}
二进制版:
int main(){FILE *fp;printf("+----------------------+\n");printf("+ 欢迎光临我家银行 +\n");printf("+----------------------+\n");if (pass()){exchange(); //将数据从文本文件读到二进制文件if((fp=fopen("account.bin", "rb+"))==NULL) //文件不存在时重建,文件已经存在时,将保留原数据{printf("数据文件打开失败,退出程序....");exit(1);}fseek(fp, 0, SEEK_END);N = ftell(fp)/sizeof(record); //ftell用于得到文件位置指针当前位置相对于文件首的偏移字节数,除以sizeof(struct record),得到的是当前用户的数目work();fclose(fp);}return 0;}
结构体版readData(),writeData() 需要用到大数组操作,需要读写所有的数据信息;
二进制版运用随机读写,只要定位到某账户所在的文件指针位置,不再需要内存中的大数组。
(三)二进制的业务员文件及存储
结构体版:
int pass()
{...if ((fp=fopen("worker.txt", "r"))==NULL){printf("password file cannot open!");exit(0);}fscanf(fp, "%s %s", sNameInFile, sPassInFile); //从文件中读业务员用户名和密码密码fclose(fp);//进入系统,密码三次不对将退出do{...}while(iTry);return right;
}
二进制版:
int pass()
{...if ((fp=fopen("password.dat", "rb"))==NULL){printf("第一次使用,将设置初始操作员账户:\n");printf("请输入用户名:");scanf("%s",sName);printf("请输入密码:");iPass1=inputPassword(); //输入密码1printf("确认密码:");iPass2=inputPassword(); //输入密码2if(iPass1==iPass2){fp=fopen("password.dat", "wb");fwrite(sName, sizeof(sName), 1, fp);fwrite((char*)&iPass1, sizeof(int), 1, fp);right = 1;fclose(fp);}else{printf("两次密码不一致,设置不成功!\n");exit(0);}}else{fread(sNameInFile, sizeof(sNameInFile), 1, fp); //从文件中读业务员用户名fread((char*)&iPassInFile, sizeof(int), 1, fp); //密码fclose(fp);//进入系统,密码三次不对将退出do{...}while(iTry);}return right;
}
结构体版中用字符数组保存业务员密码;二进制版中密码采用整型,添加了打开失败的处理
(四)从文件中读取以及更新内容——以取款为例
结构体版:
void withdraw()
{...printf("账号:");scanf("%d", &id);who = search(id); //根据账号查询用户,返回用户的下标if(who<0) //说明id账户不存在{printf("该用户不存在,取款失败!\n");}else{if(users[who].status==0){printf("户主姓名:%s\n", users[who].name);printf("密码:");iPass=inputPassword();if(iPass!=users[who].password){printf("输入密码错误,取款失败!\n");}else{printf("输入取款额:");scanf("%lf", &money);if(money>users[who].balance) //亲,不玩透支{printf("余额不足,取款失败!\n");}else{users[who].balance-=money;printf("取款后,还有%.2f元. \n",users[who].balance);}}}else if(users[who].status==1)...else...}return;
}
int search(int id)
{int index=-1;int i;for(i=0; i<N; i++){if(users[i].account==id){index=i;break; //找到了,立即退出循环}}return index; //若找到,其值在0~N-1间,否则,保持-1
}
二进制版:
void withdraw()
{...record *user;user = getuser(); //输入并查询用户,不存在返回NULLif(user!=NULL){if(user->status==0){printf("户主姓名:%s\n", user->name);printf("密码:");iPass=inputPassword();if(iPass!=user->password){printf("输入密码错误,取款失败!\n");}else{printf("输入取款额:");scanf("%lf", &money);if(money>user->balance) //亲,不玩透支{printf("余额不足,取款失败!\n");}else{user->balance-=money;writeData(user);printf("取款后,还有%.2f元. \n",user->balance);}}}else if(user->status==1)...else...free(user);}return;
}
record* getuser()
{FILE *fp;if((fp=fopen("account.bin", "rb+"))==NULL) //文件不存在时重建,文件已经存在时,将保留原数据{printf("数据文件打开失败,退出程序....");exit(1);}int id;printf("账号:");scanf("%d", &id);record *user = NULL;if(id>=N+10001)//说明账户不存在{printf("该用户不存在,查询完毕!\n");}else{fseek(fp,(id-10001)*sizeof(record), SEEK_SET);user=(record*)malloc(sizeof(record));fread((char*)user, sizeof(record), 1, fp);}fclose(fp);return user; //若找不到,user为NULL
}
void writeData(record *user)
{FILE *fp;if((fp=fopen("account.bin", "rb+"))==NULL) //文件不存在时重建,文件已经存在时,将保留原数据{printf("数据文件打开失败,退出程序....");exit(1);}//先在文件中定位long i = user->account -10001;fseek(fp, (long)i*sizeof(record), SEEK_SET);fwrite((char*)user, sizeof(record),1,fp);fclose(fp);
}
二进制版随机读取并采用动态分配内存的方式,避免大数组操作和节省空间
(五)创建二进制文件account.bin用来保存储户信息
#define upNum 2000 //估计一个超出原实际储户的大数
void exchange(){FILE *fp;record users[upNum]; //存放数据的一段内存空间int i=0,N;/*事先将储户信息输入到文本文件中*/if((fp=fopen("account.dat","r"))==NULL){ printf("account.dat cannot be opened");exit(1);}/*将文本文件中的信息读到内存*/while(fscanf(fp,"%d %s %d %lf %d",&users[i].account, users[i].name, &users[i].password, &users[i].balance,&users[i].status ) != EOF)i++;N=i;fclose(fp);if((fp=fopen("account.bin","wb"))==NULL){printf("account.bin cannot be opened");exit(1);}/*将内存数据读到二进制文件中*/fwrite((char*)&users[0],sizeof(users[0]),N,fp);fclose(fp);
}
优势:
二进制文件:空间省、效率高、保密。结合随机读取,自由灵活,适用大文件
两难:
fp作为全局变量,又是指针,在整个文件中起作用,生存周期长
若将fp作为局部变量(定义FILE *fp;fopen();fclose();),但会在writeData(),getuser()中频繁调用,使用外存,过程缓慢
改进之处:索引+随机访问
实际应用中数据文件未必顺序存储,但账号不会重复,
使用数据在内存中的偏移量代替序号,声明第几条记录
把偏移量和账号抽取出来作为排序前索引,根据账号查出是第几条记录
通过以账号进行排序后的索引文件,将索引数据读到内存,快速查找到账户信息
查找账号->偏移量->储户数据信息
C语言进阶-第39讲:银行储蓄系统(二进制版)开发相关推荐
- 银行账户管理系统c语言链表,课程设计银行储蓄管理系统Word版
<课程设计银行储蓄管理系统Word版>由会员分享,可在线阅读,更多相关<课程设计银行储蓄管理系统Word版(22页珍藏版)>请在人人文库网上搜索. 1.传播优秀Word版文档 ...
- 银行办理CSS系统,简单的银行储蓄系统.doc
PAGE PAGE 2 哈 尔 滨 理 工 大 学 毕 业 设 计 题 目: 简单的银行储蓄系统 院 .系: - 学院 - 工程系 姓 名: - - 指导教师: - - 系 主 任: - - 2012 ...
- 软件工程导论 银行储蓄系统_银行计算机储蓄系统
银行计算机储蓄系统 题目:银行帐户管理,储蓄业务管理处理系统 班级:计算机科学与技术( 3 )班 设计者:易华丽 1 引言 1.1 编写目的 本报告的目的是规范化本软件的编写,旨在于提高软件开发过程中 ...
- Day11-软件测试设计之银行储蓄系统
银行储蓄系统 需求分析 银行储蓄系统存取款流程如下: 1. 业务员事先录入利率信息. 2. 如果是存款,储户填写存款单,业务员将存款单键 入系统,系统更新储户存款信息(存款人姓名.存款人账号.电话号 ...
- 学术休假之银行储蓄系统
银行储蓄系统指导 该银行储蓄系统的目标,将是设计一个可以支持多名储户开户.存款.取款.转帐.改密.挂失.解挂.销户等功能的系统,以此初步体会完整系统开发,综合运用已经学过的知识. 以下提示中,给出了多 ...
- 银行储蓄系统的可行性分析
作业题目 题目: 为方便储户,某银行拟开发计算机储蓄系统.储户填写的存款单或取款单由业务员输入系统,如果是存款,系统记录存款人姓名.住址.存款类型.存款日期.利率等信息,并印出存款单给储户:如果是取款 ...
- 数据结构课程设计银行储蓄系统
/** *版权所有(C)2017,panyanan * *文件名称:main.cpp *文件标识:无 *内容摘要:本文件的作用是调用算法库里面的函数,完成题目要求. *其它说明:无 *当前版本:V1. ...
- 软件工程导论 银行储蓄系统_银行储蓄系统问题定义及其可行性
1.问题定义(系统目标及范围说明书): 项目名称:XX银行储蓄业务系统 问题描述:方便储蓄用户存取等业务.解决当前银行业务员处理储蓄业务时间消耗长.工作量大.效率低 项目目标:开发一个方便储蓄用户的银 ...
- C语言之简单版本银行储蓄系统4(结构体版本)
1.老学长的唠叨 在上一个编的数组版本的简化银行系统的基础上改为结构体存储,为还没有学到结构体的学弟学妹们提供一个迁就的方案,现在将程序改为结构体存储了,也希望学弟学妹们有个c语言学习缓冲的时间,这个 ...
最新文章
- 【转】centos 6.2 安装mysql-5.5.17
- raspberry pi 3B 树莓派 安装tensorflow
- html select 可输入 可编辑
- mongodb模糊查询_AWS 回击了!推出兼容 MongoDB 的 DocumentDB
- arduino判断是否连接串口_Arduino-串口通信
- ae渲染出现错误是什么问题_[Switch]解决OPENWRT路由,使用UU加速器等出现相同IP,DNS解析错误问题...
- mysql部署策略_MySQL延迟问题和数据刷盘策略流程分析
- 利用hutool工具类导出Excel
- Visual Studio 2010 (ASP.Net 4.0)新功能一览(转载)
- VirtualDub - 开源视频捕捉及线性处理软件
- 面试题之——多线程详解
- vbs实现恶搞无限弹窗,复制粘贴就能用
- 看看“电子招投标平台”是如何识破“围标串标”的,看完少走弯路
- socket编程详解(一)——服务器端
- Oracle Data Pump Schema 方式导入导出
- win10怎么更新显卡驱动_Intel发布核显新驱动:支持Win10 H2更新、11代酷睿狂喜-Intel,核显,驱动,Win10 ——快科技(驱动之家旗下媒体)-...
- nginx动静分离和资源隔离的网站搭建
- 敏捷项目管理21天学习计划--敏捷生命周期
- 「兔了个兔」玉兔踏青,纯CSS实现瑞兔日历(附源码)
- ffmpeg加水印、logo等