项目1:C中实现ATM功能

功能说明:

        1.完成注册功能:输入账号和密码登录

        2.完成登录功能:输入账号和密码注册

        3.成功登陆后,实现存款

        4.成功登陆后,实现取款

        5.成功登陆后,实现转账

        6.成功登陆后,实现查询余额

        7.退卡

代码解析:

        1.完成登录功能:输入账号和密码登录

                先查找是否有该账号,如果查找不到账号或者密码输入错误,打印“登陆失败”。

                查找到该账号并且密码匹配,打印“登陆成功”。

        2.完成注册功能:输入账号和密码注册

                先检查该账号和密码是否已经注册过,如已注册,打印“注册失败”。

                如未注册过,检查内存是否满了,如果内存满了需要进行扩容操作。

                未满\扩容之后,将注册的账号和密码进行存储,并打印“注册成功”。

        3.完成登陆成功后的功能:输入要操作的账号和密码进行登录。

                存款:对已经登陆成功的卡进行原余额+新存入的钱,并通过查询余额进行验证

                取款:对已经登陆成功的卡进行原余额-新存入的钱,并通过查询余额进行验证;如果待取金额>原余额,则取款失败,否则,成功。

                转账:对已经登陆成功的卡进行原余额-待转账的钱,并通过查询余额进行验证;如果待取金额>原余额,则转账失败;通过输入另一账号对待接收转账金额的卡进行查找,如果该卡不存在,则转账失败;

                查询余额:输出当前卡余额

函数设计:

        首先建立结构体,对卡槽的卡进行存储,以及卡的账户密码余额信息存储。

        typedef struct BankCard {//存放卡的信息

                int id; //账户

                int password;//密码

                double money;//余额

        }BankCard;//BankCard=struct BankCard

        typedef struct Array {//卡槽,存放卡

                BankCard* cards;//该数组存放卡

                int size;//记录有效卡个数,可以理解为实际占用的数组内存个数

                int length;//记录当前数组cards大小,动态开辟的内存大小

        }Array,*PArr; //Array=struct Array,PArr=struct Array* 

        说明:BankCard* cards:写成BankCard cards[size];不对,因为[]内只能是常量,而指针就比较OK,可以动态内存开辟存储信息。

完整代码:

头文件

atm.h

#pragma once //可以防止头文件被编译多次
typedef struct BankCard {//银行卡类型
	int id;
	int password;
	double money;

}BankCard;
typedef struct Array {
	int size;//记录有效卡个数,可以理解为实际占用的数组内存个数
	BankCard* cards;
	int length;//记录当前数组cards大小
	BankCard* temp;//后面代码扩容函数时需要一个替代量,无其他含义
}Array, * PArr; //PArr=struct Array* parray

//功能函数声明
void init(PArr parray, int len);//初始化Array
int search_card(PArr parray, int id, int password);//查找卡
int login_user(PArr parray, int id, int password); //登录
bool is_full(PArr parray);//对数组判满操作
void grow(PArr parray);//如果满了,扩容
bool register_card(PArr parray, int id, int password);//注册
void destory(PArr parray);//销毁函数
void after_login_success(PArr parray, int index);//登陆成功后的操作,index是当前卡


.cpp

#define _CRT_SECURE_NO_WARNINGS
#include"atm.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//函数声明
void init(PArr parray, int len)//初始化Array
{
	assert(parray != NULL);
	parray->cards = (BankCard*)malloc(sizeof(BankCard) * len); //或者写成(*parray).cards
	assert(parray->cards != NULL);
	parray->size = 0;
	parray->length = len;
	parray->cards->money = 0;
}

//查找卡函数
int search_card(PArr parray, int id, int password)
{
    /*实现的操作:去判断该卡的id和密码是否与卡槽里面拥有的卡和密码对应
    循环实现,拿卡槽内的卡和密码一张行比较*/
	for (int i = 0; i < parray->size; i++)//parray->length是总长,size是有效卡数
	{
		BankCard curcard = parray->cards[i];//curcard是卡槽的卡,对其初始化
		if (curcard.id == id && curcard.password == password) {
			return i;//查找成功,返回卡所在下标
		}
	}
	return -1;//没有卡返回-1
}

