• C语言银行综合业务系统


    一、系统功能设计

    1.1功能介绍

    本系统是一个关于银行储蓄业务的系统,需要保存用户(储户)在银行的基本信息、办理的银行卡的信息以及用户一定时间的交易信息。因此系统需要的核心数据有:用户数据、银行卡数据、交易数据;用户数据包括:用户编号、用户名称、身份证号、电话、地址;银行卡数据包括:银行卡号、币种、存储类型、开户日期、余额,密码,使用状态(是否注销)、用户编号;交易数据包括:交易日期、交易类型、卡号、金额。根据对银行综合业务管理系统的分析,系统的主要功能包括:从文件读出数据、从文件保存数据、用户存款、用户取款、用户转账、查询余额、查询明细、管理者开户、注销客户、查询账户、查看所有用户和账户信息等,银行综合业务平台系统的总体功能图如图1所示:
    在这里插入图片描述

    图1 系统总体功能图

    1.2设计框架

    ①定义3个结构:银行卡信息结构、交易记录结构、用户信息结构。
    ②用户信息结构包含银行卡结构、交易记录链表头结点、尾结点。
    ③一个用户信息的结构 可以存储一个用户的所有信息。
    ④使用动态数组记录每个人的信息。
    ⑤使用链表记录每个人的交易记录。
    ⑥将所有数据存储在一个文档中,易于管理。

    二、文件读写数据

    实现读取、保存、备份、刷新功能,保证操作后的数据保存问题。

    2.1从文件读取数据

    首先读取用户信息,再读取用户银行卡信息,最后读取交易记录,通过判断结束标识-1 来判断是否结束切换后一个人。在这里是利用标识判断结束标识来判断结束的,即最后的 “over -1 over -1”是有效的结束标识。标志此人信息结束,用于分隔两个人的数据。利用while 循环不断循环以上过程,读出所有人的数据。

    ①首先打开文件 
    fopen_s(&fp, "UserBase.md", "r");
    ②判断是否打开成功   	
    if (fp == NULL)
          {
                printf("打开文件失败!\n");
    	  exit(0);
         }
    ③为动态数组申请一段初始长度用于存储数据
    arr = (UserInfo*)malloc(LEN_User*100); 
    ④读取此人银行卡信息和个人信息
    sign = fscanf_s(fp, "%d %s %s %s %s %d %d\n", &arr[n].number, arr[n].name, 19, arr[n].phone_id, 19, arr[n].address, 24, arr[n].ID_num, 24, &arr[n].sex,&(arr[n].cord).status);//读取个人信息
    sign = fscanf_s(fp, "%s %s %ld %d %s %d\n", (arr[n].cord).app_time, 29, (arr[n].cord).card_id, 29, &(arr[n].cord).moneynum, &(arr[n].cord).moneytype, (arr[n].cord).password, 19, &(arr[n].cord).phase);  
    //读取个人银行卡信息
    //fscanf_s返回成功读取的个数,这里用来判断读取结束。
    ⑤读取此人交易记录
    arr[n].record_h = (Trad_Record*)malloc(LEN_TRcord);   //为链表头申请内存
    tr_t1 = arr[n].record_h;   
    fscanf_s(fp, "%s %d %s %d\n", tr_t1->trad_time,29, &tr_t1->trad_type,
    tr_t1->card,29, &tr_t1->money);   //读取第一条记录
    signt = (tr_t1->trad_type == -1 && tr_t1->money == -1);  //判断是否结束
    tr_t2 = (Trad_Record*)malloc(LEN_TRcord);  //  申请第二个节点的内存
    if (!signt)    //若未结束 ,则再读入一条记录
    {
    		fscanf_s(fp, "%s %d %s %d\n", tr_t2->trad_time, 29, &tr_t2->trad_type,
     tr_t2->card, 29, &tr_t2->money);
    		signt = (tr_t2->trad_type == -1 && tr_t2->money == -1);   //再次判断是否结束
    }
    if (!signt)   //若未结束 ,则插入这条数据
    {
    		tr_t1->next = tr_t2;
    		tr_t1 = tr_t2;
    		tr_t2 = (Trad_Record*)malloc(LEN_TRcord);
    		if (tr_t2 == NULL)
    		{
    			printf("error\n");
    			exit(0);
    		}
    }
    while (!signt)  //若未结束 ,则再读入一条记录
    	{
    		fscanf_s(fp, "%s %d %s %d\n", tr_t2->trad_time, 29, 
    &tr_t2->trad_type, tr_t2->card, 29, &tr_t2->money);
    		signt = (tr_t2->trad_type == -1 && tr_t2->money == -1);
    		if (signt)
    			break;
    		tr_t1->next = tr_t2;
    		tr_t1 = tr_t2;
    		tr_t2 = (Trad_Record*)malloc(LEN_TRcord);
    	}
    tr_t1->next = NULL;   //最后一条记录指向空
    arr[n].record_last = tr_t1;	//保存最后一条记录便于以后增加
    free(tr_t2);   //释放掉未使用的节点
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    2.2从文件保存数数据

    ①打开文件
    fopen_s(&fp, "UserBase.md", "w");
    ②保存个人信息(格式严格一一对应)
    fprintf(fp,"%d %s %s %s %s %d %d\n",arr[n].number,arr[n].name,arr[n].phone_id,arr[n].address,arr[n].ID_num,arr[n].sex, (arr[n].cord).status);
    fprintf(fp,"%s %s %ld %d %s %d\n",(arr[n].cord).app_time,(arr[n].cord).card_id,(arr[n].cord).moneynum,(arr[n].cord).moneytype,(arr[n].cord).password,(arr[n].cord).phase);
    ③保存个人交易记录(简单的遍历链表)
    p = arr[n].record_h;
    while (p != NULL)
      {
           fprintf(fp, "%s %d %s %d\n", p->trad_time, p->trad_type, p->card, p->money);
           p = p->next;
          }
    ④关闭文件! (防止数据丢失)
    fclose(fp);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.3备份文件

    类似上面的保存文件,只有打开文件处改变。
    ①即fopen_s(&fp, “back.md”, “w”); //打开备份文件
    ②将数据保存到“back.md”即可。

    三、常用结构体及函数

    通过适当的定义全局变量和函数,使得系统程序语言更容易读懂和理解。

    3.1全局变量

    extern UserInfo *arr;     //盛放动态数组首地址
    extern int UserNum;	  //记录用户数
    extern int ArrNum;		  //记录动态数组长度
    extern int SaveFlag;	  //记录保存状态
    extern const char SAVEFLAG[2][10];		//保存状态
    extern const char MONEY_TYPE[3][10];	//币种
    extern const char PHASE[2][10];			//交易期限
    extern const char TRAD_TYPE[5][10];		//交易类型
    extern const char STATUS[2][10];			//用户银行卡状态
    extern const char SEX[2][10];			//性别
    extern const char TITLE[16][15];			//表头
    extern const char CAOZUO[2][10];		//操作
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.2客户信息结构体

    typedef struct UserInfo    //用户信息,包含(基本信息、银行卡信息、交易记录)
    {
    	int number;       //编号
    	char name[20];    //姓名
    	char phone_id[20]; //手机号
    	char address[25];		//籍贯
    	char ID_num[25];		//身份证
    	int sex;    //0.男      1.女
    	BankCardInfo cord;   //银行卡结构
    	Trad_Record* record_h;		//记录链表头
    	Trad_Record* record_last;	//记录链表尾
    }UserInfo;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.3 全局常量字符串

    const char TITLE[16][15] = {
    	{"编号"},		//0
    	{"姓名"},		//1
    	{"手机号码"},	//2
    	{"户籍"},		//3
    	{"身份证号"},	//4
    	{"性别"},		//5
    	{"银行卡号"},	//6
    	{"开户时间"},	//7
    	{"余额"},		//8
    	{"币种"},		//9
    	{"登录密码"},	//10
    	{"期限"},		//11
    	{"交易记录"},	//12
    	{"交易时间"},   //13
    	{"交易类型"},	//14
    	{"交易金额"},	//15
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这里是记录表头信息的一些常量,通过 0 1 2 等数字直接引用这里的字符串。
    例如输出表头:

    void print_title_cord()
    {
    	printf("%-30s%-30s%-10s%-8s%-15s%-8s\n", TITLE[6], TITLE[7], TITLE[8], TITLE[9], TITLE[10], TITLE[11]);     //此处是引用了全局常量字符串
    }
    
    • 1
    • 2
    • 3
    • 4

    3.4 银行卡信息结构体

    typedef struct BankCardInfo
    {
    	char card_id[30];    //银行卡号
    	int moneytype;        //币种:0代表人民币,1代表美元,2代表欧元
    	int phase;         //0.活期 or 1.定期
    	char app_time[30];     //申请日期
    	long moneynum;			//余额
    	char password[20];		//登录密码
    	int status;			//1.正常    0.注销
    }BankCardInfo;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.5 银行交易记录结构体

    typedef struct Trad_Record
    {
    	char trad_time[30];		//交易时间
    	int trad_type;      //0.存款,1.取款,2.挂失
    	char card[30];		//交易的卡号
    	long money;			//交易金额
    	struct Trad_Record *next;	//下一条信息
    }Trad_Record;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.6 得到系统时间函数

    char* GetNowTime(char* nowtime)
    {
    	struct tm t;   //tm结构指针
    	time_t now;  //声明time_t类型变量
    	time(&now);      //获取系统日期和时间
    	localtime_s(&t, &now);   //获取当地日期和时间
    	strftime(nowtime, 29, "%Y-%m-%d~%H:%M:%S", &t);
    	return nowtime;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.7 根据卡号,寻找用户下标函数

    int location_CordID(char* id)
    {
    int i;
    	for (i = 0; i < UserNum; i++)
    	{
    		if (strcmp(id, (arr[i].cord).card_id) == 0)
    			break;
    	}
    	if (i < UserNum)
    		return i;
    	else
    		return -1;
    } //根据卡号寻找,找到返回下标,否则返回-1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.8 根据身份证,寻找用户下标函数

    int location_ID(char* id)
    {
    	int i;
    	for (i = 0; i < UserNum; i++)
    	{
    		if (strcmp(id, arr[i].ID_num) == 0)
    			break;
    	}
    	if (i < UserNum)
    		return i;
    	else
    		return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.9输出函数

    void print_record(int n);  	 //输出记录
    void print_login_page();		//输出主页面
    void print_login_admin();	//输出管理人员菜单
    void print_login_user();		//输出用户菜单
    void print_title_user();		//输出用户信息表头
    void print_title_cord();		//输出银行卡信息表头
    void print_all_cord();		//输出所以银行卡信息
    void print_all_user();		//输出所以用户信息
    void print_person(int n);		//输出个人详细信息
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    四、系统设计

    该模块为银行客户提供基本所需功能,系统包括客户登录、取款、存款、转账、查询余额及账户明细以及退卡功能。
    主函数如下:

    int main()
    {
    	char order[10];
    	printf("\n\n\t\t载入数据库数据...\n");
    	Sleep(1000);
    	data_load();      //从文件载入数据
    	system("cls");
    	while (1)
    	{
    		system("cls");
    		print_login_page();
    		scanf_s("%s", order,9);
    		if (order[0] == '1')
    		{
    			adminfun();   //运行管理人员界面
    		}
    		else if (order[0] == '2')
    		{
    			userfun();		//运行用户界面
    		}
    		else
    		{
    			printf("错误!");
    			exit(0);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    4.1 用户系统

    登录函数如下

    int login_user()      //登录成功返回下标,
    {
    	int t;
    	int t_2;
    	int i;
    	char account[30];
    	char password[20];
    	for (i = 0; i < 3; i++)
    	{
    		printf("\t\t请输入卡号:\n\n");
    		scanf_s("%s", account, 29);
    		t = location_CordID(account);
    		if (t == -1)
    		{
    			printf("未找到该账户!\n");
    		}
    		else
    		{
    			printf("\t\t请输入密码:\n\n");
    			scanf_s("%s", password, 19);
    			t_2 = strcmp(((arr[t].cord).password), password);
    			if (t_2 != 0)
    			{
    				t = -1;	//t为-1标志失败
    				printf("密码错误!\n");
    			}
    		}
    		if (t == -1)
    		{
    			printf("请重新输入!\n");
    		}
    		else
    		{
    			break;
    		}
    	}
    	return t;
    }
    其中用户系统通过调用函数“userfun()”实现,登录成功进入,执行相应操作。
    例程为:
    void userfun()
    {
    	char str_t[30];
    	char order[10];
    	int n,t;
    	int back = 0;  //返回标志
    	n = login_user();
    	if (n != -1)	//判断登录是否成功
    	{
    		system("cls");
    		printf("登录成功请稍等...");
    		Sleep(1000);
    		while (1)
    		{
    			if (back == 1)
    				break;
    			system("cls");
    			print_login_user();
    			scanf_s("%s", order, 9);   //防止用户输出过多数据进入死循环
    			switch (order[0] - 48)
    			{
    			case 1://取款
    				withdrawal(n);    
    				break;
    			case 2://存款
    				deposit(n);   
    				break;
    			case 3://转账
    				printf("请输入转账对象银行卡号:\n");
    				scanf_s("%s", str_t, 29);
    				t = location_CordID(str_t);
    				if (t != n)       //判断转账对象是否是自己
    				{
    					if (t != -1)
    						transfer_accounts(n, t);
    					else
    						printf("找不到这个账户!\n");
    				}
    				else
    					printf("转账对象不能是自己!\n");
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 4://查询余额
    				check_balance(n);
    				break;
    			case 5://查询明细
    				print_record(n);
    				break;
    			case 6://查询状态
    				printf("当前状态是:%s \n",STATUS[(arr[n].cord).status]);
    				break;
    			case 7://确认操作
    				data_save();
    				break;
    			case 8:     //返回上一级
    				back = 1;
    				break;
    			default:
    				break;
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104

    4.1.1 取款功能

    通过调用”withdrawal()”函数实现用户取款功能。首先判断用户账号是否被注销,若账号已被注销则结束此功能;若未被注销则进入取款界面。输入取款金额,若取款金额小于0或大于账户余额则结束此功能;取款金额正确,再次确认是否取出,若不确定则结束功能;确定后,取款成功,返回用户界面,如图2所示,部分代码如下:
    在这里插入图片描述

    图2 取款流程图

    void withdrawal(int n)	 //取款
    {
    	if (isunsubscribe(n) == 0)
    	{
    		printf("账户已注销!\n");
    		goto end;
    	}
    	char nowtime[30];
    	char *p_nowtime;
    	p_nowtime = GetNowTime(nowtime);    //获取当前时间
    	Trad_Record* p;
    	long money;
    	char c_t;		
    	printf("输入取款金额:\n");
    	scanf_s("%ld",&money);
    	if (money < 0)
    	{
    		printf("金额不正确! \n退出!\n");
    		goto end;
    	}
    	printf("确定要取出%ld %s吗?(请按Y或y继续,任意键取消操作)	\n",money,MONEY_TYPE[(arr[n].cord).moneytype]);
    	getchar();       //接受缓冲器字符
    	c_t = getchar();
    	if (c_t == 'Y' || c_t == 'y')
    	{
    		if ((arr[n].cord).moneynum >= money)
    		{
    			(arr[n].cord).moneynum -= money;
    			p = (Trad_Record*)malloc(LEN_TRcord);  //添加记录(链表)
    			if (p == NULL)
    			{
    				printf("error\n");
    				exit(0);
    			}
    			arr[n].record_last->next = p;
    			p->next = NULL;
    			strcpy_s(p->card, 29,(arr[n].cord).card_id);  //29最大可用长度
    			p->money = money*(-1);
    			p->trad_type = 1;
    			strcpy_s(p->trad_time, 29, nowtime);
    			arr[n].record_last = p;
    			printf("操作成功!\n");
    		}
    		else
    			printf("余额不足!\n");
    	}
    	else
    		printf("操作取消!\n");
    	SaveFlag = 0;
    end:;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    4.1.2 存款功能

    通过函数”deposit()”实现用户存款功能。首先判断账号是否注销,若账状态正常则进入存款界面;输入存款金额,若金额正确,保存当前时间、交易类型等信息至文档,操作成功,返回用户界面。部分代码如下:

    	void deposit(int n)  //存款
    {
    	if (isunsubscribe(n) == 0)
    	{
    		printf("账户已注销!\n");
    		goto end;
    	}
    	char nowtime[30];
    	char *p_nowtime;
    	p_nowtime = GetNowTime(nowtime);    //获取当前时间
    	Trad_Record* p;
    	long money;
    	char cct;
    	printf("请将整齐的%s放入:\n", MONEY_TYPE[(arr[n].cord).moneytype]);
    	scanf_s("%ld", &money);
    	if (money < 0)
    	{
    		printf("金额不正确! \n退出!\n");
    		goto end;
    	}
    	printf("确定要存入%ld %s吗?(请按Y或y继续,任意键取消操作)\n", money, 	MONEY_TYPE[(arr[n].cord).moneytype]);
    	getchar();       //接受缓冲器字符
    	cct = getchar();
    	if (cct == 'Y' || cct == 'y')
    	{
    		(arr[n].cord).moneynum += money;
    		p = (Trad_Record*)malloc(LEN_TRcord);  //添加记录(链表)
    		if (p == NULL)
    		{
    			printf("error\n");
    			exit(0);
    		}
    		p->next = NULL;
    		strcpy_s(p->card, 29, (arr[n].cord).card_id);  //交易卡号
    		p->money = money;								//交易金额
    		p->trad_type = 0;								//交易类型
    		strcpy_s(p->trad_time, 29, nowtime);			//交易时间
    		arr[n].record_last->next = p;					//加入记录
    		arr[n].record_last = p;
    		printf("操作成功!\n");
    		SaveFlag = 0;
    	}
    	else
    		printf("操作取消!\n");
    end:;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    4.1.3转账功能

    通过调用”transfer_accounts()”函数实现转账功能。进转账界面后输入要转账的对象,首先判断转账对象是否是自己,若不是再判断转账对象是否存在,若存在则输入转账金额;判断转账金额是否正确,若正确,再次确认是否转账,确认后操作成功,返回用户界面。如图3所示,部分代码如下:
    在这里插入图片描述

    图3转账流程图

    void transfer_accounts(int a, int b)  //转账(a账户到b账户)
    {
    	if (isunsubscribe(a) == 0)
    	{
    		printf("账户%s已注销!\n",(arr[a].cord).card_id);
    		goto end;
    	}
    	if (isunsubscribe(b) == 0)
    	{
    		printf("账户%s已注销!\n", (arr[b].cord).card_id);
    		goto end;
    	}
    	char nowtime[30];
    	char *p_nowtime;
    	p_nowtime = GetNowTime(nowtime);    //获取当前时间
    	Trad_Record* p;
    	long money;
    	char cct;
    	printf("输入转账金额:\n");
    	scanf_s("%ld", &money);
    	if (money < 0)
    	{
    		printf("金额不正确! \n退出!\n");
    		goto end;
    	}
    	printf("确定要转账%ld %s到 %s 的账户吗?(请按Y或y继续,任意键取消操作)\n", money, MONEY_TYPE[(arr[a].cord).moneytype],arr[b].name);
    	getchar();       //接受缓冲器字符
    	cct = getchar();
    	if (cct == 'Y' || cct == 'y')
    	{
    		if ((arr[a].cord).moneynum >= money)
    		{
    			(arr[a].cord).moneynum -= money;
    			(arr[b].cord).moneynum += money;
    			//生成交易记录
    			p = (Trad_Record*)malloc(LEN_TRcord);  //为账户a添加记录
    			if (p == NULL)
    			{
    				printf("error\n");
    				exit(0);
    			}
    			arr[a].record_last->next = p;
    			p->next = NULL;
    			strcpy_s(p->card, 29, (arr[a].cord).card_id);
    			p->money = money*(-1);
    			p->trad_type = 2;
    			strcpy_s(p->trad_time, 29, nowtime);
    			arr[a].record_last = p;
    			p = (Trad_Record*)malloc(LEN_TRcord);  //为账户b添加记录
    			if (p == NULL)
    			{
    				printf("error\n");
    				exit(0);
    			}
    			arr[b].record_last->next = p;
    			p->next = NULL;
    			strcpy_s(p->card, 29, (arr[b].cord).card_id);
    			p->money = money;
    			p->trad_type = 2;
    			strcpy_s(p->trad_time, 29, nowtime);
    			arr[b].record_last = p;
    			printf("操作成功!\n");
    		}
    		else
    			printf("余额不足!\n");
    	}
    	else
    		printf("操作取消!\n");
    	SaveFlag = 0;
    end:;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    4.1.4 查询余额

    实现用户查询余额功能,进入查询余额后系统会将卡内余额展示出来,直接输出即可。
    部分代码如下:

    printf("您当前的余额是%ld %s \n", (arr[n].cord).moneynum, MONEY_TYPE[(arr[n].cord).moneytype]);
    
    • 1

    4.1.5查询明细

    通过调用函数“showTradeInfo()”实现用户查询账户明细的功能。进入查询账户明细界面输入卡号,则系统提供用户信息,调用函数即可。
    void print_record(int n);

    4.1.6查询状态

    (arr[n].cord).status记录用户银行卡状态 (0或1),且有定义STATUS[2][10]={{注销},{正常}};因此可以使用STATUS[(arr[n].cord).status]引用相应字符串。
    例程:
    printf(“当前状态是:%s \n”,STATUS[(arr[n].cord).status]);

    4.1.7修改密码

    为用户提供修改密码功能基本流程是:首先输入身份证判断身份证是否正确,若正确进入下一步,不正确则退出,输入原密码,判断是否正确,若正确进入下一步,不正确则退出,输入新密码,修改成功,退出。密码修改流程图,如图4所示:
    在这里插入图片描述

    图4密码修改流程图
    主要代码:

    void change_password(int n)
    {
    	char cht[30];
    	int sign;
    	printf("请输入您的身份证号:\n");
    	scanf_s("%s",cht,29);
    	sign = strcmp(cht, arr[n].ID_num);
    	if (sign == 0)
    	{
    		printf("清输入你的原密码:\n");
    		scanf_s("%s",cht,29);
    		sign = strcmp(cht, (arr[n].cord).password);
    		if (sign == 0)
    		{
    			printf("请输入你的新密码:\n");
    			scanf_s("%s",cht,29);
    			strcpy_s((arr[n].cord).password, 29, cht);
    			printf("操作成功!\n");
    		}
    		else
    		{
    			printf("原密码错误!\n");
    		}
    	}
    	else
    	{
    		printf("身份证错误!\n");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    4.1.8退卡

    使用返回标识标识 每次循环先判断是否要返回,例程为:

    while (1)
    {
    	if (back == 1)
    		break;
    	scanf_s("%s", order, 9);   //防止用户输出过多数据进入死循环
    	switch (order[0] - 48)
    	{
    	case 1:break;
    	case 2:break;
    	case 3:break;
    	case 4:break;
    	case 5:break;
    	case 6:break;
    	case 7:break;
    	case 8:back = 1;break;
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.2 管理人员系统

    银行工作人员登录系统必须具有访问权限,本系统的登录模块主要通过调用函数“login_system()”实现,其主要代码为:

    int login_system()
    {
    int sign;
    const char* ACCOUNT = "1";
    const char* PASSWORD = "1";
    char account[11];
    char password[11];
    printf("\t\t请输入账号:\n\n");
    scanf_s("%s", account, 10);
    printf("\t\t请输入密码:\n\n");
    scanf_s("%s", password, 10);
    if ((strcmp(account, ACCOUNT) == 0) && (strcmp(password, PASSWORD) == 0))
    sign = 1;
    else
    sign = 0;
    return sign;
    } 
    其中管理人员系统通过调用函数“adminfun()”实现,登录成功进入,执行相应操作:
    以下是例程为:
    void adminfun()
    {
    	char order[10];
    	char t[30];
    	int sign;
    	int back = 0;	//返回标志
    	if (login_system())
    	{
    		system("cls");
    		printf("\n\n\t\t登录成功请稍等...\n");
    		Sleep(1000);
    		while (1)
    		{
    			if (back == 1)  //返回标志
    				break;
    			system("cls");
    			print_login_admin();
    			scanf_s("%s", order, 9);
    			switch (order[0] - 48)
    			{
    			case 1:
    				open_account();
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 2:
    				printf("请输入银行卡号或身份证号:\n");
    				scanf_s("%s", t, 29);
    				sign = location_ID(t);
    				if (sign == -1)
    					sign = location_CordID(t);
    				if (sign != -1)
    					unsubscribe(sign);
    				else
    					printf("找不到这个人!\n");
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 3:
    				printf("请输入银行卡号或身份证号:\n");
    				scanf_s("%s", t, 29);
    				sign = location_ID(t);
    				if (sign == -1)
    					sign = location_CordID(t);
    				if (sign != -1)
    					print_person(sign);
    				else
    					printf("找不到这个人!\n");
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 4:
    				print_title_user();
    				print_all_user();
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 5:
    				print_title_cord();
    				print_all_cord();
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 6:      //返回上一级
    				back = 1;
    				break;
    			case 7:
    				printf("请输入银行卡号或身份证号:\n");
    				scanf_s("%s", t, 29);
    				sign = location_ID(t);
    				if (sign == -1)
    					sign = location_CordID(t);
    				if (sign != -1)
    					delate(sign);
    				else
    					printf("找不到这个人!\n");
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 8://修改账户数据
    				printf("请输入银行卡号或身份证号:\n");
    				scanf_s("%s", t, 29);
    				sign = location_ID(t);
    				if (sign == -1)
    					sign = location_CordID(t);
    				if (sign != -1)
    					revise(sign);
    				else
    					printf("找不到这个人!\n");
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 9:
    				if (data_save())
    				{
    					printf("%d条记录已经存入文件,请按任意键结束\n", UserNum);
    				}
    				printf("任意键退出...\n");
    				getch();
    				break;
    			case 0:
    				backups();     //备份函数  备份到文件"back.md"
    				printf("备份成功!\n");
    				printf("任意键退出...\n");
    				getch();
    				break;
    			default:
    				printf("输入错误!\n");
    				break;
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    4.2.1开户

    通过调用函数“open_account()”实现开户功能,输入姓名、身份证号、电话、地址得到卡号,系统生成开户日期,然后选择币种和存储类型从而实现开户,部分代码如下:

    void open_account()
    {
    	char nowtime[30];
    	char *p_nowtime;
    	p_nowtime = GetNowTime(nowtime);    //获取当前时间
    	int n,i;
    	UserInfo* t;
    	n = UserNum;
    	if (n + 5 >= ArrNum)     //判断数组长度是否足够(若不足则增加一段)并留出冗余
    	{
    		t = (UserInfo*)realloc(arr, (ArrNum + 10) * LEN_User);     //用ralloc修改原数组的长度
    		if (arr == NULL)
    		{
    			printf("申请内存失败,请按任意键返回主菜单");
    			getch();
    			exit(0);
    		}
    		ArrNum += 10;
    	}
    	printf("请输入姓名:\n");
    	scanf_s("%s",arr[n].name,19);
    	printf("请输入身份证号:\n");
    	scanf_s("%s",arr[n].ID_num,24);
    	printf("请输入手机号:\n");
    	scanf_s("%s",arr[n].phone_id,19);
    	printf("请输入户籍:\n");
    	scanf_s("%s",arr[n].address,24);
    	do
    	{
    		if (arr[n].sex == -1)
    			goto end;
    		printf("请输性别:(0男性 1女性 )\n");
    		scanf_s("%d", &arr[n].sex);
    	} while (!(arr[n].sex == 0 || arr[n].sex == 1));   //判断输入的有效性避免出现错误
    	strcpy_s((arr[n].cord).app_time,29, nowtime);   //时间
    	do
    	{
    		printf("输入币种: (0人民币 1美元 2欧元)\n");
    		scanf_s("%d", &(arr[n].cord).moneytype);
    	} while (!(((arr[n].cord).moneytype == 0) || ((arr[n].cord).moneytype == 1) || ((arr[n].cord).moneytype == 	2)));
    	do
    	{
    		printf("输入存款期限: (0活期 1定期)\n");
    		scanf_s("%d", &(arr[n].cord).phase);
    	} while (!((((arr[n].cord).phase)==0) || (((arr[n].cord).phase)==1)));
    	printf("输入存款金额:\n");
    	scanf_s("%ld", &(arr[n].cord).moneynum);
    	printf("设置密码:\n");
    	scanf_s("%s", (arr[n].cord).password,19);
    	(arr[n].cord).status = 1;   //状态置正常
    	printf("正在为您生成卡号!\n");
    	strcpy_s((arr[n].cord).card_id,29 ,"621700021000");      //前12位固定
    	do
    	{
    		for (i = 0; i < 7; i++) //后7位随机
    		{
    			(arr[n].cord).card_id[i + 12] = (rand() % 10) + 48;  
    		}
    		(arr[n].cord).card_id[i + 12] = '\0';
    	} while (location_CordID((arr[n].cord).card_id) != -1);   //设置条件,防止重复
    	arr[n].number = n + 1;    //设置编号
    	printf("您的卡号是:%s \n", (arr[n].cord).card_id);
    	//生成初始记录
    	arr[n].record_h = (Trad_Record*)malloc(LEN_TRcord);
    	if (arr[n].record_h == NULL)
    	{
    		printf("error!\n");
    		exit(0);
    	}
    	strcpy_s((arr[n].record_h)->card, 29, (arr[n].cord).card_id);
    	strcpy_s((arr[n].record_h)->trad_time, 29, nowtime);
    	(arr[n].record_h)->trad_type = 3;
    	(arr[n].record_h)->money = (arr[n].cord).moneynum;
    	(arr[n].record_h)->next = NULL;
    	arr[n].record_last = arr[n].record_h;
    	n=n+1;      //增加一个人
    	UserNum = n;
    	SaveFlag = 0; //标志未保存
    	end:;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    五、系统实现

    软件测试是为了发现程序中的错误而执行程序的过程。软件测试目的是尽可能多的发现并排除软件中隐藏的错误,最终把一个高质量的软件交给用户使用。系统主界面,如图5所示:

    系统主界面

    在这里插入图片描述

    5.1用户功能实现

    用户在进入到用户功能界面后,用户主界面,如图6所示:
    在这里插入图片描述

    图6用户主界面

    5.1.1取款

    用户在进入到取款界面后,并且输入取款金额,再按y确认取款,完成取款详细界面,如图7所示:
    在这里插入图片描述

    图7取款界面

    5.1.2存款

    用户在进入到存款界面后,可以输入存款金额,并且输入存款金额,再按y确认操作详细界面如图8所示。
    在这里插入图片描述

    图8存款界面

    5.1.4查询余额

    用户在进入到查询余额界面后,在屏幕上输出余额,详细界面如图10所示。在这里插入图片描述

    图10查询余额

    5.1.6查询状态
    用户在进入到查询状态界面后,在屏幕上输出当前状态,详细界面如图12所示。在这里插入图片描述

    图12查询状态

    5.2管理人员功能实现

    用户在进入到用户功能界面后,界面如图14所示。在这里插入图片描述

    图14管理员主界面

    六、交流与联系

    q:969060742 完整代码、报告、程序资源
    
    • 1
  • 相关阅读:
    springboot vue 部署至Rocky(Centos)并自启,本文部署是若依应用
    Android 11 设置开机默认系统横屏显示
    【Torch】torch.load( )系列语句解读解读,易学易用
    Charles抓包
    FFplay文档解读-49-多媒体过滤器三
    APP 开发中的费用一般用在哪里?
    qt day2
    优秀论文以及思路分析02
    SpringCloud微服务实战——搭建企业级开发框架(四十五):【微服务监控告警实现方式二】使用Actuator(Micrometer)+Prometheus+Grafana实现完整的微服务监控
    nginx的安装与配置启动(linux)
  • 原文地址:https://blog.csdn.net/m0_58065010/article/details/133692335