银行管理系统

一个简单的银行管理系统,利息管理部分尚未实现(2025年末数据结构结课作业)

另外所有输入都有严格验证机制,不会因用户的错误输入导致系统瘫痪,铁子们可以放心尝试

main.c

cpp 复制代码
#include <stdio.h>
#include <time.h>
#include "Bank.h"

int main(void)
{
	int choice;
	LinkList L;//单链指针
	SqList S;//顺序表指针
	InitList(&L);//初始化单链表
	InitListSq(&S);//初始化顺序表
	menu();
	while ((choice = get_choice()) != 'q')
	{
		switch (choice)
		{
		case '1'://开户
		{
			ElemTypeLink e;
			ElemTypeSq se;
			time_t current_time;
			time(&current_time);
			fputs("请输入卡号:", stdout);
			//获取并校验卡号
			Verify_Card(e.card_number);
			fputs("请输入户人姓名:", stdout);
			scanf_s("%s", e.name,MAX_NAME);
			fputs("请输入户人电话:", stdout);
			//获取并校验手机号
			Verify_Phone(e.phone);
			fputs("请输入户人身份证号:", stdout);
			//获取并校验身份证号
			Verify_Id(e.id);
			fputs("请输入账户密码:", stdout);
			//获取并校验密码
			Verify_Password(e.password);
			e.current_money = 0;//余额初始化为0
			//获取开户时间
			ctime_s(e.start_date, sizeof(e.start_date), &current_time);
			if (ListInsert(L, 1, e))puts("开户成功!");
			else puts("开户失败!");
			//存储操作记录
			Save_Record(&S, &se, &e,"开户");
			break;
		}
		case '2'://销户
		{
			ElemTypeSq se;
			char temp_card[MAX_CARD];
			fputs("请输入要销户的卡号:", stdout);
			Verify_Card(temp_card);
			//定位该卡在链表中的位置
			int location = LocateElem(L, temp_card);
			LNode* e = LocateLNode(L, temp_card);
			if (location == 0)
			{
				puts("未查询到该账户!");
				break;
			}
			Save_Record(&S, &se, e,"销户");
			if (ListDelete(L, location))puts("销户成功!");
			else puts("销户失败!");
			break;
		}
		case '3'://查询
		{
			ElemTypeSq se;
			int temp_choice;
			LNode* location;
			inquire_menu();
			fputs("请选择要查询的选项:", stdout);
			scanf_s("%d", &temp_choice);
			switch (temp_choice)
			{
			case 1://查询账户信息
			{
				char temp_card[MAX_CARD];
				char temp_password[MAX_PASSWORD];
				fputs("请输入要查询的卡号:", stdout);
				Verify_Card(temp_card);
				location = LocateLNode(L, temp_card);
				if (!location)
				{
					puts("未查询到该账户!");
					break;
				}
				while (1)
				{
					fputs("请输入账户密码:", stdout);
					Verify_Password(temp_password);
					temp_password[MAX_PASSWORD - 1] = '\0';
					if (!strncmp(temp_password, location->data.password, MAX_CARD))
					{
						printf("卡号:%s\n", location->data.card_number);
						printf("开户人:%s\n", location->data.name);
						printf("预留电话:%s\n", location->data.phone);
						printf("开户人身份证号:%s\n", location->data.id);
						printf("余额:%.2f\n", location->data.current_money);
						printf("开户日期:%s\n", location->data.start_date);
						break;
					}
					puts("密码错误!");
				}
				Save_Record(&S, &se, location, "查询账户信息");
				break;
			}
			case 2://查询交易记录
			{
				Show_ListSq(&S);
				break;
			}
			}
			break;
		}
		case '4'://存款
		{
			ElemTypeSq se;
			char temp_card[MAX_CARD];
			double temp_money = 0;
			fputs("请输入要存款的卡号:", stdout);
			Verify_Card(temp_card);
			LNode* location = LocateLNode(L, temp_card);
			if (!location)
			{
				puts("未查询到该账户!");
				break;
			}
			fputs("请输入存款金额:", stdout);
			scanf_s("%lf", &temp_money);
			location->data.current_money += temp_money;
			puts("存款成功!");
			Save_Record(&S, &se, location, "存款");
			break;
		}
		case '5'://取款
		{
			ElemTypeSq se;
			char temp_card[MAX_CARD];
			char temp_password[MAX_PASSWORD];
			double temp_money = 0;
			fputs("请输入要取款的卡号:", stdout);
			Verify_Card(temp_card);
			LNode* location = LocateLNode(L, temp_card);
			if (!location)
			{
				puts("未查询到该账户!");
				break;
			}
			while (1)
			{
				fputs("请输入账户密码:", stdout);
				Verify_Password(temp_password);
				if (!strncmp(temp_password, location->data.password, MAX_CARD))
				{
					fputs("请输入取款金额:", stdout);
					scanf_s("%lf", &temp_money);
					if (temp_money > location->data.current_money)
						puts("余额不足");
					else
					{
						location->data.current_money -= temp_money;
						puts("取款成功!");
					}
					break;
				}
				puts("密码错误!");
			}
			Save_Record(&S, &se, location, "取款");
			break;
		}
		case '6'://转帐
		{
			ElemTypeSq se;
			char temp_card1[MAX_CARD];
			char temp_card2[MAX_CARD];
			char temp_password[MAX_PASSWORD];
			double temp_money = 0;
			fputs("请输入出帐的卡号:", stdout);
			Verify_Card(temp_card1);
			LNode* location1 = LocateLNode(L, temp_card1);
			if (!location1)
			{
				puts("未查询到出账账户!");
				break;
			}
			while (1)
			{
				fputs("请输入账户密码:", stdout);
				Verify_Password(temp_password);
				if (!strncmp(temp_password, location1->data.password, MAX_CARD))
				{
					fputs("请输入收款的卡号:", stdout);
					Verify_Card(temp_card2);
					LNode* location2 = LocateLNode(L, temp_card2);
					if (!location2)
					{
						puts("未查询到收款账户!");
						break;
					}
					fputs("请输入转账金额:", stdout);
					scanf_s("%lf", &temp_money);
					if (temp_money > location1->data.current_money)
						puts("余额不足");
					else
					{
						location1->data.current_money -= temp_money;
						location2->data.current_money += temp_money;
						puts("转账成功!");
					}
					break;
				}
				puts("密码错误!");
			}
			Save_Record(&S, &se, location1, "取款");
			break;
		}
		case '7'://利息管理
			break;
		}
		while (getchar() != '\n');
		//ShowList(L);
		putchar('\n');
		menu();
	}
	return 0;
}

