C语言-银行系统的简单实现(存钱,取钱,保存用户信息,销户,开户,转账,查询等功能,使用消息队列达到2个不同进程之间的相互通信)

该博客介绍了使用C语言在Linux环境下实现的一个简单的银行系统,包括开户、销户、登录、解锁、存取款、转账、查询等功能。通过消息队列实现在不同进程间通信,每个功能对应一个子进程。用户信息存储在单独文件中,项目还包含编译执行脚本和相关头文件。未来计划通过学习socket套接字实现跨主机通信。
摘要由CSDN通过智能技术生成

主要分为两人大模块:

客户端
1、进入时的功能开户、销户、登录、解锁
开户:输入姓名、身份证号、设置密码,如果开户成功,则服务器上保存一个账号信号(一个账号存一个文件,文件名建议是账号)。
销户:输入帐号、密码,服务器询问是否确认销户,如果确认则服务器删除帐号文件,并记录帐号。
登录:输入账号、密码,三次错误账号锁定。
解锁:输入账号、身份证号解锁。
2、登录成功:存钱、取钱、转账、查询、修改密码
存钱:输入存钱金额
取钱:输入取钱金额
转账:目标帐号和要转的金额
查询:不需要输入数据
修改密码:原密码和新密码
服务器
如果识别功能:根据消息的类型识别客户端请求的功能。
开启服务各项功能的子进程
各进程按照消息类型接收消息

Makefile

FLAG=-Werror
STD=-std=gnu99
CC=gcc

all:
	$(CC) $(STD) $(FLAG) client.c tools.c -o client
	$(CC) $(STD) $(FLAG) server.c tools.c -o server
	$(CC) $(STD) $(FLAG) login.c tools.c -o login
	$(CC) $(STD) $(FLAG) open.c tools.c -o open
	$(CC) $(STD) $(FLAG) save.c tools.c -o save
	$(CC) $(STD) $(FLAG) take.c tools.c -o take
	$(CC) $(STD) $(FLAG) transf.c tools.c -o transf
	$(CC) $(STD) $(FLAG) select.c tools.c -o select
	$(CC) $(STD) $(FLAG) change.c tools.c -o change 
	$(CC) $(STD) $(FLAG) destory.c tools.c -o destory
	$(CC) $(STD) $(FLAG) unlock.c tools.c -o unlock	

clean:
	rm client server login open save take transf select change destory unlock

change.c 修改密码
destory.c 销毁用户
open.c 开户
select.c 查询
save.c 存款
take.c 取款
transf.c 转账
client.c 用户端
login.c 登陆
server.c 系统端
tools.c 一些工具函数
unlock.c 解锁
data(文件夹) 存储用户信息
Makefile 编译执行脚本
struct.h 结构体存储头文件 tools.h 工具函数头文件

此处所用getch.h的头文件为自建头文件(linux下没有conio.h头文件) 如果有需要可以私我

client.c 用户端

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include "struct.h"
#include "tools.h"


static long online = 0;		//记录当前的用户
static int lock = 0;		//密码错误的次数

int msgid_ctos;				//消息队列的标识符
int msgid_stoc;				//消息队列的标识符

int init(void);				//创建消息队列
void open_acc(void);		//开户操作
void destory(void);			//销户操作
void login(void);			//登录操作
void unlock(void);			//解锁操作
void user_menu(void);		//用户菜单
void menu(void);			//菜单(开户,销户)
void save(void);			//存钱
void take(void);			//取钱
void transf(void);			//转账
void select_money(void);	//查询余额
void change_pw(void);		//改变密码

int main()
{
   
	init();
	menu();
}

int init(void)				//创建消息队列
{
   
	//ftok是获取IPC键值
	msgid_ctos = msgget(ftok(".",100),IPC_CREAT);
	if(0 > msgid_ctos)
	{
   
		perror("msgget");
		return -1;
	}
	msgid_stoc = msgget(ftok(".",200),IPC_CREAT);
	if(0 > msgid_stoc)
	{
   
		perror("msgget");
		return -1;
	}
	return 0;
}

void login(void)			//登录操作
{
   
	if(lock >= 3)
	{
   
		printf("您的账户已被锁定,请解锁\n");
		getch();
		return;
	}
	Account acc = {
   };
	Msg msg = {
   110};
	printf("请输入帐号:");
	scanf("%ld",&acc.user);
	getchar();
	printf("请输入密码:");
	get_pw(acc.pw,true,L_PW);
	msg.acc = acc;
	//发送消息
	msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);

	Msg msg2 = {
   };
	// 接收消息
	msgrcv(msgid_stoc,&msg2,sizeof(Msg),220,MSG_NOERROR);
	
	if(acc.user == msg2.acc.user)
	{
   
		online = acc.user;
		printf("\n用户:%ld,登陆成功\n",online);
		getch();
		user_menu();
	}
	else
	{
   	
		lock++;	
		printf("\n帐号或密码错误\n");
		getch();
	}
}

