【C语言】银行账户管理系统丨源码+解析

系统功能说明

1. 核心功能模块

  • 账户管理​:创建/删除账户,自动生成唯一账号
  • 资金操作​:存款/取款/转账(含余额校验)
  • 账户服务​:余额查询/密码修改/交易记录查询
  • 数据持久化​:文件存储所有账户信息

2. 关键技术实现

3. 数据结构设计

字段类型说明
accountIDchar[20]唯一账户标识
namechar[50]客户姓名
passwordchar[20]加密密码
balancedouble账户余额
transactionschar[100][50]交易记录缓存
transactionCountint交易记录数

4. 安全特性

  1. 密码加密输入​:使用_getch()实现密码星号显示
  2. 余额验证​:取款/转账前检查余额充足性
  3. 交易审计​:记录最近50笔交易
  4. 操作确认​:关键操作前要求二次确认

5. 文件存储机制

  • 二进制存储​:使用fwrite/fread高效读写
  • 数据完整性​:保存账户数和下一个可用ID
  • 自动加载​:程序启动时自动恢复数据

编译运行说明

  1. 开发环境​:Visual Studio 2019 (需安装C++桌面开发组件)
  2. 创建项目​:
    • 新建"控制台应用"项目
    • 将代码粘贴到main.c文件中
  3. 注意事项​:
    • 密码输入时显示星号(*)
    • 数据存储在程序同目录的accounts.dat文件
    • 初始账户ID从10001开始自动递增

扩展建议

  1. 增加利息计算​:实现按日计息功能
  2. 多账户管理​:支持同一客户多个账户
  3. 管理员模式​:添加账户冻结/解冻功能
  4. 数据加密​:使用简单异或加密保护密码
  5. 界面优化​:添加颜色和ASCII艺术字

系统完整实现了银行核心业务流程,通过文件存储保证数据持久化,交易记录功能便于审计,适合作为C语言文件操作和结构体应用的实践案例

源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>  // 密码输入处理
#include <ctype.h>  // 字符处理

#define MAX_ACCOUNTS 100
#define FILENAME "accounts.dat"
#define TRANSACTION_HISTORY_SIZE 50

// 账户结构体
typedef struct {
    char accountID[20];      // 账号
    char name[50];           // 姓名
    char password[20];       // 密码
    double balance;          // 余额
    char transactions[TRANSACTION_HISTORY_SIZE][100]; // 交易记录
    int transactionCount;    // 交易计数
} Account;

Account accounts[MAX_ACCOUNTS];
int accountCount = 0;
int nextAccountID = 10001;   // 初始账号

// 函数声明
void loadAccounts();
void saveAccounts();
void createAccount();
void deleteAccount();
void deposit();
void withdraw();
void transfer();
void checkBalance();
void changePassword();
void viewAccountInfo();
int findAccount(const char* id);
void printHeader();
void clearInputBuffer();

int main() {
    loadAccounts(); // 启动时加载账户数据
    
    while (1) {
        system("cls");
        printHeader();
        printf("\n\t银行账户管理系统\n");
        printf("\t====================\n");
        printf("\t1. 创建账户\n");
        printf("\t2. 存款\n");
        printf("\t3. 取款\n");
        printf("\t4. 转账\n");
        printf("\t5. 查询余额\n");
        printf("\t6. 修改密码\n");
        printf("\t7. 账户信息\n");
        printf("\t8. 删除账户\n");
        printf("\t0. 退出系统\n");
        printf("\t====================\n");
        printf("\t请选择操作: ");
        
        int choice;
        if (scanf("%d", &choice) != 1) {
            clearInputBuffer();
            continue;
        }
        
        switch (choice) {
            case 1: createAccount(); break;
            case 2: deposit(); break;
            case 3: withdraw(); break;
            case 4: transfer(); break;
            case 5: checkBalance(); break;
            case 6: changePassword(); break;
            case 7: viewAccountInfo(); break;
            case 8: deleteAccount(); break;
            case 0: 
                saveAccounts();
                printf("\n\t系统已保存数据,感谢使用!\n");
                exit(0);
            default:
                printf("\n\t无效选择,请重新输入!\n");
        }
        printf("\n\t按任意键继续...");
        _getch();
    }
    return 0;
}