LinkList.c

cpp 复制代码
#include "LinkList.h"

Status InitList(LinkList* L)//初始化(新建一个只有头结点的链表,即新建空表)
{
    //为头结点分配内存并让头指针指向头结点
    *L = (LinkList)malloc(sizeof(LNode));
    if (*L == NULL)
    {
        fprintf(stderr, "初始化失败,内存分配不成功!\n");
        return ERROR;
    }
    //将头结点的next初始化为空
    (*L)->next = NULL;
    //fprintf(stdout,"初始化成功!\n");
    return OK;
}

Status DestroyList(LinkList* L)//彻底摧毁链表(释放包括头结点的所有结点内存并置空头指针)
{
    //已经被销毁
    if (*L == NULL) return OK;
    //让p指向头结点
    LNode* p = *L;
    LNode* temp;
    while (p != NULL)
    {
        //临时指向被释放的第i个结点(指向当前结点)
        temp = p;
        //p指向i+1个结点(指向当前结点的下一个结点)
        p = p->next;
        //释放第i个结点的内存(释放当前结点)
        free(temp);
    }
    //置空头指针,避免导致悬空指针
    *L = NULL;
    //fprintf(stdout,"销毁成功\n");
    return OK;
}

Status ClearList(LinkList L)//将链表重置为空表
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    //如果头结点的next为空,则已经是空表
    if (L->next == NULL)
    {
        //fprintf(stderr,"链表已经是空的,无需清空!\n");
        return OK;
    }
    //新建结点指针p,并让其指向首元结点,即头结点的next
    LNode* p = L->next;
    LNode* temp;
    while (p != NULL)
    {
        //临时指向第i个结点(指向当前结点)
        temp = p;
        //p指向第i+1个结点(指向当前结点的下一个结点)
        p = p->next;
        //释放第i个结点(释放当前结点)
        free(temp);
    }
    L->next = NULL;//头结点的next置空
    //fprintf(stdout,"已成功清空链表\n");
    return OK;
}

Status ListEmpty(LinkList L)//判断链表是否为空
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    else if (L->next == NULL) return OK;
    else return ERROR;
}

