目录

前言

一,需求定义

二,具体框架

1,Manager(管理员).h头文件和BankCard(银行卡).h头文件

(1)Manager.h

(2)BankCard.h

2,文件框架

三,函数封装

1,Manager.cpp

(1) 初始化数组

(2)登录管理员

(3)注册管理员

(4)销毁释放

2,BankCard.cpp

(1)初始化银行卡

(2)初始化该银行卡对应记录

(3)初始化卡内容

(4)登录

(5)记录流水记录

(6)注册

(7)存款

(8)取款

(9)转账

(10)查余额

(11)查开户日期

(12)查流水明细

(13)挂失卡

(14)注销卡

(15)结束时销毁数组

四,函数调用

1,前置工作

2,atm_op.cpp(引用头文件后的所有函数调用)

(1)从文件中读取管理员身份信息

(2)从文件中读取银行卡身份信息

(3)将Manager数据保存到文件中

(4)将BankCard数据保存到文件中

(5)判断是否是管理员

(6)判断是否是用户

(7)银行卡解锁

(8)管理员选项界面

(9)用户选项界面

(10)管理员功能选择实现

(11)用户功能选择实现

(12)打开atm机窗口

3,main主函数

五,心得总结


前言

熟练使用c语言所练习时写的,也是大学时c语言的课设题目,但是当时老师要求用链表写,那一版的要对数据结构里链表有足够的熟练才行。

我这版的是用数组结构体写的(数组的话对于代码本身实现很简单)。

一,需求定义

首先我们需要有一个管理员和用户的不同的操作模块,两者各自有各自的登录和实现功能。

          

其次,我是用EasyX图形库调用窗口并贴以ATM机做背景图片以实现的,用鼠标点击来确认用户或管理员所需要实现的功能模块,图放这了。

二,具体框架

1,Manager(管理员).h头文件和BankCard(银行卡).h头文件

(1)Manager.h

宏定义INITSIZE和GROWSIZE分别是初始化管理员数组初始个数和扩容倍数。

#pragma once
#define INITSIZE 10
#define GROWSIZE 2
typedef struct Manager {int m_id;//管理员账户idint m_passwd;//账号密码
}Manager;
typedef struct Array_Manager {Manager* managers;//管理员int manager_length;//当前数组总容量int manager_size;//记录当前数组中有效数据个数
}Array_Manager;
//初始化数组
void InitManagers(Array_Manager* parr);
//登录管理员
bool LoginManager(Array_Manager* parr, int m_id, int m_passwd);
//注册管理员
bool RegisterManager(Array_Manager* parr, int m_id, int m_passwd);
//银行卡解锁
bool FindCard(Array_Manager* parr, int m_id, int m_passwd);
//销毁释放
void DestoryManagers(Array_Manager* parr);

(2)BankCard.h

宏定义RECORDSIZE:初始化流水记录个数

宏定义INITCARDSIZE:初始化银行卡个数

宏定义GROWCARDSIZE:银行卡扩容倍数

#pragma once
#define RECORDSIZE 100
#define INITCARDSIZE 10
#define GROWCARDSIZE 2
typedef struct User {char name[128];//姓名char idcard[128];//身份证号long long phone;//电话号码
}User;
typedef struct Record {const char* time;//日期const char* type;//业务double money;//金额
}Record;
typedef struct BankCard {int card_id;//卡号int card_passwd;//卡密double money;//余额int islocked;//是否被锁int islost;//是否丢失char create_card_date[20];//开户日期User user;//卡主Record* records;//流水记录int records_size;//记录当前数组中有效数据个数int records_length;//当前数组总容量
}BankCard;
typedef struct Array_BankCard {BankCard* cards;//银行卡int cards_length;//当前数组总容量int cards_size;//记录当前数组中有效数据个数
}Array_BankCard;
//初始化银行卡
void InitCardArray(Array_BankCard* parr);
//初始化该银行卡对应记录
void InitRecords(BankCard* pcard);
//初始化卡内容
void InitCard(BankCard* pcard, int id, int passwd, double money, User* puser);
//登录
int LoginCard(Array_BankCard* parr, int id, int passwd);//返回银行卡存储下标
//注册
bool RegisterCard(Array_BankCard* parr, int id, int passwd, double money, User* puser);
//存款
bool SaveMoney(Array_BankCard* parr, int index, double money);
//取款
bool Withdraw(Array_BankCard* parr, int index, double money);
//转账
bool Transfer(Array_BankCard* parr, int index, int userid, double money);
//查余额
void GetMoney(Array_BankCard* parr, int index);
//查开户日期
char* GetCretCarDate(Array_BankCard* parr, int index);
//查流水明细
void GetWaterMessage(Array_BankCard* parr, int index);
//挂失卡
bool Lost(Array_BankCard* parr, int index);
//注销卡
bool DeleteCard(Array_BankCard* parr, const char* idcard);
//结束销毁数组
void Destroy(Array_BankCard* parr);