// 加载账户数据
void loadAccounts() {
    FILE* file = fopen(FILENAME, "rb");
    if (file) {
        fread(&nextAccountID, sizeof(int), 1, file);
        fread(&accountCount, sizeof(int), 1, file);
        fread(accounts, sizeof(Account), accountCount, file);
        fclose(file);
    }
}

// 保存账户数据
void saveAccounts() {
    FILE* file = fopen(FILENAME, "wb");
    if (file) {
        fwrite(&nextAccountID, sizeof(int), 1, file);
        fwrite(&accountCount, sizeof(int), 1, file);
        fwrite(accounts, sizeof(Account), accountCount, file);
        fclose(file);
    }
}

// 创建新账户
void createAccount() {
    system("cls");
    printHeader();
    printf("\n\t--- 创建新账户 ---\n");
    
    if (accountCount >= MAX_ACCOUNTS) {
        printf("\n\t账户数量已达上限!\n");
        return;
    }
    
    Account newAcc;
    sprintf(newAcc.accountID, "%d", nextAccountID++);
    newAcc.transactionCount = 0;
    newAcc.balance = 0.0;
    
    printf("\n\t请输入姓名: ");
    scanf("%s", newAcc.name);
    
    // 密码输入(带*号显示)
    printf("\t设置密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            newAcc.password[i++] = ch;
            printf("*");
        }
    }
    newAcc.password[i] = '\0';
    printf("\n");
    
    // 初始存款
    double initDeposit;
    printf("\n\t请输入初始存款金额: ");
    scanf("%lf", &initDeposit);
    
    if (initDeposit < 10.0) {
        printf("\n\t初始存款不能低于10元!\n");
        return;
    }
    
    newAcc.balance = initDeposit;
    
    // 记录初始交易
    char trans[100];
    sprintf(trans, "开户存入: %.2f元", initDeposit);
    strcpy(newAcc.transactions[newAcc.transactionCount++], trans);
    
    accounts[accountCount++] = newAcc;
    printf("\n\t账户创建成功!账号: %s\n", newAcc.accountID);
}

// 存款操作
void deposit() {
    system("cls");
    printHeader();
    printf("\n\t--- 存款操作 ---\n");
    
    char id[20];
    printf("\n\t请输入账号: ");
    scanf("%s", id);
    
    int index = findAccount(id);
    if (index == -1) {
        printf("\n\t账户不存在!\n");
        return;
    }
    
    // 密码验证
    char pwd[20];
    printf("\t请输入密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            pwd[i++] = ch;
            printf("*");
        }
    }
    pwd[i] = '\0';
    
    if (strcmp(accounts[index].password, pwd) != 0) {
        printf("\n\n\t密码错误!\n");
        return;
    }
    
    double amount;
    printf("\n\n\t请输入存款金额: ");
    scanf("%lf", &amount);
    
    if (amount <= 0) {
        printf("\n\t存款金额必须大于0!\n");
        return;
    }
    
    accounts[index].balance += amount;
    
    // 记录交易
    char trans[100];
    sprintf(trans, "存款: %.2f元", amount);
    if (accounts[index].transactionCount < TRANSACTION_HISTORY_SIZE) {
        strcpy(accounts[index].transactions[accounts[index].transactionCount++], trans);
    } else {
        // 循环覆盖旧记录
        for (int i = 0; i < TRANSACTION_HISTORY_SIZE - 1; i++) {
            strcpy(accounts[index].transactions[i], accounts[index].transactions[i + 1]);
        }
        strcpy(accounts[index].transactions[TRANSACTION_HISTORY_SIZE - 1], trans);
    }
    
    printf("\n\t存款成功!当前余额: %.2f元\n", accounts[index].balance);
}