int ListLength(LinkList L)//返回链表中的元素个数,即除头结点外其余结点的个数
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return -1;
    }
    int ElemCount = 0;
    LNode* p = L->next;
    while (p != NULL)
    {
        ElemCount++;
        p = p->next;
    }
    return ElemCount;
}

Status GetElem(LinkList L, int i, ElemTypeLink* e)//取值
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    //新建一个结点指针p,并让其指向首元结点
    LNode* p = L->next;
    //计数器初值赋为1
    int j = 1;
    //如果p不为空并且计数器小于要获取的结点位置
    while (p && j < i)
    {
        //p指向下一个结点
        p = p->next;
        //计数器j相应加1
        ++j;
    }
    //如果p为空(p指向尾结点),或计数器大于要获取的结点位置
    //如果p为空(p指向尾结点),或计数器大于要获取的结点位置
    if (!p || j > i)
    {
        fprintf(stderr, "取值失败!\n");
        return ERROR;
    }
    //查找成功以后,将p指向结点的数据域赋值给e
    *e = p->data;
    //fprintf(stdout,"取值成功!\n");
    return OK;
}

int LocateElem(LinkList L, char card[])//查找
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return 0;
    }
    int i = 1;
    //新建一个结点指针p,并让其指向首元结点
    LNode* p = L->next;
    //如果p不为空并且p所指向结点的数据域与要查找的元素不同
    while (p && strncmp(p->data.card_number, card, MAX_CARD))
    {
        i++;
        //查找下一个结点
        p = p->next;
    }
    //如果p指向空说明遍历完整个链表都没找到,p等于表尾的next
    if (p == NULL)
    {
        fprintf(stderr, "查找失败!未找到!\n");
        return 0;
    }
    else;//fprintf(stdout,"查找成功!\n");
    //查找成功,返回指向查找目标的指针p
    return i;
}

LNode* LocateLNode(LinkList L, char card[])
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return NULL;
    }
    //新建一个结点指针p,并让其指向首元结点
    LNode* p = L->next;
    //如果p不为空并且p所指向结点的数据域与要查找的元素不同
    while (p && strncmp(p->data.card_number,card,MAX_CARD))
        //查找下一个结点
        p = p->next;
    //如果p指向空说明遍历完整个链表都没找到,p等于表尾的next
    if (p == NULL)fprintf(stderr, "查找失败!未找到!\n");
    else;//fprintf(stdout,"查找成功!\n");
    //查找成功,返回指向查找目标的指针p
    return p;
}

Status PriorElem(LinkList L, ElemTypeLink cur_e, ElemTypeLink* pre_e)//返回指定元素的前驱
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    //如果链表为空,返回错误
    if (ListEmpty(L))
        return ERROR;
    //如果指定元素为第一个元素,即首元结点的数据域
    if (!strncmp(L->next->data.name, cur_e.name, MAX_NAME))
    {
        fprintf(stderr, "该元素无前驱\n");
        return ERROR;
    }
    else//如果非第一个元素
    {
        //新建结点指针p,并让其指向首元结点
        LNode* p = L->next;
        while (p->next != NULL)
        {
            //从首元结点开始,依次判断当前结点下一个结点的
            //数据域是否等于指定元素,如果是,则当前结点
            //为指定元素的前驱
            if (!strncmp(p->next->data.name, cur_e.name, MAX_NAME))
            {
                *pre_e = p->data;
                return OK;
            }
            p = p->next;
        }
        fprintf(stderr, "未找到该元素\n");
        return ERROR;
    }
}

Status NextElem(LinkList L, ElemTypeLink cur_e, ElemTypeLink* next_e)//返回指定元素的后继
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    //从首元结点开始
    LNode* p = L->next;
    while (p != NULL)
    {
        //检查当前结点的数据域是否为指定元素
        if (!strncmp(p->next->data.name, cur_e.name, MAX_NAME))
            //如果当前结点不是尾结点
            //则当前结点的next为指定元素的后继
            if (p->next != NULL)
            {
                *next_e = p->next->data; return OK;
            }
        //当前结点是尾结点
            else
            {
                fprintf(stderr, "该元素无后继\n"); return ERROR;
            }
        p = p->next;
    }
    fprintf(stderr, "未找到该元素\n");
    return ERROR;
}