//登录
int login_user(PArr parray, int id, int password)
{
	/*操作:用户输入账号和密码(这个在菜单界面会显示提醒,在这儿不用写),
	系统进行卡的查找工作,如果查找成功继续访问,查找失败重新输入*/
	assert(parray != NULL);
	int index = search_card(parray, id, password);
	return index;//返回下标值
}
//对数组判满操作
bool is_full(PArr parray)
{
	assert(parray != NULL);
	//什么情况下数组是满的?数组开辟总长度==目前数组格子被占用的长度。size==length
	return parray->size == parray->length ? true : false;
}
//如果满了,扩容1.5倍
void grow(PArr parray)
{
	assert(parray != NULL);
	/*以下几种错误解析:
    1.int newlength =(int) parray->length + 0.5 * parray->length;
	等号右边是double类型,强转为int会出问题,比如扩为1.3,强转:1.
	2.对于位运算的使用(如下一行代码所示),/2:右移一位。格子里剔除掉最后一位
      位运算优先级小于+。对0.5和2一定要敏感,大多数情况需要使用位运算,而且不会出错 */
	int newlength = parray->length + (parray->length >> 1);
	parray->temp = (BankCard*)realloc(parray->cards, newlength *         
    sizeof(BankCard));//realloc扩容的是字数,不是字节数
	if (parray->temp != NULL)//如果为NULL,则原来cards所指向的内容无法释放
		parray->cards = parray->temp;//该两行代码等同于assert(parray->cards != NULL);
	parray->length = newlength;//更新length
}
//注册
bool register_card(PArr parray, int id, int password)
{
	assert(parray != NULL);
	//查找是否有相同的id和password,如有不能再重复注册
	if (search_card(parray, id, password) != -1)//if (search_card(parray, id, password))
		return false;
	//这个函数内需要用到判满操作
	if (is_full(parray))//如果满,扩容
		grow(parray);
	//此时数组长度已经够了,放入id和password到卡包内
	BankCard card = { id,password,0.0 };//新卡余额为0
	parray->cards[parray->size] = card;
	parray->size++;
	return true;
}
//登陆成功后的操作
void after_login_success(PArr parray, int index)
{
	int choice;
	int id, password;
	double money;
	int Otherid;
	while (true)
	{
		printf("1.存款 2.取款 3.转账 4.查余额 5.退卡\n");
		//下面的代码写到头文件内不好,因为是在一个函数内部实现的		
        printf("1.存款 2.取款 3.转账 4.查余额 5.退卡");
		scanf("%d", &choice);
		if (choice == 5)
			break;
		switch (choice)
		{
		case 1://存款
			printf("请输入存款金额:\n");
			scanf("%lf", &money);
			parray->cards[index].money += money;
			printf("存款成功\n");
			break;
		case 2://取款
			printf("请输入取款金额:\n");
			scanf("%lf", &money);
			if (parray->cards[index].money >= money) {
				parray->cards[index].money -= money;
				//等价于(*parray).cards[index].money -= money;
				printf("取款成功\n");
			}
			else
				printf("取款失败\n");
			break;
		case 3://转账
			printf("请输入对方转账账号:\n");
			scanf("%d", &id);
			printf("请输入密码:\n");
			scanf("%d", &password);
			Otherid = search_card(parray, id, password);
			//查找该用户是否存在
			if (Otherid == -1)//if (search_card(parray, id, password))
				printf("不存在该用户\n");
			else
			{
				printf("请输入转账金额:\n");
				scanf("%lf", &money);
				//前提转出去的金额所在卡余额应大于转出的钱
				if (parray->cards[index].money >= money)
				{
					parray->cards[index].money -= money;
					parray->cards[Otherid].money += money;
					printf("转账成功!\n");
				}
				else
					printf("余额不足,转账失败!\n");
			}
			break;
		case 4://显示卡余额
			printf("当前卡的余额是:%lf\n", parray->cards[index].money);
			break;
		}


	}
}


//销毁函数
void destory(PArr parray)
{
	if (parray == NULL)
		return;
	free(parray->cards);//释放一维数组
	parray->cards = NULL;
}


.cpp

#define  _CRT_SECURE_NO_WARNINGS//在vs2019编译器中输入scanf函数必须用到该行
#include<stdio.h>
#include"atm.h" //引用头文件
#define INITCAPACITY 10 //宏常量INITCAPACITY=10
void menu()//ATM主菜单界面
{
	printf("***********欢迎进入ATM操作**************\n");
    printf("********请选择你需要的功能操作:*********\n");
	printf("**************1:登录*******************\n");
	printf("**************2:注册*******************\n");
	printf("**************3:退出*******************\n");
}

void show()
{
	Array array; 
    int choice, id, password;//choice:输入的功能选择,id账户,password密码
	init(&array, INITCAPACITY);
	while (true) { //while循环可以多次选择功能而不是选择一次就退出了,终止条件是 3:退出
		menu();
		scanf("%d", &choice);
		switch (choice)
		{
			case 1:
				printf("请输入账号:\n");
				scanf("%d", &id);
				printf("请输入密码:\n");
				scanf("%d", &password);
				if(login_user(&array,id,password))
					printf("登录成功");
				else
					printf("登录失败");
				break;
			case 2:
				printf("请输入账号:\n");
				scanf("%d", &id);
				printf("请输入密码:\n");
				scanf("%d", &password);
				if (register_card(&array, id, password))
					printf("注册成功");
				else
					printf("注册失败");
				break;
			case 3:
				return;
				break;
			default:
				break;
		}
	}
	destory(&array); //释放malloc内存
}

int main()
{
	show();
	return 0;
}

运行结果:

1.测试操作:

 2.测试登录函数

 3.登陆成功继续操作,测试存款

  4.登陆成功继续操作,测试取款

 5.登陆成功继续操作,测试转账

 检验如果余额大于本卡内余额是否提醒错误

 

再检验222卡内是否余额增加

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值