2,文件框架

三,函数封装

1,Manager.cpp

(1) 初始化数组

用指针传递管理员数组,malloc扩容。

assert是断言函数,防止未接收到参数。

//初始化数组
void InitManagers(Array_Manager* parr) {assert(parr != nullptr);parr->managers = (Manager*)malloc(INITSIZE * sizeof(Manager));assert(parr->managers != nullptr);//memset(parr->managers, 0, INITSIZE * sizeof(Manager));//初始化堆内存parr->manager_length = INITSIZE;//容量初始化parr->manager_size = 0;//有效个数0
}

(2)登录管理员

//登录管理员
bool LoginManager(Array_Manager* parr, int m_id, int m_passwd) {assert(parr != nullptr);bool flag = false;for (int i = 0; i < parr->manager_size; i++) {if (parr->managers[i].m_id == m_id && parr->managers[i].m_passwd == m_passwd) {flag = true;break;}}return flag;
}

(3)注册管理员

注册时需注意是否需要扩容。

//注册管理员
bool RegisterManager(Array_Manager* parr, int m_id, int m_passwd) {assert(parr != nullptr);if (parr->manager_size == parr->manager_length) {Manager* temp = (Manager*)realloc(parr->managers, GROWSIZE * parr->manager_length * sizeof(Manager));if (temp == nullptr) {return false;}parr->managers = temp;parr->manager_length *= GROWSIZE;}Manager manager = { m_id, m_passwd };parr->managers[parr->manager_size++] = manager;return true;
}

(4)销毁释放

//销毁释放
void DestoryManagers(Array_Manager* parr) {assert(parr != nullptr);free(parr->managers);parr->managers = nullptr;//防止野指针
}

2,BankCard.cpp

(1)初始化银行卡

//初始化银行卡
void InitCardArray(Array_BankCard* parr) {assert(parr != nullptr);parr->cards = (BankCard*)malloc(INITCARDSIZE * sizeof(BankCard));assert(parr->cards != nullptr);parr->cards_length = INITCARDSIZE;//容量初始化parr->cards_size = 0;//有效个数0
}

(2)初始化该银行卡对应记录

//初始化该银行卡对应记录
void InitRecords(BankCard* pcard) {assert(pcard != nullptr);pcard->records = (Record*)malloc(RECORDSIZE * sizeof(Record));assert(pcard->records != nullptr);pcard->records_length = RECORDSIZE;//容量初始化pcard->records_size = 0;//有效个数0
}

(3)初始化卡内容

这里用到time有关函数,这个是用来直接获得当前系统所用时间的,因为要写开户日期是需要直接读取到本地系统时间的。

//初始化卡内容
void InitCard(BankCard* pcard, int id, int passwd, double money, User* puser) {*pcard = { id, passwd, money, false, false };char timestr[20] = { 0 };//2023-2-18 15:00struct tm* p;time_t t;time(&t);//获取当前时间p = localtime(&t);//时间数据换算为年月日格式sprintf(timestr, "%d-%d-%d%d:%d", p->tm_year, p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min);strcpy(pcard->create_card_date, timestr);pcard->user = *puser;InitRecords(pcard);//上述初始化卡
}

(4)登录

登录这里返回银行卡存储下标位置是方便下面进行其他功能时直接操作当前账号卡。

//登录
int LoginCard(Array_BankCard* parr, int id, int passwd) {//返回银行卡存储下标assert(parr != nullptr);int index = -1;for (int i = 0; i < parr->cards_size; i++) {if (parr->cards[i].card_id == id && parr->cards[i].card_passwd == passwd && parr->cards[i].islocked == false && parr->cards[i].islost == false) {index = i;break;}}return index;
}

(5)记录流水记录

//记录流水记录
void InsertRecords(BankCard* pcard, const char* type, double money) {char timestr[20] = { 0 };//2023-2-18 15:00struct tm* p;time_t t;time(&t);//获取当前时间p = localtime(&t);//时间数据换算为年月日格式sprintf(timestr, "%d-%d-%d %d:%d", p->tm_year, p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min);Record record = { timestr, type, money };pcard->records[pcard->records_size++] = record;
}

(6)注册