Status ListInsert(LinkList L, int i, ElemTypeLink e)//插入
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    //新建一个结点指针p,并让其指向头结点
    LNode* p = L;
    //计数器初始化为0
    int j = 0;
    //如果p不为空,并且计数器小于待插入位置的前一个
    while (p && (j < i - 1))
    {
        p = p->next;
        ++j;
    }
    //i>n+1或i<1
    if (!p || j > i - 1) return ERROR;
    //生成新结点s
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)
    {
        fprintf(stderr, "结点创建失败,内存分配不成功\n");
        return ERROR;
    }
    //将待插入数据存入s
    s->data = e;
    //在第i个位置插入,即插入ai-1与ai之间,让s指向ai
    s->next = p->next;
    //让ai-1指向s
    p->next = s;
    //fprintf(stdout,"添加成功\n");
    return OK;
}

Status ListDelete(LinkList L, int i)//删除
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    //新建结点指针p,并让其指向头结点
    LNode* p = L;
    //计数器置0
    int j = 0;
    //从头开始直到找到第i-1个结点
    while ((p->next) && (j < i - 1))
    {
        p = p->next;
        ++j;
    }
    //如果遍历完都没找到或者i的位置不合理,报错
    if (!(p->next) || (j > i - 1)) return ERROR;
    //新建临时结点指针q,并用其临时存储第i个结点的位置
    LNode* q = p->next;
    //让第i-1个结点指向第i+1个结点
    p->next = q->next;
    //删除第i个结点
    free(q);
    //fprintf(stdout,"删除成功\n");
    return OK;
}

Status ListExist(LinkList L)//判断链表是否初始化
{
    if (L == NULL)
    {
        fprintf(stderr, "链表不存在或未初始化!\n");
        return ERROR;
    }
    else
        return OK;
}

void ShowList(LinkList L)
{
    if (L == NULL)
    {
        puts("链表不存在或未初始化!");
        return;
    }
    LNode* p = L->next;
    while (p != NULL)
    {
        printf("卡号:%s\n", p->data.card_number);
        printf("开户人:%s\n", p->data.name);
        printf("预留电话:%s\n", p->data.phone);
        printf("开户人身份证号:%s\n", p->data.id);
        printf("余额:%.2f\n", p->data.current_money);
        printf("开户日期:%s\n", p->data.start_date);
        p = p->next;
    }
}

LinkList.h

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef MAX_NAME
    #define MAX_NAME 20
    #define MAX_CARD 20
    #define MAX_PHONE 12
    #define MAX_ID 19
    #define MAX_PASSWORD 20
#endif 

#ifndef OK
    #define OK 1
#endif // !OK

#ifndef ERROR
    #define ERROR 0
#endif // !ERROR

#ifndef OVERFLOW
    #define OVERFLOW -2
#endif // !OVERFLOW
typedef int Status;

//使用时将int改为需要的元素类型即可
typedef struct
{
    char card_number[MAX_CARD];
    char name[MAX_NAME];
    double current_money;
    double regular3_money;
    double regular5_money;
    char phone[MAX_PHONE];
    char id[MAX_ID];
    char password[MAX_PASSWORD];
    char start_date[27];
}ElemTypeLink;

typedef struct LNode
{
    ElemTypeLink data;
    struct LNode* next;
}LNode, * LinkList;

Status InitList(LinkList* L);
Status DestroyList(LinkList* L);
Status ClearList(LinkList L);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Status GetElem(LinkList L, int i, ElemTypeLink* e);
int LocateElem(LinkList L, char []);
LNode* LocateLNode(LinkList L, char[]);
Status PriorElem(LinkList L, ElemTypeLink cur_e, ElemTypeLink* pre_e);
Status NextElem(LinkList L, ElemTypeLink cur_e, ElemTypeLink* next_e);
Status ListInsert(LinkList L, int i, ElemTypeLink e);
Status ListDelete(LinkList L, int i);
Status ListExist(LinkList L);
void ShowList(LinkList L);

SqList.c

cpp 复制代码
#include "SqList.h"
#include <string.h>

Status InitListSq(SqList* L)//初始化顺序表
{
	//为顺序表分配存储空间
	L->elem = (ElemTypeSq*)malloc(sizeof(ElemTypeSq) * MAXSIZE);
	//如果分配失败返回错误信息
	if (!L->elem)return OVERFLOW;
	//顺序表的实际使用长度初始化为0
	L->length = 0;
	return OK;
}