void open_acc(void)			//开户操作
{
   

	Account acc = {
   };
	Msg msg = {
   111};
	printf("请输入姓名:");
	get_str(acc.name,L_NAME);
	printf("请输入身份证:");
	get_str(acc.id,L_ID);
	printf("请输入密码:");
	get_str(acc.pw,L_PW);
	msg.acc = acc;
	//发送消息
	msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);

	Msg msg2 = {
   };
	// 接收消息
	msgrcv(msgid_stoc,&msg2,sizeof(Msg),221,MSG_NOERROR);
	printf("msg2:%s,acc:%s\n",msg2.acc.name,acc.name);
	if(strcmp(acc.name,msg2.acc.name) == 0)
	{
   
		printf("帐号:%ld,开户成功\n",msg2.acc.user);
	}
	else
	{
   		
		printf("开户失败\n");
	}
	getch();
}

void save(void)				//存款
{
   
	Account acc = {
   };
	Msg msg = {
   112};

	printf("请输入存款金额:");
	scanf("%lf",&acc.money);
	getchar();
	acc.user = online;	
	msg.acc = acc;
	//发送消息
	msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);

	Msg msg2 = {
   };
	// 接收消息
	msgrcv(msgid_stoc,&msg2,sizeof(Msg),222,MSG_NOERROR);
	if(msg2.acc.user == online)
	{
   
		printf("存钱成功\n");
	}
	else
	{
   
		printf("存钱失败\n");
	}
	getch();
}