//注册
bool RegisterCard(Array_BankCard* parr, int id, int passwd, double money, User* puser) {assert(parr != nullptr);for (int i = 0; i < parr->cards_size; i++) {if (strcmp(parr->cards[i].user.idcard, puser->idcard) == 0) {return false;}}BankCard bankcard;InitCard(&bankcard, id, passwd, money, puser);if (parr->cards_size == parr->cards_length) {BankCard* temp = (BankCard*)realloc(parr->cards, GROWCARDSIZE * parr->cards_length * sizeof(BankCard));if (temp == nullptr) {return false;}parr->cards = temp;parr->cards_length *= GROWCARDSIZE;}InsertRecords(&bankcard, "开户", money);//记录流水记录parr->cards[parr->cards_size++] = bankcard;return true;
}

(7)存款

//存款
bool SaveMoney(Array_BankCard* parr, int index, double money) {assert(parr != nullptr);parr->cards[index].money += money;InsertRecords(&parr->cards[index], "存款", money);//记录流水记录return true;
}

(8)取款

//取款
bool Withdraw(Array_BankCard* parr, int index, double money) {assert(parr != nullptr);bool t = parr->cards[index].money < money ? false : true;if (t) {parr->cards[index].money -= money;InsertRecords(&parr->cards[index], "取款", money);//记录流水记录}return t;
}

(9)转账

找不到对方或者是余额不足是不能转出去的哦。

//转账
bool Transfer(Array_BankCard* parr, int index, int userid, double money) {assert(parr != nullptr);bool t = false;int i = 0;for (; i < parr->cards_size; i++) {if (parr->cards[i].card_id == userid) {break;}}if (i != parr->cards_size) {if (parr->cards[index].money > money) {parr->cards[i].money += money;parr->cards[index].money -= money;InsertRecords(&parr->cards[index], "转出", -1 * money);//记录流水记录InsertRecords(&parr->cards[i], "转入", money);//记录流水记录t = true;}}return t;
}

(10)查余额

void GetMoney(Array_BankCard* parr, int index) {assert(parr != nullptr);printf("%lf\n", parr->cards[index].money);
}

(11)查开户日期

//查开户日期
char* GetCretCarDate(Array_BankCard* parr, int index) {assert(parr != nullptr);return &parr->cards[index].create_card_date[0];
}

(12)查流水明细

//查流水明细
void GetWaterMessage(Array_BankCard* parr, int index) {assert(parr != nullptr);for (int i = 0; i < parr->cards[index].records_size; i++) {printf("%s %s, %lf\n", parr->cards[index].records->time, parr->cards[index].records->type, parr->cards[index].records->money);}
}

(13)挂失卡

//挂失卡
bool Lost(Array_BankCard* parr, int index) {assert(parr != nullptr);parr->cards[index].islocked = 1;parr->cards[index].islost = 1;return true;
}

(14)注销卡

这个注销卡我是只给了管理员这个权限的(前后文都有提及)。

//注销卡
bool DeleteCard(Array_BankCard* parr, const char* idcard) {assert(parr != nullptr);int i = 0;for (; i < parr->cards_size; i++) {if (strcmp(parr->cards[i].user.idcard, idcard) == 0) {break;}}free(parr->cards->records);for (; i < parr->cards_size; i++) {parr->cards[i] = parr->cards[i + 1];}parr->cards_size--;return true;
}

(15)结束时销毁数组

//结束销毁数组
void Destroy(Array_BankCard* parr) {assert(parr != nullptr);free(parr->cards->records);free(parr->cards);parr->cards->records = nullptr;//防止野指针parr->cards = nullptr;//防止野指针
}

四,函数调用

1,前置工作

这里为代码方便使用,我是直接将账号信息数据存贮到文件里去了。

所以在这里需要你们在自己桌面上建立两个文本文档,一个用来存贮管理员账号信息,一个用来存贮银行卡账号信息。

2,atm_op.cpp(引用头文件后的所有函数调用)

(1)从文件中读取管理员身份信息

这里直接把你们自己创建的文件的地址跟我的一替换就行。

//从文件中读取管理员身份信息
void ReadMangerFile(Array_Manager* parr) {assert(parr != nullptr);FILE* fp;  //用于文件操作int i = 0;//初始化,用于确定个数//从文件中取出账户信息并存入当前操作系统中/*a+:以附加方式打开可读/写的文件。若文件不存在,则会创建该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)。*/if ((fp = fopen("C:/Users/123/Desktop/ATM机Manger账号信息存根.txt", "a+")) == NULL){printf("数据文件无法打开!\n");//出错预处理exit(0);//exit函数直接结束当前进程}/*fscanf其功能为根据数据格式,从输入流(文件)中读入数据,存储到结构体数组中,遇到空格和换行时结束。*/while (fscanf(fp, "%d %d",  &(parr->managers + i)->m_id, &(parr->managers + i)->m_passwd) != EOF){i++;}parr->manager_size = i; fclose(fp);//关闭文件return;
}

(2)从文件中读取银行卡身份信息

//从文件中读取银行卡身份信息
void ReadBankCardFile(Array_BankCard* parr) {assert(parr != nullptr);FILE* fp;  //用于文件操作int i = 0;//初始化,用于确定个数//从文件中取出账户信息并存入当前操作系统中/*a+:以附加方式打开可读/写的文件。若文件不存在,则会创建该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)。*/if ((fp = fopen("C:/Users/123/Desktop/ATM机BankCard账号存根.txt", "a+")) == NULL){printf("数据文件无法打开!\n");//出错预处理exit(0);//exit函数直接结束当前进程}/*fscanf其功能为根据数据格式,从输入流(文件)中读入数据,存储到结构体数组中,遇到空格和换行时结束。*/while (fscanf(fp, "%d %d %s %d %d %lf %d %d %s %s %lld", &(parr->cards + i)->card_id, &(parr->cards + i)->card_passwd, &(parr->cards + i)->create_card_date, &(parr->cards + i)->islocked, &(parr->cards + i)->islost, &(parr->cards + i)->money, &(parr->cards + i)->records_length, &(parr->cards + i)->records_size, &(parr->cards + i)->user.idcard, &(parr->cards + i)->user.name, &(parr->cards + i)->user.phone) != EOF){InitRecords(parr->cards + i);i++;}parr->cards_size = i;fclose(fp);//关闭文件return;
}

(3)将Manager数据保存到文件中

void WriteMangerFile(Array_Manager* parr) {assert(parr != nullptr);FILE* fp;  //用于文件操作int i = 0;//保存余额/*w:打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。*/if ((fp = fopen("C:/Users/123/Desktop/ATM机Manger账号信息存根.txt", "w")) == NULL){printf("数据文件无法打开!\n");exit(0);//exit函数直接结束当前进程}for (i = 0; i < parr->manager_size; i++) {fprintf(fp, "%d", (parr->managers + i)->m_id);fprintf(fp, " %d\n", (parr->managers+ i)->m_passwd);}fclose(fp);//关闭文件
}

(4)将BankCard数据保存到文件中

void WriteBankCardFile(Array_BankCard* parr) {assert(parr != nullptr);FILE* fp;  //用于文件操作int i = 0;//保存余额/*w:打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。*/if ((fp = fopen("C:/Users/123/Desktop/ATM机BankCard账号存根.txt", "w")) == NULL){printf("数据文件无法打开!\n");exit(0);//exit函数直接结束当前进程}for (i = 0; i < parr->cards_size; i++) {fprintf(fp, "%d", (parr->cards + i)->card_id);fprintf(fp, " %d", (parr->cards + i)->card_passwd);fprintf(fp, " %s", (parr->cards + i)->create_card_date);fprintf(fp, " %d", (parr->cards + i)->islocked);fprintf(fp, " %d", (parr->cards + i)->islost);fprintf(fp, " %lf", (parr->cards + i)->money);fprintf(fp, " %d", (parr->cards + i)->records_length);fprintf(fp, " %d", (parr->cards + i)->records_size);fprintf(fp, " %s", (parr->cards + i)->user.idcard);fprintf(fp, " %s", (parr->cards + i)->user.name);fprintf(fp, " %lld\n", (parr->cards + i)->user.phone);}fclose(fp);//关闭文件
}

(5)判断是否是管理员

EasyX图形库里面,InputBox这个函数就是弹出一个输入框让你输入,这个是自动识别为字符数组类型的,我这里是用atoi函数强转成的int整型。

MessageBoxA函数就是给一个选项框,MB_OK就是只有一个“确定”选项。

//判断是否是管理员
void IsManger(Array_Manager* parr) {assert(parr != nullptr);//弹出输入账号窗口界面while (true) {char buff[128] = { 0 };InputBox(buff, 128, "账号");int value1 = atoi(buff);char buff2[128] = { 0 };InputBox(buff2, 128, "密码");int value2 = atoi(buff2);bool a = LoginManager(parr, value1, value2);if (a)break;else {MessageBoxA(NULL, "账号密码有误!是否重输?", "账号密码不正确", MB_OK);//a作为返回值进行确定下一界面的调用}}
}

(6)判断是否是用户

//判断是否是用户
int IsUser(Array_BankCard* parr) {assert(parr != nullptr);//弹出输入账号窗口界面while (true) {char buff[128] = { 0 };InputBox(buff, 128, "账号");int value1 = atoi(buff);char buff2[128] = { 0 };InputBox(buff2, 128, "密码");int value2 = atoi(buff2);int a = LoginCard(parr, value1, value2);if (a != -1) {return a;}else {MessageBoxA(NULL, "账号密码有误或此卡已丢失上锁!是否重输?", "请确认是否是您的卡", MB_OK);//a作为返回值进行确定下一界面的调用}}
}

(7)银行卡解锁

//银行卡解锁
bool FindCard(Array_BankCard* parr, int m_id, int m_passwd) {assert(parr != nullptr);int index = -1;for (int i = 0; i < parr->cards_size; i++) {if (parr->cards[i].card_id == m_id && parr->cards[i].card_passwd == m_passwd) {index = i;break;}}if (index != -1) {parr->cards[index].islocked = 0;parr->cards[index].islocked = 0;return true;}else return false;
}

(8)管理员选项界面

(我觉得我在这里写的注释应该可以看懂吧?)

//管理员选项界面
int Mangeroption() {//矩形(多用于按钮) rectangle(起点x, 起点y, 终点x, 终点y) 自带边框填充fillrectangle(同上)RECT rect1 = { 110, 210, 165, 230 };fillrectangle(110, 210, 165, 230);RECT rect2 = { 435, 210, 490, 230 };fillrectangle(435, 210, 490, 230);RECT rect3 = { 110, 250, 165, 270 };fillrectangle(110, 250, 165, 270);RECT rect4 = { 435, 250, 490, 270 };fillrectangle(435, 250, 490, 270);RECT rect5 = { 110, 290, 165, 310 };fillrectangle(110, 290, 165, 310);settextcolor(BLACK);//设置文字颜色settextstyle(15, 5, "楷体");//设置文字大小setbkmode(TRANSPARENT);//设置文字透明背景//文字存放在矩形中间drawtext("注册银行卡", &rect1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("注销银行卡", &rect2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("注册管理员", &rect3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("银行卡解锁", &rect4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("退出登录", &rect5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//鼠标事件监听 左键 右键while (true) {MOUSEMSG msg = GetMouseMsg();//鼠标操作if (msg.x >= 110 && msg.x <= 165 && msg.y >= 210 && msg.y <= 230 && msg.uMsg == WM_LBUTTONDOWN) {return 1;}if (msg.x >= 435 && msg.x <= 490 && msg.y >= 210 && msg.y <= 230 && msg.uMsg == WM_LBUTTONDOWN) {return 2;}if (msg.x >= 110 && msg.x <= 165 && msg.y >= 250 && msg.y <= 270 && msg.uMsg == WM_LBUTTONDOWN) {return 3;}if (msg.x >= 435 && msg.x <= 490 && msg.y >= 250 && msg.y <= 270 && msg.uMsg == WM_LBUTTONDOWN) {return 4;}if (msg.x >= 110 && msg.x <= 165 && msg.y >= 290 && msg.y <= 310 && msg.uMsg == WM_LBUTTONDOWN) {return 0;}}
}

(9)用户选项界面

//用户选项界面
int BankCardoption() {RECT rect1 = { 110, 210, 165, 230 };fillrectangle(110, 210, 165, 230);RECT rect2 = { 435, 210, 490, 230 };fillrectangle(435, 210, 490, 230);RECT rect3 = { 110, 250, 165, 270 };fillrectangle(110, 250, 165, 270);RECT rect4 = { 435, 250, 490, 270 };fillrectangle(435, 250, 490, 270);RECT rect5 = { 110, 290, 165, 310 };fillrectangle(110, 290, 165, 310);RECT rect6 = { 435, 290, 490, 310 };fillrectangle(435, 290, 490, 310);RECT rect7 = { 110, 330, 165, 350 };fillrectangle(110, 330, 165, 350);RECT rect8 = { 435, 330, 490, 350 };fillrectangle(435, 330, 490, 350);settextcolor(BLACK);//设置文字颜色settextstyle(15, 5, "楷体");//设置文字大小setbkmode(TRANSPARENT);//设置文字透明背景//文字存放在矩形中间drawtext("存款", &rect1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("取款", &rect2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("转账", &rect3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("查余额", &rect4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("查开户日期", &rect5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("查流水明细", &rect6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("挂失", &rect7, DT_CENTER | DT_VCENTER | DT_SINGLELINE);drawtext("退出", &rect8, DT_CENTER | DT_VCENTER | DT_SINGLELINE);while (true) {MOUSEMSG msg = GetMouseMsg();//鼠标操作if (msg.x >= 110 && msg.x <= 165 && msg.y >= 210 && msg.y <= 230 && msg.uMsg == WM_LBUTTONDOWN) {return 1;}if (msg.x >= 435 && msg.x <= 490 && msg.y >= 210 && msg.y <= 230 && msg.uMsg == WM_LBUTTONDOWN) {return 2;}if (msg.x >= 110 && msg.x <= 165 && msg.y >= 250 && msg.y <= 270 && msg.uMsg == WM_LBUTTONDOWN) {return 3;}if (msg.x >= 435 && msg.x <= 490 && msg.y >= 250 && msg.y <= 270 && msg.uMsg == WM_LBUTTONDOWN) {return 4;}if (msg.x >= 110 && msg.x <= 165 && msg.y >= 290 && msg.y <= 310 && msg.uMsg == WM_LBUTTONDOWN) {return 5;}if (msg.x >= 435 && msg.x <= 490 && msg.y >= 290 && msg.y <= 310 && msg.uMsg == WM_LBUTTONDOWN) {return 6;}if (msg.x >= 110 && msg.x <= 165 && msg.y >= 330 && msg.y <= 350 && msg.uMsg == WM_LBUTTONDOWN) {return 7;}if (msg.x >= 435 && msg.x <= 490 && msg.y >= 330 && msg.y <= 350 && msg.uMsg == WM_LBUTTONDOWN) {return 0;}}
}

(10)管理员功能选择实现

管理员是最高级权限,可以对银行卡进行销户和注册以及挂失的操作。

再提一嘴,MessageBoxA函数这里MB_YESNO就是有一个“是”选项和一个“否”选项。这里要注意是的话会返回6,否的话会返回7。注意是7不是0!!!

//管理员功能选择实现
void ManagerWork(Array_Manager* parr, Array_BankCard* parr2) {assert(parr != nullptr && parr2 != nullptr);IsManger(parr);while (true) {int t = Mangeroption();switch (t) {case 0:break;case 1:{char buff[128] = { 0 };InputBox(buff, 128, "账号");int id = atoi(buff);char buff2[128] = { 0 };InputBox(buff2, 128, "密码");int passwd = atoi(buff2);char buff3[128] = { 0 };InputBox(buff3, 128, "金额");double money = atof(buff3);User user = { NULL, NULL, 0 };InputBox(user.name, 128, "姓名");InputBox(user.idcard, 128, "身份证号");char buff6[128] = { 0 };InputBox(buff6, 128, "电话号码");user.phone = atoll(buff6);bool test = RegisterCard(parr2, id, passwd, money, &user);if (test) {MessageBoxA(NULL, "恭喜你,注册成功!", "注册成功", MB_OK);}else {MessageBoxA(NULL, "很抱歉,您的身份证已存在一张卡!", "注册失败", MB_OK);}break;}case 2:{char buff4[128] = { 0 };InputBox(buff4, 128, "请输入您要注销的账号");bool deletecard = DeleteCard(parr2, buff4);if (deletecard) {MessageBoxA(NULL, "恭喜你,注销成功!", "注销成功", MB_OK);}else {MessageBoxA(NULL, "很抱歉,注销失败,请确认您的卡号是否正确", "注销失败", MB_OK);}break;}case 3:{char buff7[128] = { 0 };InputBox(buff7, 128, "账号");int id2 = atoi(buff7);char buff8[128] = { 0 };InputBox(buff8, 128, "密码");int passwd2 = atoi(buff8);RegisterManager(parr, id2, passwd2);MessageBoxA(NULL, "恭喜你,注册成功!", "注册成功", MB_OK);break;}case 4:{char buff9[128] = { 0 };InputBox(buff9, 128, "账号");int id3 = atoi(buff9);char buff10[128] = { 0 };InputBox(buff10, 128, "密码");int passwd3 = atoi(buff10);bool find = FindCard(parr2, id3, passwd3);if (find) {MessageBoxA(NULL, "恭喜你,解锁成功!", "解锁成功", MB_OK);}else {MessageBoxA(NULL, "请确认您所输入的账号和密码是否正确!", "解锁失败", MB_OK);}break;}}if (t != 0) {int n = MessageBoxA(NULL, "还有别的服务需求吗?", "ATM机管理员询问", MB_YESNO);//a作为返回值进行确定下一界面的调用if (n == 6) {continue;}else break;}else break;}
}

(11)用户功能选择实现

//用户功能选择实现
void BankCardWord(Array_BankCard* parr) {assert(parr != nullptr);int index = IsUser(parr);while (true) {int t = BankCardoption();switch (t) {case 0:break;case 1:{char buff[128] = { 0 };InputBox(buff, 128, "金额");double money = atof(buff);bool save = SaveMoney(parr, index, money);if (save) {MessageBoxA(NULL, "恭喜你,存款成功!", "存款", MB_OK);}else {MessageBoxA(NULL, "很抱歉,存款失败!", "存款失败", MB_OK);}break;}case 2:{char buff2[128] = { 0 };InputBox(buff2, 128, "金额");double money2 = atof(buff2);bool get = Withdraw(parr, index, money2);if (get) {MessageBoxA(NULL, "恭喜你,取款成功!", "取款", MB_OK);}else {MessageBoxA(NULL, "您的余额不足,取款失败!", "取款失败", MB_OK);}break;}case 3:{char buff3[128] = { 0 };InputBox(buff3, 128, "请输入你要转向的账户");int userid = atoi(buff3);char buff4[128] = { 0 };InputBox(buff4, 128, "金额");double money3 = atof(buff4);bool tranfer = Transfer(parr, index, userid, money3);if (tranfer) {MessageBoxA(NULL, "恭喜你,转账成功!", "转账", MB_OK);}else {MessageBoxA(NULL, "您的余额不足或不存在该账户,转账失败!", "转账失败", MB_OK);}break;}case 4:GetMoney(parr, index);break;case 5:{char* create = GetCretCarDate(parr, index);int i = 0;for (; i < 8; i++) {printf("%c", *(create + i));}printf(" ");for (; i < strlen(parr->cards[index].create_card_date); i++) {printf("%c", *(create + i));}printf("\n");break;}case 6:GetWaterMessage(parr, index);break;case 7:{bool lost = Lost(parr, index);if (lost) {MessageBoxA(NULL, "不用担心,已将您挂失的卡成功上锁!", "挂失", MB_OK);}else {MessageBoxA(NULL, "很抱歉,挂失失败!", "挂失失败", MB_OK);}break;}}if (t != 0) {int n = MessageBoxA(NULL, "还有别的服务需求吗?", "ATM机管理员询问", MB_YESNO);//a作为返回值进行确定下一界面的调用if (n == 6) {continue;}else break;}else break;}
}

(12)打开atm机窗口

initgraph函数就是建立一个图形化窗口。

SHOWCONSOLE就是把控制台也展示出来。

image在这里简单理解就是贴了个图,图片就是前面放的那张ATM机的图片,直接下载就好,如果你要用自己的图那么我只能祝你好运了(因为我前面有关选项按钮的设置是根据我自己的图打的点,打点本身其实不难,数学功底够硬就好,主要还是一个点一个点打的太麻烦,懒人直接下载我的图就好)。

//打开atm机窗口
void Put_initgraph(Array_Manager* parr, Array_BankCard* parr2) {assert(parr != nullptr && parr2 != nullptr);//BGM();initgraph(600, 700, SHOWCONSOLE);IMAGE image;loadimage(&image, "F:/微信图片_20230218171935.jpg", 600, 700, true);putimage(0, 0, &image);while (true) {int m = MessageBoxA(NULL, "你是管理员吗?", "ATM识别身份", MB_YESNO);//a作为返回值进行确定下一界面的调用if (m == 6) {ManagerWork(parr, parr2);int next = MessageBoxA(NULL, "是否需要更换身份?选否则运行结束", "登录", MB_YESNO);cleardevice();//清屏loadimage(&image, "F:/微信图片_20230218171935.jpg", 600, 700, true);putimage(0, 0, &image);if (next == 6)continue;elsebreak;}else {int u = MessageBoxA(NULL, "你是用户吗?", "ATM识别身份", MB_YESNO);//a作为返回值进行确定下一界面的调用if (u == 6) {BankCardWord(parr2);int next2 = MessageBoxA(NULL, "是否需要更换身份?选否则运行结束", "登录", MB_YESNO);cleardevice();//清屏loadimage(&image, "F:/微信图片_20230218171935.jpg", 600, 700, true);putimage(0, 0, &image);if (next2 == 6)continue;elsebreak;}else {MessageBoxA(NULL, "你绝对是选错了,没有第三个身份。", "逗我玩呢?", MB_OK);}}}system("pause");//按任意键继续closegraph();//关闭窗口
}

3,main主函数

int main() {Array_Manager managers;InitManagers(&managers);ReadMangerFile(&managers);Array_BankCard bankcards;InitCardArray(&bankcards);ReadBankCardFile(&bankcards);Put_initgraph(&managers, &bankcards);WriteMangerFile(&managers);DestoryManagers(&managers);WriteBankCardFile(&bankcards);Destroy(&bankcards);return 0;
}

五,心得总结

作为c语言的练习代码,其中封装函数和调用函数是必须要掌握的基础知识,相较于我大学时写的简易版的银行账户管理系统,我现在这个版本也只是加上了EasyX库的图形调用。

整体上来说功能模块完成的还算完整,缺点是没有对卡的流水记录进行文件存贮,会导致重新运行时数据的丢失(不过问题不大,只要你学会了文件读写操作,就是多谢一部分代码的事)。

整体代码量比较长,但是为了功能完整性,还是只能写这么多

最后:

(本文仅供学习时参考,如有错误,纯属作者技术不到位,不足之处请多指教,勿喷,谢谢)

c语言实现银行账户管理(超详细)相关推荐

  1. c语言有关字符的操作,C语言字符操作总结大全(超详细).doc

    C语言字符串操作总结大全(超详细) 作者: 本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n ...

  2. SAP银行账户管理(Bank Account Management)

    1. 基本概念 & 系统配置 1.1 BANK(银行): SAP系统中的BANK对应现实中的实体银行,例如"中国工商银行","中国农业银行"等.BANK ...

  3. 【Linux】软件包管理超详细笔记

    往期内容: Linux常用指令合集 Linux文本编辑器 Linux软件包管理 Linux用户管理 Linux权限管理 文章目录 软件包管理简介 软件包分类 两种软件包的比较 源码包 RPM包 RPM ...

  4. 银行账户管理项目(纯java)

    银行管理项目 温馨提示:如果你是java大佬,好了,你可以去干别的事情去了.本项目适合java初学者,对大佬没有什么帮助. 文章目录 银行管理项目 前言 一.项目说明 二.项目展示 1.主菜单 2.用 ...

  5. c语言主范式与编码,超详细!终于搞明白KMP算法

    小伙伴们好久不见,今天将开设"数据结构与算法"专栏,一起梳理一遍硬核课程的重要知识点,那我们开始吧 正文 「字符串匹配」是计算机的基本任务之一,举个栗子,有一个字符串"「 ...

  6. c++ 字符串连接_C语言字符串操作总结大全(超详细)

    本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, ...

  7. Mac上安装R语言运行环境及RStudio [超详细!~]

    前言 我们需要安装:1)R语言环境,2)Rstudio软件(R语言开发工具). 我的安装方法参考了博文mac上安装R和RStudio,感谢作者. 接下来分步骤展示详细方法,并给出一个运行示例~ Ste ...

  8. 南京邮电大学Java软件开发(混合式)实验2:银行账户管理——面向对象

    一. Java 类与对象的基本知识: 1. 类的定义 2. 方法重载 3. 构造方法 4. static 关键字 5. this 关键字 6. 包与import 语句 7. 访问权限 8. 对象的使用 ...

  9. C语言基础入门笔记(超详细笔记,多出进行更新,将近九千字)

    下载VS2013,我们一起学习. #include 包含一个叫stdio.h的文件,文件包含令,预处理指令. stdio.h C语言的标准I/O库,用于读取和写入文件,也用于控制台的输入和输出. ma ...

最新文章

  1. 论文里常出现的可扩展性(Scalability)是什么意思呢?
  2. 谷歌Nexus 3开售时间曝光
  3. python创建一个txt文件-python新建txt文件,并逐行写入数据
  4. 5815. 扣分后的最大得分
  5. PWN-PRACTICE-BUUCTF-7
  6. postman如何测试php接口_基于Postman的API自动化测试
  7. 【IDEA】IDEA git log 点击 没有代码变更
  8. pl/sql操作数据库之触发器的使用
  9. (1)鼠标单独移动两个actor
  10. 2022年电工杯A题高比例风电电力系统储能运行及配置分析参考代码
  11. html5数学公式编辑器,数学公式编辑器的使用技巧
  12. C++面向对象课程设计实例-图书馆借阅系统
  13. 重启iis的命令是什么?三种简单的重启方式
  14. Linux 基础之基础网络ss命令
  15. Python实现线性函数的拟合算法
  16. TYPE-C接口的定义诠释以及功能参数挖掘
  17. 游戏原画,掌握角色设计2个小技巧,你也能画好角色
  18. origin作图中的图中图(将原图中的某个区域放大)
  19. 电脑如何共享代理到wifi
  20. Zend studio 调整优化

热门文章

  1. python短信发送
  2. 输入圆柱体的底面半径和高就可以得到体积及表面积
  3. 张孝祥老师给我们的---该不该从大学退学的讨论
  4. 404页面如何设计?
  5. 计算几何基础知识总结
  6. 【微信小程序】微信小程序使用表单的一些坑和注意事项
  7. 全国首档国货社交综艺《国货潮起来》,有了线下快闪店
  8. 文件包含漏洞实例操作
  9. 实验七 2 古老的语言
  10. 重定向dup和dup2