Status DestroyListSq(SqList* L)//摧毁顺序表
{
	//释放存储顺序表的内存空间
	if (L->elem != NULL)
	{
		free(L->elem);
		L->elem = NULL;
	}
	L->length = 0;
	return OK;
}

Status ClearListSq(SqList* L)//清空顺序表
{
	//顺序表的实际使用长度重新置为0
	L->length = 0;
	return OK;
}

Status ListEmptySq(SqList L)//判断表是否为空
{
	if (L.length == 0)
		return OK;
	else
		return ERROR;
}

int ListLengthSq(SqList L)//返回表的实际使用长度
{
	return L.length;
}

Status GetElemSq(SqList L, int i, ElemTypeSq* e)//取值(获取顺序表中第i个元素)
{
	if (i<1 || i>L.length)
	{
		//puts("读取失败,位置错误!");
		fprintf(stderr, "错误:读取失败,位置%d无效(表长:%d)\n",
			i, L.length);
		return ERROR;
	}
	*e = L.elem[i - 1];
	return OK;
}

int LocateElemSq(SqList L, ElemTypeSq e)//查找定位(返回e在表中的序号)
{
	//将表中元素逐个与e比较,直到找到相同或表尾
	//此处对比方法不适用于结构体元素,若元素为结构体
	//则需要修改if语句,因为C无法直接对比两个结构体是否相同
	for (int i = 0; i < L.length; i++)
		if (strncmp( L.elem[i].trader_number ,e.trader_number,4))return i + 1;
	//遍历整个表都没找到,打印错误信息并返回0
	//puts("表中没有该元素");
	return 0;
}

Status PriorElemSq(SqList L, ElemTypeSq cur_e, ElemTypeSq* pre_e)//返回指定元素前驱
{
	//先定位要查找前驱的元素在表中的位置
	int location = LocateElemSq(L, cur_e);
	//如果在表中找到了该元素
	if (location)
	{
		//如果这个元素是第一个元素,则无前驱
		if (location == 1)
		{
			//puts("该元素是第一个,无前驱");
			fprintf(stderr, "该元素是第一个,无前驱\n");
			return ERROR;
		}
		//不是第一个元素,用pre_e返回其前一个元素的值
		//下标从零开始,故减2
		else
		{
			*pre_e = L.elem[location - 2];
			return OK;
		}
	}
	//表中没有找到该元素(LocateElemSq返回0),返回错误
	return ERROR;
}

Status NextElemSq(SqList L, ElemTypeSq cur_e, ElemTypeSq* next_e)//返回指定元素后继
{
	//先定位要查找后继的元素在表中的位置
	int location = LocateElemSq(L, cur_e);
	if (location)
	{
		//如果这个元素是最后一个元素,则无后继
		if (location == L.length)
		{
			//puts("该元素是最后一个,无后继");
			fprintf(stderr, "该元素是最后一个,无后继\n");
			return ERROR;
		}
		//不是最后一个元素,用next_e返回其后一个元素的值
		else
		{
			*next_e = L.elem[location];
			return OK;
		}
	}
	//表中没有找到该元素(LocateElemSq返回0),返回错误
	return ERROR;
}

Status ListInsertSq(SqList* L, int i, ElemTypeSq e)//插入(在表的第i个位置上插入新元素)
{
	//如果删除位置不为正整数(0和负整数)或大于表的长度+1则返回错误
	//首先因为i为int,所有默认传进来的都是整数,则i<1时为0或负整数
	//可以在表尾插入,故插入位置可以等于表长+1,但不能大于
	if ((i < 1) || (i > L->length + 1))
	{
		//puts("插入位置不存在!");
		fprintf(stderr, "错误:在位置%d插入失败,当前表长%d\n",
			i, L->length);
		return ERROR;
	}
	//如果实际表长等于最大容量,则无法插入返回错误
	if (L->length == MAXSIZE)
	{
		//puts("表已满,无法插入!");
		fprintf(stderr, "错误:表已满,当前表长%d\n", ListLengthSq(*L));
		return ERROR;
	}
	//插入位置之后的元素逐个后移(包括插入前的第i个元素)
	for (int j = L->length - 1; j >= i - 1; j--)
		L->elem[j + 1] = L->elem[j];
	//新元素放入表中第i个位置上
	L->elem[i - 1] = e;
	//插入新元素后,表的实际使用长度加1
	(L->length)++;
	//puts("插入成功!");
	return OK;
}

