任务和代码:
/*
*All rights reserved
*文件名称:main.c
*作者: Osseyda
完成日期:2017.10.15
*版本号:v2.
*
*说明:本程序在学习者仅掌握了基本数据类型和控制结构、函数的前提下设计,模拟银行储蓄系统的基本功能。
程序运行前,请在程序所在文件夹中,自建文件password.txt,balance.dat.
运行结束后,对数据所做的所有修改均可以利用文件保存下来。
与上一个版本相比,我们学习了模块化程序设计及用函数的实现方法,所以有能力重构了整个软件的结构。
本程序在后续将进一步的改进:
1、银行应该是多用户,而绝不可以是单个的用户
2、应该要记录详细的业务过程
3、增加转帐、挂失等功能
4、密码的加密存储以及密码输入隐藏
随着课程进展,我们将继续完善这个程序。
*/
#include <stdio.h>
#include <stdlib.h>
double dBalance; //记录余额
int pass(); //验证密码
void work(); //业务驱动
void showMenu(); //显示菜单
void save(double); //存款业务
void withdraw(double); //取款业务
void updatePassword(); //更改密码
double getBalance(); //从文件中读取余额
void saveBalance(double);//将余额保存到文件中
//主函数
int main(){
printf("欢迎您光临CSDN学院\n");
if(pass())
work();
return 0;
}
//验证密码
int pass(){
int iPass,iPassInFile,iTry=0;
FILE *fp;
if((fp=fopen("password.txt","r"))==NULL){
printf("password file cannot be opened");
exit(0);
}
fscanf(fp,"%d",&iPassInFile); //从文件中读取密码
fclose(fp);
do{
iTry++; //密码尝试次数
printf("请输入密码:");
scanf("%d",&iPass);
if(iPass==iPassInFile)
break; //密码读取成功则进入业务驱动
else{
if(iTry<3)
printf("超过3次将退出,你已经尝试%d次!\n",iTry);
else{
printf("对不起,你不能进入系统\n");
exit(0);
}
}
}
while(1);
}
//业务驱动
void work(){
int iChoice; //业务序号
double dMoney; //存、取款金额
do{
showMenu();
scanf("%d",&iChoice);
switch(iChoice){
case 1:
dBalance=getBalance();
printf("您的余额有%.2f\n",dBalance);
break;
case 2:
withdraw(dMoney);
saveBalance(dBalance);
break;
case 3:
save(dMoney);
saveBalance(dBalance);
break;
case 4:
updatePassword();
break;
case 0:
printf("欢迎您再来\n");
}
}
while(iChoice);
}
//显示菜单
void showMenu(){
printf("\n您可以办理下面的业务:\n");
printf(" 1.查询.\n");
printf(" 2.取款\n");
printf(" 3.存款\n");
printf(" 4.改密码\n");
printf(" 0.退出\n");
printf("请输入(0-4):");
}
//从文件读取余额
double getBalance(){
FILE *fp;
if((fp=fopen("balance.dat","r"))==NULL){
printf("data file cannot be opened");
exit(0);
}
fscanf(fp,"%lf",&dBalance);
fclose(fp);
return dBalance;
}
//将存款业务
void save(double d){
printf("输入存款额:");
scanf("%lf",&d);
dBalance+=d;
printf("存款后,您有%.2f元\n",dBalance);
}
//取款业务
void withdraw(double d){
printf("输入取款额:",d);
scanf("%lf",&d);
if(dBalance>d){
dBalance-=d;
printf("取款后,您还有%.2f元\n",dBalance);
}
else
printf("余额不足,取款失败\n");
}
//将余额保存到文件
void saveBalance(double d){
FILE *fp;
if((fp=fopen("balance.dat","w"))==NULL){
printf("data file cannot be opened");
exit(0);
}
fprintf(fp,"%f",d);
fclose(fp);
}
//更改密码
void updatePassword(){
int iNewPass1,iNewPass2,iPassInFile;
FILE *fp;
printf("请输入新密码:");
scanf("%d",&iNewPass1);
printf("再输入密码:");
scanf("%d",&iNewPass2);
if(iNewPass1==iNewPass2){
iPassInFile=iNewPass1;
printf("密码修改成功\n");
}
else
printf("密码修改失败\n");
if((fp=fopen("password.txt","w"))==NULL){ //将修改后的密码保存到文件
printf("password file cannot be opened");
exit(0);
}
fprintf(fp,"%d",iPassInFile);
fclose(fp);
}
知识点总结:
1.函数版本的总体设计思路:自顶向下,分而治之
2.对于各个函数模块之间:高内聚,低耦合
3.在声明一个函数的时候,根据它在程序中的使用,要考虑好:功能、返回值、参数
4.谨慎使用全局变量
心得:
1.在使用全局变量double dBalance; 时,起初在work()中又定义了一次double dBalance;,导致经过withdraw()和save()后,余额都不能保存到文件中。
具体原因如下:
saveBalance()是work()的一个子函数,变量dBalance听命于work()中声明的变量,故每调用过完saveBalance(),都会将形参释放掉。
解决如下:
在声明全局变量值之后,不要再函数中继续定义该变量。
2.实参若是全局变量,形参不必同名,但既然采用了全局变量,则可以避免函数传参,程序更易读
将dBalance不作为全局变量的另一解法:
需要考虑如何在withdraw(),save()中读取dBalance,以及如何将dBalance返回到work()中
对应具体操作:在withdraw(),save()中,double dBalance=getBalance();
将void withdraw(double); void save(double); 变为返回值为dBalance的函数
#include <stdio.h>
#include <stdlib.h>
int pass(); //验证密码
void work(); //业务驱动
void showMenu(); //显示菜单
double save(double); //存款业务
double withdraw(double); //取款业务
void updatePassword(); //更改密码
double getBalance(); //从文件中读取余额
void saveBalance(double);//将余额保存到文件中
//主函数
int main(){
printf("欢迎您光临CSDN学院\n");
if(pass())
work();
return 0;
}
//验证密码
int pass(){
int iPass,iPassInFile,iTry=0;
FILE *fp;
if((fp=fopen("password.txt","r"))==NULL){
printf("password file cannot be opened");
exit(0);
}
fscanf(fp,"%d",&iPassInFile); //从文件中读取密码
fclose(fp);
do{
iTry++; //密码尝试次数
printf("请输入密码:");
scanf("%d",&iPass);
if(iPass==iPassInFile)
break; //密码读取成功则进入业务驱动
else{
if(iTry<3)
printf("超过3次将退出,你已经尝试%d次!\n",iTry);
else{
printf("对不起,你不能进入系统\n");
exit(0);
}
}
}
while(1);
}
//业务驱动
void work(){
int iChoice; //业务序号
double dMoney,dBalance;
do{
showMenu();
scanf("%d",&iChoice);
switch(iChoice){
case 1:
dBalance=getBalance();
printf("您的余额有%.2f\n",dBalance);
break;
case 2:
dBalance=withdraw(dMoney);
saveBalance(dBalance);
break;
case 3:
dBalance=save(dMoney);
saveBalance(dBalance);
break;
case 4:
updatePassword();
break;
case 0:
printf("欢迎您再来\n");
}
}
while(iChoice);
}
//显示菜单
void showMenu(){
printf("\n您可以办理下面的业务:\n");
printf(" 1.查询.\n");
printf(" 2.取款\n");
printf(" 3.存款\n");
printf(" 4.改密码\n");
printf(" 0.退出\n");
printf("请输入(0-4):");
}
//从文件读取余额
double getBalance(){
double dBalance;
FILE *fp;
if((fp=fopen("balance.dat","r"))==NULL){
printf("data file cannot be opened");
exit(0);
}
fscanf(fp,"%lf",&dBalance);
fclose(fp);
return dBalance;
}
//将存款业务
double save(double d){
double dBalance=getBalance();
printf("输入存款额:");
scanf("%lf",&d);
dBalance+=d;
printf("存款后,您有%.2f元\n",dBalance);
return dBalance;
}
//取款业务
double withdraw(double d){
double dBalance=getBalance();
printf("输入取款额:",d);
scanf("%lf",&d);
if(dBalance>d){
dBalance-=d;
printf("取款后,您还有%.2f元\n",dBalance);
}
else
printf("余额不足,取款失败\n");
return dBalance;
}
//将余额保存到文件
void saveBalance(double d){
FILE *fp;
if((fp=fopen("balance.dat","w"))==NULL){
printf("data file cannot be opened");
exit(0);
}
fprintf(fp,"%f",d);
fclose(fp);
}
//更改密码
void updatePassword(){
int iNewPass1,iNewPass2,iPassInFile;
FILE *fp;
printf("请输入新密码:");
scanf("%d",&iNewPass1);
printf("再输入密码:");
scanf("%d",&iNewPass2);
if(iNewPass1==iNewPass2){
iPassInFile=iNewPass1;
printf("密码修改成功\n");
}
else
printf("密码修改失败\n");
if((fp=fopen("password.txt","w"))==NULL){ //将修改后的密码保存到文件
printf("password file cannot be opened");
exit(0);
}
fprintf(fp,"%d",iPassInFile);
fclose(fp);
}