void take(void)				//取款
{
   
	Account acc = {
   };
	Msg msg = {
   113};
	printf("请输入取款金额:");
	scanf("%lf",&acc.money);
	getchar();
	acc.user = online;	
	msg.acc = acc;
	msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);

	Msg msg2 = {
   };
	// 接收消息
	msgrcv(msgid_stoc,&msg2,sizeof(Msg),223,MSG_NOERROR);
	if(msg2.acc.user == online)
	{
   
		printf("取钱成功\n");
	}
	else if(msg2.acc.user == online + 2)
	{
   
		printf("余额不足,请充值\n");
	}
	else
	{
   
		printf("取钱失败\n");
	}
	getch();
}
void transf(void)			//转账
{
   
	Account acc = {
   };
	Msg msg = {
   114};
	printf("请输入转帐金额:");
	scanf("%lf",&acc.money);
	getchar();
	acc.user = online;	
	msg.acc = acc;
	msg.flag = 0;
	msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);

	Msg msg2 = {
   };
	// 接收消息
	msgrcv(msgid_stoc,&msg2,sizeof(Msg),224,MSG_NOERROR);
	if(msg2.flag == 0)
	{
   
		printf("请输入要转帐的帐号:");
		scanf("%ld",&acc.user);
		getchar();
		msg.acc = acc;
		msg.flag = 1;
		msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
		
		// 接收消息
		msgrcv(msgid_stoc,&msg2,sizeof(Msg),224,MSG_NOERROR);
		
		if(msg2.flag == 2)  printf("转帐成功\n");
		else printf("转帐失败\n");
	}
	else
	{
   
		printf("余额不足\n");
	}
	getch();
}
void select_money(void)			//余额查询
{
   
	Account acc = {
   };
	Msg msg = {
   115};
	acc.user = online;	
	msg.acc = acc;
	msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);

	Msg msg2 = {
   };
	// 接收消息
	msgrcv(msgid_stoc,&msg2,sizeof(Msg),225,MSG_NOERROR);
	if(msg2.acc.user == online)
	{
   
		printf("余额:%.2lf\n",msg2.acc.money);
	}
	else
	{
   
		printf("查询失败\n");
	}
	getch();
}
void change_pw(void)			//修改密码
{
   
	Account acc = {
   };
	Msg msg = {
   116};
	printf("请输入新密码:");
	get_pw(acc.pw,true,L_PW);
	acc.user = online;	
	msg.acc = acc;
	msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);

	Msg msg2 = {
   };
	// 接收消息
	msgrcv(msgid_stoc,&msg2,sizeof(Msg),226,MSG_NOERROR);
	if(msg2.acc.user == online)
	{
   
		printf("\n改密成功\n");
	}
	else
	{
   
		printf(
【实验目的】 1. 理解死锁的概念; 2. 用高级语言编写和调试一个银行家算法程序,以加深对死锁的理解。 【实验准备】 1. 产生死锁的原因  竞争资源引起的死锁  进程推进顺序不当引起死锁 2.产生死锁的必要条件  互斥条件  请求和保持条件  不剥夺条件  环路等待条件 3.处理死锁的基本方法  预防死锁  避免死锁  检测死锁  解除死锁 【实验内容】 1. 实验原理 银行家算法是从当前状态出发,逐个按安全序列检查各客户中谁能完成其工作,然后假定其完成工作且归还全部贷款,再进而检查下一个能完成工作的客户。如果所有客户都能完成工作,则找到一个安全序列,银行家才是安全的。与预防死锁的几种方法相比较,限制条件少,资源利用程度提高了。缺点:该算法要求客户数保持固定不变,这在多道程序系统中是难以做到的;该算法保证所有客户在有限的时间内得到满足,但实时客户要求快速响应,所以要考虑这个因素;由于要寻找一个安全序列,实际上增加了系统的开销.Banker algorithm 最重要的一点是:保证操作系统的安全状态!这也是操作系统判断是否分配给一个进程资源的标准!那什么是安全状态?举个小例子,进程P 需要申请8个资源(假设都是一样的),已经申请了5个资源,还差3个资源。若这个时候操作系统还剩下2个资源。很显然,这个时候操作系统无论如何都不能再分配资源给进程P了,因为即使全部给了他也不够,还很可能会造成死锁。若这个时候操作系统还有3个资源,无论P这一次申请几个资源,操作系统都可以满足他,因为操作系统可以保证P不死锁,只要他不把剩余的资源分配给别人,进程P就一定能顺利完成任务。 2.实验题目 设计五个进程{P0,P1,P2,P3,P4}共享三类资源{A,B,C}的系统,{A,B,C}的资源数量分别为10,5,7。进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。要求程序具有显示和打印各进程的某一时刻的资源分配表和安全序列;显示和打印各进程依次要求申请的资源号以及为某进程分配资源后的有关资源数据。 3.算法描述 我们引入了两个向量:Resourse(资源总量)、Available(剩余资源量) 以及两个矩阵:Claim(每个进程的最大需求量)、Allocation(已为每个进程分配的数量)。它们共同构成了任一时刻系统对资源的分配状态。 向量模型: R1 R2 R3 矩阵模型: R1 R2 P1 P2 P3 这里,我们设置另外一个矩阵:各个进程尚需资源量(Need),可以看出 Need = Claim – Allocation(每个进程的最大需求量-剩余资源量) 因此,我们可以这样描述银行家算法: 设Request[i]是进程Pi的请求向量。如果Request[i , j]=k,表示Pi需k个Rj类资源。当Pi发出资源请求后,系统按下述步骤进行检查: (1) if (Request[i]<=Need[i]) goto (2); else error(“over request”); (2) if (Request[i]<=Available[i]) goto (3); else wait(); (3) 系统试探性把要求资源分给Pi(类似回溯算法)。并根据分配修改下面数据结构中的值。 剩余资源量:Available[i] = Available[i] – Request[i] ; 已为每个进程分配的数量: Allocation[i] = Allocation[i] + Request[i]; 各个进程尚需资源量:Need[i] = Need[i]-Request[i]; (4) 系统执行安全性检查,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程以完成此次分配;若不安全,试探方案作废,恢复原资源分配表,让进程Pi等待。 系统所执行的安全性检查算法可描述如下: 设置两个向量:Free、Finish 工作向量Free是一个横向量,表示系统可提供给进程继续运行所需要的各类资源数目,它含有的元素个数等于资源数。执行安全算法开始时,Free = Available .标记向量Finish是一个纵向量,表示进程在此次检查中中是否被满足,使之运行完成,开始时对当前未满足的进程做Finish[i] = false;当有足够资源分配给进程(Need[i]<=Free)时,Finish[i]=true,Pi完成,并释放资源。 (1)从进程集中找一个能满足下述条件的进程Pi ① Finish[i] == false(未定) ② Need[i] D->B->A A 1 6 B 1 5 C 2 4 D 4 7 Available = (2) ; Resourse = (10) ; 测试结果如下 process number:5 resource number:4 resource series:6 3 4 2 assined matrix:p0:3 0 1 1 p1:0 1 0 0 p2:1 1 1 0 p3:1 1 0 1 p4:0 0 0 0 needed matrix: p0:1 1 0 0 p1:0 1 1 2 p2:3 1 0 0 p3:0 0 1 0 p4:2 1 1 0 p3-->p4-->p0-->p2-->p1 p3-->p4-->p0-->p1-->p2 p3-->p0-->p4-->p2-->p1 p3-->p0-->p4-->p1-->p2 p3-->p0-->p2-->p4-->p1 p3-->p0-->p2-->p1-->p4 p3-->p0-->p1-->p4-->p2 p3-->p0-->p1-->p2-->p4 it is safe,and it has 8 solutions
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值