Status ListDeleteSq(SqList* L, int i)//删除(将表中第i个元素删去)
{
	//如果删除位置不为正整数(0和负整数)或大于表的长度则返回错误
	if ((i < 1) || (i > L->length))
	{
		fprintf(stderr, "错误:删除位置%d不存在,当前表长%d\n",
			i, ListLengthSq(*L));
		return ERROR;
	}
	//被删元素之后的所有元素逐个前移
	for (int j = i; j <= L->length - 1; j++)
		L->elem[j - 1] = L->elem[j];
	//删除第i个元素后,表的实际长度减1
	--L->length;
	//puts("删除成功!");
	return OK;
}

void Show_ListSq(SqList* L)
{
	for (int i = 0; i < L->length; i++)
		printf("%d %s %s %s", L->elem[i].trader_number,
			L->elem[i].trader, L->elem[i].trader_type, L->elem[i].trading_time);
}

SqList.h

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef MAX_NAME
#define MAX_NAME 20
#endif // !MAX_NAME


#ifndef OK
#define OK 1
#endif // !OK

#ifndef ERROR
#define ERROR 0
#endif // !ERROR

#ifndef OVERFLOW
#define OVERFLOW -2
#endif // !OVERFLOW


#ifndef Status
typedef int Status;
#endif // !Status

//顺序表可能的最大长度,使用时按实际需求更改
#define MAXSIZE 500

//使用时将int改为需要的元素类型即可
typedef struct
{
	char trading_time[27];//交易时间
	char trader[MAX_NAME];//交易人
	char trader_type[20]; //交易类型
	int trader_number;	  //交易编号
}ElemTypeSq;

typedef struct
{
	ElemTypeSq* elem;
	int length;
}SqList;

Status InitListSq(SqList* L);
Status DestroyListSq(SqList* L);
Status ClearListSq(SqList* L);
Status ListEmptySq(SqList L);
int ListLengthSq(SqList L);
Status GetElemSq(SqList L, int i, ElemTypeSq* e);
int LocateElemSq(SqList L, ElemTypeSq e);
Status PriorElemSq(SqList L, ElemTypeSq cur_e, ElemTypeSq* pre_e);
Status NextElemSq(SqList L, ElemTypeSq cur_e, ElemTypeSq* next_e);
Status ListInsertSq(SqList* L, int i, ElemTypeSq e);
Status ListDeleteSq(SqList* L, int i);
void Show_ListSq(SqList* L);

Bank.c

cpp 复制代码
#include "Bank.h"
#include <time.h>
void menu(void)
{
	puts("     银行管理系统");
	puts("1.开户\t2.销户\t3.查询");
	puts("4.存款\t5.取款\t6.转账");
	puts("7.利息管理");
	putchar('\n');
}

void inquire_menu(void)
{
	puts("1.查询账户信息");
	puts("2.查询交易记录");
	putchar('\n');
}

void interest_rate_menu(void)
{
	puts("1.活期:年利率0.05%");
	puts("2.3年定期:年利率1.25%");
	puts("3.5年定期:年利率1.3%");
}

int get_choice(void)
{
	int ch;
	fputs("请输入要执行的操作(q退出):", stdout);
	while ((ch = getchar()) != '\0')
	{
		if ((ch < '1' || ch > '7') && ch != 'q')
		{
			fputs("输入错误!请重新输入:", stdout);
			while (getchar() != '\n');
			continue;
		}
		break;
	}
	while (getchar() != '\n');
	return ch;
}

//验证输入是否正确
Status Put_Verify(char* str, int kind)
{
	size_t len = strlen(str);
	switch (kind)
	{
	case 1://验证卡号输入是否正确
	{
		if (len == 19)//判断长度
		{
			//逐个判断每一位是否为数字
			for (int i = 0; i < len; i++)
				if (str[i] < 48 || str[i]>57)
					return ERROR;
			return OK;
		}
		return ERROR;
		break;
	}
	case 2://验证手机号输入是否正确
	{
		if (len == 11)
		{
			for (int i = 0; i < len; i++)
				if (str[i] < 48 || str[i]>57)
					return ERROR;
			return OK;
		}
		return ERROR;
		break;
	}
	case 3://验证身份证号输入是否正确
	{
		if (len == 18)
		{
			for (int i = 0; i < len; i++)
				if (str[i] < 48 || str[i]>57 && str[i] != 'X')
					return ERROR;
			return OK;
		}
		return ERROR;
		break;
	}
	case 4://验证密码是否输入正确
	{
		if (len == 6)
		{
			for (int i = 0; i < len; i++)
				if (str[i] < 48 || str[i]>57)
					return ERROR;
			return OK;
		}
		return ERROR;
		break;
	}
	default:
		fprintf(stderr, "Put_Verify()参数错误");
		return ERROR;
		break;
	}
}