// 取款操作
void withdraw() {
    system("cls");
    printHeader();
    printf("\n\t--- 取款操作 ---\n");
    
    char id[20];
    printf("\n\t请输入账号: ");
    scanf("%s", id);
    
    int index = findAccount(id);
    if (index == -1) {
        printf("\n\t账户不存在!\n");
        return;
    }
    
    // 密码验证
    char pwd[20];
    printf("\t请输入密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            pwd[i++] = ch;
            printf("*");
        }
    }
    pwd[i] = '\0';
    
    if (strcmp(accounts[index].password, pwd) != 0) {
        printf("\n\n\t密码错误!\n");
        return;
    }
    
    double amount;
    printf("\n\n\t请输入取款金额: ");
    scanf("%lf", &amount);
    
    if (amount <= 0) {
        printf("\n\t取款金额必须大于0!\n");
        return;
    }
    
    if (amount > accounts[index].balance) {
        printf("\n\t余额不足!当前余额: %.2f元\n", accounts[index].balance);
        return;
    }
    
    accounts[index].balance -= amount;
    
    // 记录交易
    char trans[100];
    sprintf(trans, "取款: %.2f元", amount);
    if (accounts[index].transactionCount < TRANSACTION_HISTORY_SIZE) {
        strcpy(accounts[index].transactions[accounts[index].transactionCount++], trans);
    } else {
        // 循环覆盖旧记录
        for (int i = 0; i < TRANSACTION_HISTORY_SIZE - 1; i++) {
            strcpy(accounts[index].transactions[i], accounts[index].transactions[i + 1]);
        }
        strcpy(accounts[index].transactions[TRANSACTION_HISTORY_SIZE - 1], trans);
    }
    
    printf("\n\t取款成功!当前余额: %.2f元\n", accounts[index].balance);
}

// 转账操作
void transfer() {
    system("cls");
    printHeader();
    printf("\n\t--- 转账操作 ---\n");
    
    char fromID[20], toID[20];
    printf("\n\t请输入转出账号: ");
    scanf("%s", fromID);
    
    int fromIndex = findAccount(fromID);
    if (fromIndex == -1) {
        printf("\n\t转出账户不存在!\n");
        return;
    }
    
    // 密码验证
    char pwd[20];
    printf("\t请输入密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            pwd[i++] = ch;
            printf("*");
        }
    }
    pwd[i] = '\0';
    
    if (strcmp(accounts[fromIndex].password, pwd) != 0) {
        printf("\n\n\t密码错误!\n");
        return;
    }
    
    printf("\n\n\t请输入转入账号: ");
    scanf("%s", toID);
    
    int toIndex = findAccount(toID);
    if (toIndex == -1) {
        printf("\n\t转入账户不存在!\n");
        return;
    }
    
    if (strcmp(fromID, toID) == 0) {
        printf("\n\t不能转账给自己!\n");
        return;
    }
    
    double amount;
    printf("\n\t请输入转账金额: ");
    scanf("%lf", &amount);
    
    if (amount <= 0) {
        printf("\n\t转账金额必须大于0!\n");
        return;
    }
    
    if (amount > accounts[fromIndex].balance) {
        printf("\n\t余额不足!当前余额: %.2f元\n", accounts[fromIndex].balance);
        return;
    }
    
    // 执行转账
    accounts[fromIndex].balance -= amount;
    accounts[toIndex].balance += amount;
    
    // 记录转出交易
    char fromTrans[100];
    sprintf(fromTrans, "转出到%s: %.2f元", toID, amount);
    if (accounts[fromIndex].transactionCount < TRANSACTION_HISTORY_SIZE) {
        strcpy(accounts[fromIndex].transactions[accounts[fromIndex].transactionCount++], fromTrans);
    } else {
        for (int i = 0; i < TRANSACTION_HISTORY_SIZE - 1; i++) {
            strcpy(accounts[fromIndex].transactions[i], accounts[fromIndex].transactions[i + 1]);
        }
        strcpy(accounts[fromIndex].transactions[TRANSACTION_HISTORY_SIZE - 1], fromTrans);
    }
    
    // 记录转入交易
    char toTrans[100];
    sprintf(toTrans, "从%s转入: %.2f元", fromID, amount);
    if (accounts[toIndex].transactionCount < TRANSACTION_HISTORY_SIZE) {
        strcpy(accounts[toIndex].transactions[accounts[toIndex].transactionCount++], toTrans);
    } else {
        for (int i = 0; i < TRANSACTION_HISTORY_SIZE - 1; i++) {
            strcpy(accounts[toIndex].transactions[i], accounts[toIndex].transactions[i + 1]);
        }
        strcpy(accounts[toIndex].transactions[TRANSACTION_HISTORY_SIZE - 1], toTrans);
    }
    
    printf("\n\t转账成功!当前余额: %.2f元\n", accounts[fromIndex].balance);
}

