辣鸡数据结构作业:简易银行管理系统

虽然说是三人合作,但其实基本上是我一个人写的

总的来说,这是个体力活,而且还是个没有任何结构性编程的体力活,就当是我象牙塔时代的一个见证吧

本博文面向大一大二水友。


简易银行卡管理系统

(1)开户:创建一个新的账户,接受用户输入的身份证号,以及账户密码,判断用户输入的身份证号是否唯一且账户密码是否符合要求,如验证成功则为该用户生成一个唯一的帐号。

(2)存款:在用户输入正确的帐号和密码的情况下,接受用户输入的存款金额,并对该帐号的存款信息进行更新。

(3)取款:在用户输入正确的帐号和密码的情况下,接受用户输入的取款金额。取款金额不应该大于当前帐号存款金额,当取款金额不大于当前帐号存款金额时,执行取款操作,并对该帐户的存款信息进行更新。

(4)挂失:在用户输入正确的帐号和密码的情况下,接受用户挂失操作。当帐号挂失后,与该帐号相关的操作都将被禁止。

(5)销户:在用户输入正确的帐号和密码的情况下,接受用户销户。当用户销户后,该帐号将被永久删除。

(6)转帐:在用户输入正确的帐号和密码的情况下,接受用户转账操作,转帐金额不应该大于当前帐号存款金额,当转帐金额不大于当前帐号存款金额时,执行转帐操作,并对该帐户的存款信息及转帐的接受账户的存款信息进行更新。

(7)修改账户密码:在用户输入正确的帐号和密码的情况下,接受用户修改密码操作,用户输入的原密码,若用户输入的密码与原密码匹配,则接受用户输入的新密码,若用户两个输入的密码相同,则修改账户密码,并对数据文件进行更新操作。

(8)查看余额:在用户输入正确的帐号和密码的情况下,接受用户查看余额操作,该模块只涉及数据查询,并不涉及数据文件更新操作。

(9)查看用户交易历史:在用户输入正确的帐号和密码的情况下,接受用户查看用户交易历史操作,系统将显示当前账户的最近的存、取款操作记录,该模块只涉及数据查询,并不涉及数据文件更新操作。


帐号的结构体为Node,存在List这个直接取值法构造的哈希表中,交易历史是一个链表,每个帐号里都包含一个表头。销毁帐号时,将该帐号在哈希表中的位置存在链栈中,下次开户时先从链栈中找空闲的节点。数据库是在txt中读写,比较原始(笑)


 上代码