//校验卡号
void Verify_Card(char* str)
{
	while (1)
	{
		scanf_s("%s", str, MAX_CARD);
		if (Put_Verify(str, 1))
			break;
		puts("卡号应为19位纯数字编码!");
		fputs("请重新输入:", stdout);
	}
}

//校验手机号
void Verify_Phone(char* str)
{
	while (1)
	{
		scanf_s("%s", str, MAX_PHONE);
		if (Put_Verify(str, 2))
			break;
		puts("手机号应为11位纯数字编码!");
		fputs("请重新输入:", stdout);
	}
}

//校验身份证号
void Verify_Id(char* str)
{
	while (1)
	{
		scanf_s("%s", str, MAX_ID);
		if (Put_Verify(str, 3))
			break;
		puts("身份证号应为18位编码,且仅可含有数字和字母X!");
		fputs("请重新输入:", stdout);
	}
}

//校验密码
void Verify_Password(char* str)
{
	while (1)
	{
		scanf_s("%s", str, MAX_PASSWORD);
		if (Put_Verify(str, 4))
			break;
		puts("密码应为6位纯数字编码!");
		fputs("请重新输入:", stdout);
	}
}

void Save_Record(SqList* S, ElemTypeSq* se, const ElemTypeLink* e ,char* str)
{
	time_t current_time;
	time(&current_time);
	ctime_s(se->trading_time, sizeof(se->trading_time), &current_time);
	strncpy_s(se->trader, MAX_NAME, e->name, MAX_NAME);
	se->trader_number = S->length;
	//strncpy_s(se->trading_time, 27, e->start_date, 27);
	strncpy_s(se->trader_type, 20, str, 20);
	ListInsertSq(S, (S->length + 1) % MAXSIZE, *se);
}

Bank.h

cpp 复制代码
#include "LinkList.h"
#include "SqList.h"

#ifndef Status
typedef int Status;
#endif // !Status

#define INTEREST_RATE_CURRENT 0.0005
#define INTEREST_RATE_REGULAR3 0.0125
#define INTEREST_RATE_REGULAR5 0.013

void menu(void);
void inquire_menu(void);
void interest_rate_menu(void);
int get_choice(void);
Status Put_Verify(char* str, int kind);
void Verify_Card(char* str);
void Verify_Phone(char* str);
void Verify_Id(char* str);
void Verify_Password(char* str);
void Save_Record(SqList* S, ElemTypeSq* se, const ElemTypeLink* e,char* str);
相关推荐
Tingjct2 小时前
【C语言实现堆的TOPK问题】——海量数据中怎么找前K大(小)?
数据结构
知识分享小能手2 小时前
SQL Server 2019入门学习教程,从入门到精通,初识 SQL Server 2019 —— 语法知识点与使用方法详解(1)
数据库·学习·sqlserver
代码游侠2 小时前
C语言核心概念复习(三)
开发语言·数据结构·c++·笔记·学习·算法
烧烧的酒0.o2 小时前
Java——JavaSE完整教程
java·开发语言·学习
嗯嗯**2 小时前
Neo4j学习4:数据导入
学习·neo4j·图数据库·csv·数据导入
代码游侠2 小时前
学习笔记——Linux内核与嵌入式开发2
linux·运维·arm开发·嵌入式硬件·学习·架构
我是黄骨鱼2 小时前
【零基础学数据库|第四篇】SQL通用语法学习
学习
Herbert_hwt2 小时前
数据结构与算法绪论:为何学、学什么、如何避坑
c语言·数据结构·算法
lichenyang4532 小时前
Node.js AI 开发入门 - 完整学习笔记
人工智能·学习·node.js
Gain_chance2 小时前
29-学习笔记尚硅谷数仓搭建-DWD层交易域下单事务事实表和交易域支付成功事务事实表
数据仓库·hive·笔记·学习·datagrip