// 查询余额
void checkBalance() {
    system("cls");
    printHeader();
    printf("\n\t--- 查询余额 ---\n");
    
    char id[20];
    printf("\n\t请输入账号: ");
    scanf("%s", id);
    
    int index = findAccount(id);
    if (index == -1) {
        printf("\n\t账户不存在!\n");
        return;
    }
    
    // 密码验证
    char pwd[20];
    printf("\t请输入密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            pwd[i++] = ch;
            printf("*");
        }
    }
    pwd[i] = '\0';
    
    if (strcmp(accounts[index].password, pwd) != 0) {
        printf("\n\n\t密码错误!\n");
        return;
    }
    
    printf("\n\n\t账户: %s\n", accounts[index].accountID);
    printf("\t姓名: %s\n", accounts[index].name);
    printf("\t当前余额: %.2f元\n", accounts[index].balance);
}

// 修改密码
void changePassword() {
    system("cls");
    printHeader();
    printf("\n\t--- 修改密码 ---\n");
    
    char id[20];
    printf("\n\t请输入账号: ");
    scanf("%s", id);
    
    int index = findAccount(id);
    if (index == -1) {
        printf("\n\t账户不存在!\n");
        return;
    }
    
    // 原密码验证
    char oldPwd[20];
    printf("\t请输入原密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            oldPwd[i++] = ch;
            printf("*");
        }
    }
    oldPwd[i] = '\0';
    
    if (strcmp(accounts[index].password, oldPwd) != 0) {
        printf("\n\n\t原密码错误!\n");
        return;
    }
    
    // 新密码设置
    char newPwd[20];
    printf("\n\n\t请输入新密码: ");
    i = 0;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            newPwd[i++] = ch;
            printf("*");
        }
    }
    newPwd[i] = '\0';
    
    // 确认新密码
    char confirmPwd[20];
    printf("\n\t请确认新密码: ");
    i = 0;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            confirmPwd[i++] = ch;
            printf("*");
        }
    }
    confirmPwd[i] = '\0';
    
    if (strcmp(newPwd, confirmPwd) != 0) {
        printf("\n\n\t两次输入密码不一致!\n");
        return;
    }
    
    strcpy(accounts[index].password, newPwd);
    printf("\n\n\t密码修改成功!\n");
}

// 查看账户信息
void viewAccountInfo() {
    system("cls");
    printHeader();
    printf("\n\t--- 账户信息 ---\n");
    
    char id[20];
    printf("\n\t请输入账号: ");
    scanf("%s", id);
    
    int index = findAccount(id);
    if (index == -1) {
        printf("\n\t账户不存在!\n");
        return;
    }
    
    // 密码验证
    char pwd[20];
    printf("\t请输入密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            pwd[i++] = ch;
            printf("*");
        }
    }
    pwd[i] = '\0';
    
    if (strcmp(accounts[index].password, pwd) != 0) {
        printf("\n\n\t密码错误!\n");
        return;
    }
    
    printf("\n\n\t账户信息:\n");
    printf("\t账号: %s\n", accounts[index].accountID);
    printf("\t姓名: %s\n", accounts[index].name);
    printf("\t余额: %.2f元\n", accounts[index].balance);
    
    if (accounts[index].transactionCount > 0) {
        printf("\n\t最近交易记录:\n");
        int start = accounts[index].transactionCount > 5 ? 
            accounts[index].transactionCount - 5 : 0;
        
        for (int i = start; i < accounts[index].transactionCount; i++) {
            printf("\t%d. %s\n", i + 1, accounts[index].transactions[i]);
        }
    } else {
        printf("\n\t暂无交易记录\n");
    }
}

// 删除账户
void deleteAccount() {
    system("cls");
    printHeader();
    printf("\n\t--- 删除账户 ---\n");
    
    char id[20];
    printf("\n\t请输入要删除的账号: ");
    scanf("%s", id);
    
    int index = findAccount(id);
    if (index == -1) {
        printf("\n\t账户不存在!\n");
        return;
    }
    
    // 密码验证
    char pwd[20];
    printf("\t请输入密码: ");
    int i = 0;
    char ch;
    while ((ch = _getch()) != '\r' && i < 19) {
        if (ch == '\b' && i > 0) {
            printf("\b \b");
            i--;
        } else if (isprint(ch)) {
            pwd[i++] = ch;
            printf("*");
        }
    }
    pwd[i] = '\0';
    
    if (strcmp(accounts[index].password, pwd) != 0) {
        printf("\n\n\t密码错误!\n");
        return;
    }
    
    // 确认删除
    char confirm;
    printf("\n\n\t确定要删除账户 %s 吗?(y/n): ", id);
    scanf(" %c", &confirm);
    
    if (confirm == 'y' || confirm == 'Y') {
        // 移动数组元素
        for (int i = index; i < accountCount - 1; i++) {
            accounts[i] = accounts[i + 1];
        }
        accountCount--;
        printf("\n\t账户删除成功!\n");
    } else {
        printf("\n\t已取消删除操作\n");
    }
}