#include "stdafx.h"
#include 
#include 
#include 
#include "iostream"
using namespace std;
typedef struct FreeNode
{
	int freePos;
	FreeNode *next;
};
typedef struct Log
{
	char Msg[10];
	double Money;
	Log *next;
}Log;
typedef struct Node
{
	char ID[20];
	char pwd[7];
	float money;
	bool isGua;
	Log *logHead;
	bool isCancel;
}Node;
typedef struct List
{
	Node list[10000];
	int num = 1;
}List;
bool CheckCode(char code[])
{
	int count = 0;
	for (int i = 0; code[i] != '\0'; i++)
	{
		if (code[i] < 48 || code[i]>57)
			return false;
		count++;
	}
	if (count == 6)
		return true;
	else return false;
}
void CreateLogNode(List &head, int pos, char str[], float money)
{
	Log *tail = head.list[pos].logHead;
	while (tail->next != nullptr)
	{
		tail = tail->next;
	}
	strcpy_s(tail->Msg, str);
	tail->Money = money;

	Log *newTail = (Log*)malloc(sizeof(Log));
	tail->next = newTail;
	newTail->next = nullptr;
}
void ShowWelcomePanel()
{
	cout << endl << "**********************************" << endl;
	cout << "*      欢迎来到银行管理系统      *" << endl;
	cout << "*         1.开       户          *" << endl;
	cout << "*         2.登       陆          *" << endl;
}
void ShowOperationPanel()
{
	cout << endl << "**********************************" << endl;
	cout << "*         欢  迎  登  陆         *" << endl;
	cout << "*         1.存       款          *" << endl;
	cout << "*         2.取       款          *" << endl;
	cout << "*         3.挂       失          *" << endl;
	cout << "*         4.销       户          *" << endl;
	cout << "*         5.转       账          *" << endl;
	cout << "*         6.修 改 密 码          *" << endl;
	cout << "*         7.查 看 余 额          *" << endl;
	cout << "*         8.查看交易历史         *" << endl;
	cout << "*         9.退出                 *" << endl;
}
Node* FindAccount(int account, List &head)
{
	if (account >= 10001)return nullptr;
	Node *p = &(head.list[account]);
	if (p->isGua == 204)
	{
		return nullptr;
	}
	return p;
}
void CreateNode(List &head, char id[], char code[])
{
	strcpy_s(head.list[head.num].ID, id);
	strcpy_s(head.list[head.num].pwd, code);
	head.list[head.num].isGua = false;
	head.list[head.num].money = 0;
	head.list[head.num].isCancel = false;
	head.list[head.num].logHead = (Log*)malloc(sizeof(Log));
	Log* tail = (Log*)malloc(sizeof(Log));
	head.list[head.num].logHead->next = tail;
	tail->next = nullptr;
	cout << "您的帐号为:" << head.num << endl;
	head.num++;
}
bool notDuplicate(char id[20], List &head)   //开户的时候检查身份证有没有重复
{
	for (int i = 0; ipwd) == 0)
	{
		return true;
	}
	else return false;
}
void UpdateCode(Node *node)
{
	char code[7];
	if (node->isGua)
	{
		cout << "该卡号已挂失,无法修改" << endl;
		return;
	}
	while (true)
	{
		cout << "请输入旧密码" << endl; cin >> code;
		if (!strcmp(code, node->pwd))
		{
			cout << "请输入新密码" << endl; 
			cin >> code;

			while (true)
			{
				if (CheckCode(code))
				{
					break;
				}
				else
				{
					cout << "密码不符合要求,请重新输入" << endl;
					cin >> code;
				}
			}

			strcpy_s(node->pwd, code);
			cout << "密码修改成功" << endl;
			return;
		}
		else
		{
			cout << "密码错误" << endl;
		}
	}
}
void ShowMoney(Node* node)
{
	cout << "您的账号余额为:" << node->money << endl;
}
void ShowLog(Node *node)
{
	Log *p = node->logHead;
	for (p = p->next; p->next != nullptr; p = p->next)
	{
		cout << "     " << p->Msg << p->Money << endl;
	}
}
void Save(Node* node, float money, List &head)
{
	node->money += money;
	Log *log = (Log*)malloc(sizeof(Log));
	log->Money = money;
	strcpy_s(log->Msg, "存款:");
	log->next = node->logHead->next;//bug
	node->logHead->next = log;
}
void Take(Node* node, float  money)
{
	if (node->money - money < 0)
	{
		cout << "账户余额不足" << endl;
		return;
	}
	node->money -= money;
	Log *log = (Log*)malloc(sizeof(Log));
	log->Money = money;
	strcpy_s(log->Msg, "取款:");
	log->next = node->logHead->next;
	node->logHead->next = log;
}
void InitDataBase(List &head)
{
	int i = 1;
	string bufferStr;
	char buffer[100];
	ifstream NodesDB("D:\\Nodes.txt");
	if (!NodesDB)
	{
		cout << "数据库不存在!" << endl;
		return;
	}
	while (getline(NodesDB, bufferStr))
	{
#pragma warning( disable : 4996)
		strcpy(buffer, bufferStr.c_str());
		char *bufferSplit = strtok(buffer, "|");
		int pos = 1;
		while (bufferSplit != nullptr)
		{
			if (pos == 1)strcpy(head.list[i].ID, bufferSplit);
			if (pos == 2)strcpy(head.list[i].pwd, bufferSplit);
			if (pos == 3)head.list[i].money = atof(bufferSplit);
			if (pos == 4)head.list[i].isGua = strcmp("0", bufferSplit) == 0 ? false : true;
			if (pos == 5)head.list[i].isCancel = strcmp("0", bufferSplit) == 0 ? false : true;
			bufferSplit = strtok(NULL, "|");
			pos++;
		}
		i++;
		head.num = i;
		//初始化历史记录
		for (i = 1; i < head.num; i++)
		{
			head.list[i].logHead = (Log*)malloc(sizeof(Log));
			Log *tail = (Log*)malloc(sizeof(Log));
			head.list[i].logHead->next = tail;
			tail->next = nullptr;
		}
	}

	ifstream in("D:\\NodesDBLog.txt");
	if (!in)
	{
		cout << "操作历史数据库不存在!";
		return;
	}
	bool isMoney = true;
	float money;
	i = 1;
	while (getline(in, bufferStr))
	{
#pragma warning( disable : 4996)
		strcpy(buffer, bufferStr.c_str());
		if (strcmp(buffer, "***") == 0)
		{
			i++;
			continue;
		}
		char *bufferSplit = strtok(buffer, "|");
		while (bufferSplit != nullptr)
		{
			if (isMoney)
			{
				money = atof(bufferSplit);
				isMoney = false;
				bufferSplit = strtok(NULL, "|");
				continue;
			}
			if (isMoney == false)
			{
				CreateLogNode(head, i, bufferSplit, money);
				isMoney = true;
				bufferSplit = strtok(NULL, "|");
				continue;
			}
		}
	}
}
void OutStreamToDB(List &head)
{
	ofstream outNode("D:\\Nodes.txt");
	for (int i = 1; i < head.num; i++)
	{
		outNode << head.list[i].ID << '|';
		outNode << head.list[i].pwd << '|';
		outNode << head.list[i].money << '|';
		outNode << head.list[i].isGua << '|';
		outNode << head.list[i].isCancel << endl;
	}
	ofstream outLog("D:\\NodesDBLog.txt");
	Log *log;
	for (int i = 1; i < head.num; i++)
	{
		log = head.list[i].logHead->next;
		while (log->next != nullptr)
		{
			outLog << log->Money << '|';
			outLog << log->Msg << endl;
			log = log->next;
		}
		outLog << "***" << endl;
	}
}
void GuaShi(Node* node)
{
	node->isGua = true;
	cout << "账号挂失成功!" << endl;
}
void DeleteNode(FreeNode &freeList, Node &node, int pos)
{
	node.isCancel = true;
	FreeNode *free = (FreeNode*)malloc(sizeof(FreeNode));
	free->freePos = pos;
	free->next = freeList.next;
	freeList.next = free;
	cout << "注销成功!" << endl;
}
bool CheckFree(FreeNode &freeList, List &list, char id[], char code[])
{
	FreeNode *p = freeList.next;
	if (p == nullptr)return false;
	else
	{
		int i = p->freePos;
		FreeNode *de = p;
		freeList.next = p->next;
		free(de);
		strcpy_s(list.list[i].ID, id);
		strcpy_s(list.list[i].pwd, code);
		list.list[i].money = 0;
		list.list[i].isCancel = false;
		list.list[i].isGua = false;
		Log *p = list.list[i].logHead->next;
		Log *q;
		while (p->next != nullptr)
		{
			q = p;
			p = p->next;
			free(q);
		}
		list.list[i].logHead->next = p;
		cout << "您的账号是" << i << endl;
		return true;
	}
}
void Transfer(List &head, Node &me,int mypos)
{
	cout << "请输入对方账号" << endl;
	int it;
	cin >> it;
	while (true)
	{
		if (head.list[it].isCancel || head.list[it].isCancel == 204)
		{
			cout << "该账户不存在!请重新输入" << endl;
			cin >> it;
		}
		else break;
	}

	cout << "请输入金额" << endl;
	float money;
	cin >> money;
	while (true)
	{
		if (money > me.money)
		{
			cout << "金额不足,请重新输入" << endl;
			cin >> money;
		}
		else break;
	}

	me.money -= money;
	head.list[it].money += money;
	char str1[20] = "转给";
	char target1[20];
	itoa(it,target1,10);
	strcat(str1, target1);
	strcat(str1, ":");
	CreateLogNode(head, mypos, str1, money);
	char str2[20] = "收到";
	char target2[20];
	itoa(mypos, target2, 10);
	strcat(str2, target2);
	strcat(str2, ":");
	CreateLogNode(head, it, str2, money);
}
void main()
{
	List head;
	FreeNode *freeHead = (FreeNode *)malloc(sizeof(FreeNode));
	freeHead->next = nullptr;
	InitDataBase(head);
	int state;
	Node *node = nullptr;
	char id[20], code[7];
	int account;
	while (true)
	{
		node = nullptr;
		ShowWelcomePanel();
		cin >> state;
		switch (state)
		{
		case 1:
			cout << "请输入要创建的身份证号" << endl; cin >> id;
			while (true)
			{
				if (notDuplicate(id, head))break;
				cout << "身份证重复,请重新输入" << endl; cin >> id;
			}
			cout << "请输入要创建的密码(6位数字)" << endl; cin >> code;
			while (true)
			{
				if (CheckCode(code))
				{
					break;
				}
				else
				{
					cout << "密码不符合要求,请重新输入" << endl;
					cin >> code;
				}
			}
			if (CheckFree(*freeHead, head, id, code)) {}
			else CreateNode(head, id, code);
			break;
		case 2:
			cout << "请输入账号" << endl; cin >> account;
			bool loop = true;
			while (loop)
			{
				node = FindAccount(account, head);
				if (node == nullptr)
				{
					cout << "您输入的账号为空,请重新输入" << endl; cin >> account;
					continue;
				}
				while (loop)
				{
					cout << "请输入密码" << endl; cin >> code;
					if (!CodeLogin(node, code))
					{
						cout << "密码错误" << endl; continue;
					}
					loop = false;
				}
			}
			if (node->isCancel)
			{
				cout << "该账号不存在!" << endl;
				break;
			}
			if (node->isGua)
			{
				cout << "该账号已挂失!" << endl;
				break;
			}
			ShowOperationPanel();
			float money;
			bool stop = false;
			while (true)
			{
				cin >> state;
				if (state == 9)
					break;
				switch (state)
				{
				case 1:cout << "请输入存款金额:" << endl;
					cin >> money;
					Save(node, money, head);
					cout << "存款成功!" << endl;
					break;
				case 2:cout << "请输入取款多少" << endl;
					cin >> money;
					Take(node, money);
					cout << "取款成功!" << endl;
					break;
				case 3:GuaShi(node); stop = true;
					break;
				case 4:DeleteNode(*freeHead, *node, account); stop = true;
					break;
				case 5:Transfer(head, *node,account); cout << "转账成功!" << endl;
					break;
				case 6:UpdateCode(node); cout << "更改成功!" << endl;
					break;
				case 7:ShowMoney(node); cout << "显示完毕!" << endl;
					break;
				case 8:ShowLog(node); cout << "显示完毕!" << endl;
					break;
				}
				if (stop)break;
			}
		}
		OutStreamToDB(head);
	}
}

反思

其一:本程序的设计思想是面向过程,完全抛弃了先进的OOPECS的设计思想,子函数杂乱无章,函数之间具有非常高的耦合度,牵一发而动全身,给后期的迭代和重构造成了巨大的困难;其二:交易记录中缺少时间的显示。其三,缺少多线程优化,在处理大量数据信息的时候程序一定会出现响应度很慢的情况,个人认为可以将对数据库的操作封装到一个进程中,或者通过改进哈希函数,通过用户输入的帐号优先从内存中加载这个数据,或者完全抛弃内存,只从数据库中读取一个帐号信息再输出出去。其四,数据库输出的效率低下,每次修改数据保存时,都是将内存中的哈希表中的全部数据全部覆盖地输出到数据库中,做了大量的无用功。其五:自己造的轮子太多,很少用到c++的标准模版库。


(捂脸)

你可能感兴趣的:(数据结构)