// 查找账户索引
int findAccount(const char* id) {
    for (int i = 0; i < accountCount; i++) {
        if (strcmp(accounts[i].accountID, id) == 0) {
            return i;
        }
    }
    return -1;
}

// 打印表头
void printHeader() {
    printf("\n================================================");
    printf("\n=            银行账户管理系统 (VS2019)         =");
    printf("\n================================================\n");
}

// 清除输入缓冲区
void clearInputBuffer() {
    while (getchar() != '\n');
}

初学者 很浅的代码 系统说明: 银行前台处理系统包含开户、销户、存取业务。1)、开户功能中银行可以创建新用户,用户名可以重名,但是银行账号必须唯一。银行用户基本信息包括:用户名、账号、密码(初始密码都为000000)、身份证、创建时间、销户时间、销户标记、余额。开户后将开户信息存储到文件”user.dat”中。2)销户处理只需要更改用户销户标记即可。3)账务处理稍微复杂:a)账务处理菜单设计:(账号、姓名、身份证、发生额、存取标记、日期、余额)。b)工作流程:银行工作人员输入账号后,系统根据用户信息自动输出姓名、身份证、银行工作人员输入发生额(正数代表存,负数代表取,取钱时应检查用户是否透支,如透支给于提示。)存取标记根据发生额自动生成(1表示存,-1表示取)、日期(包含年月日时分)自动生成、余额自动更改, 输入完毕后,系统询问是否确定?是(1)否(0)。输入1,系统将此信息存入到文件”bankrecord.dat”中,bankrecord.dat记录发生的流水账信息。同时将用户信息中的余额进行更改。系统继续提问:是否继续记账?(1:继续0:退出记账系统) 银行客户自助系统包含:首先用户根据账号与初始密码进入自助系统。可以选择1)更改密码(密码应进行加密后,存储到“user.dat“文件中。2)查询余额。3)浏览对账单。浏览对账单稍显复杂:用户输入起始日期,和结束日期。系统在”bankrecord.dat”文件中进行查询,将符合条件的记录显示出来。显示项为:发生额、日期、余额。 功能扩展:银行主管子系统,用于管理普通工作人员的基本信息、银行存款总额、银行流水的发生等内容。自己扩展思路。客户查询功能可以扩展:只查取款业务、存款业务、某一天业务等。银行前台业务可以自己对账。
开始做本项目时对Struts架构理解的并不是很深刻,导致项目有些模块 互相耦合的比较紧密,不利于以后扩展和改进。 1.SearchGene写的比较乱,程序可读性以及可维护性都不好,下一步拟通过接口编程来实现 查询字符串的自动生成。 2.BusinessDelegate写成了一个Singleton是否合适,每一个客户请求后都会new 一个业务对象 对其服务,是否有更好的解决办法以提高程序的效率。 3.Struts-config文件的Action设计的有些散乱,下一步改进。 4.业务对象和DAO合在一起了,降低了程序的扩展性和可维护性,下一步会把二者分开以降低各层 之间的耦合。 5.Struts1.2.7 的 Validator验证框架 不稳定,只能显示第一个参数,同时执行多个验证时参数的显示顺序也不对,是程序原因还是 配置不正确,再上网查找。 6.本项目大部分错误都用异常的形式来处理,异常虽可以使程序清晰,但也会消耗大量资源,若某些错误如密码错,余额不足等多次 出现则服务器响应速度必定会很慢,下一步将经常发生的错误使用硬代码来处理,减少资源浪费。 7.持久层操作大多依赖存储过程和触发器程序的部署会比较复杂,而且会使持久层和数据库耦合过紧,不利于维护,下一步准备用Hibernate 架构改进持久层,如有条件则还可用Spring框架来规范业务层,和统一整个项目。(学习Hibernate和Spring大约1个月时间)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C语言小火车

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值