AI摘要:本文介绍了如何使用C语言开发ATM模拟系统。系统通过建立文件存储数据,实现多次操作的效果。主要功能包括取款、存款、查询余额、操作记录、修改密码以及保存每次启动程序的数据。非必须需求包括数据加密存储、隐藏密码输入和美观的界面。开发环境为C语言环境,开发软件为Clion,Windows11系统,没有用到数据库。

本系统通过建立文件储存数据,从而达到多次操作的效果

最后提醒下初学者:因为这个系统用到的库函数比较多,所以我不可能每一个都要讲清楚它的作用、头文件,所以就需要你们动动勤快的小手去百度啦!(我是这么过来的,这样真的很有用!

一、设计题目与要求

简单概括需求:

  1. 取款
  2. 存款
  3. 查询余额、操作记录
  4. 修改密码
  5. 可以保存每次启动程序的数据

非必须需求:

  1. 数据加密存储
  2. 隐藏密码输入
  3. 美观的界面

二、设计软硬件环境

开发环境为C语言环境,开发软件为Clion,Windows11系统,没有用到数据库。但用建立文件存储

三、功能设计与描述

1.主界面

包括作者信息等信息

void menu1() {
    system("cls");//清屏
    time_t t;
    struct tm *p;
    time(&t);
    p = gmtime(&t);
    printf("\t\t\t\t\033[1m**********************************************\n");
    printf("\t\t\t\t**--------------\033[31m%d年%02d月%02d日\033[0m\033[1m--------------**\n", 1900 + p->tm_year,
           1 + p->tm_mon, p->tm_mday);
    printf("\t\t\t\t****************当前时间%02d时%02d分**************\n", 8 + p->tm_hour, p->tm_min);
    printf("\t\t\t\t**********************************************\n");
    printf("\t\t\t\t**                                          **\n");
    printf("\t\t\t\t**\033[32m               ATM模拟系统                \033[0m\033[1m**\n");
    printf("\t\t\t\t**                                          **\n");
    printf("\t\t\t\t**********************************************\n");
    printf("\t\t\t\t**\033[1;31m     感谢使用本系统,希望您使用愉快!     \033[0m\033[1m**\n");
    printf("\t\t\t\t**********************************************\n");
    printf("\t\t\t\t**    制作者:刘**    学号:22041132**      **\n");
    printf("\t\t\t\t**           班级:计应程序2班              **\n");
    printf("\t\t\t\t**           学院:xxxxxx学院               **\n");
    printf("\t\t\t\t**********************************************\n");
    printf("按下 \033[1;32mEnter\033[0m 键或等待 \033[1;32m倒计时\033[0m \033[1;31m结束\033[0m 可以继续操作\n");
    countdown(60);
}

2.提示信息

包括使用程序的一些注意事项

void menu5() {
    printf("\033[1;31m程序说明:\033[0m\n\n");
    printf("\033[1m本程序会在当前目录下创建\033[32m'balance.txt'、'password.txt'、'recording.txt'\033[0m三个文件,用于存储数据,如果已经存在这三个文件,请做好备份,\n");
    printf("因为本程序可能会\033[1;31m修改\033[0m\033[1m这三个文件的内容(提示:不在使用本程序后请自行删除)\n\n");
    printf("\033[1;31m警告:\n");
    printf("如不接受,请立即关闭此程序!!!\n\n\033[0m");
    printf("按下 \033[1;32mEnter\033[0m 键或等待 \033[1;32m倒计时\033[0m \033[1;31m结束\033[0m 可以继续操作\n");
    countdown(60);
}

3.校验函数

因为需要多次打开文件所以这里将文件是否打开成功单独封装函数

//校验函数
void open_file(FILE *fp) {
    if (fp == NULL) {
        system("cls");
        printf("\033[1;31m警告:\033[0m\n\n");
        printf("\033[1m程序异常,打开文件时出错!!!");
        getchar();
        exit(0);
    }
}

4.密码隐藏输入函数

因为验证密码和修改密码都要用所以单独写一个函数

//隐藏输入密码,用*代替
void hide_password(char *pswd, unsigned maxlen) {
    int index = 0;
    char buff;
    // 当输入的字符不是回车,或者输入的字符数还没有达到最大长度时进入循环
    while ((buff = getch()) != '\r' || index < maxlen - 1) {
        // 检查字符是否为数字,否则如果输入的字符是退格,并且密码中有字符,则删除最后一个字符
        if (isdigit(buff)) {
            // 如果输入的字符数还没有达到最大长度,将字符加入密码中
            if (index < maxlen - 1) {
                pswd[index++] = buff;
                putchar('*'); // 将输入的字符替换成 *
            }
        } else if (buff == '\b' && index != 0) {
            index--;
            printf("\b \b"); // 将光标向前移动一位,并将字符清除
        }
    }
    pswd[index] = '\0'; // 在密码的末尾加上终止符
    printf("\n");
}

5.验证密码函数

//密码验证,正确返回1,错误返回0
int verify_password() {
    char key[7], password[7];
    int sum = 3;
    // 打开文件
    FILE *fp = fopen("password.txt", "r");
    open_file(fp);
    // 读取密码并写入数组
    fscanf(fp, "%s", key);
    fclose(fp);
    printf("请输入密码(初始密码为123456):");
    while (1) {
        hide_password(password, 7);
        countdown(0);
        sum--;
        if (sum > 0) {
            if (strcmp(key, password) == 0) {
                break;
            } else {
                system("cls");
                printf("密码错误,你还有 %d 次机会\n", sum);
                printf("请重新输入密码:");
            }
        } else {
            printf("密码错误3次,请联系银行工作人员取卡");
            return 0;
        }
    }
    system("cls");
    return 1;
}

全部源码

funcition.c

这份文件包含了程序所有功能的实现的函数

#include "main.h"

//校验函数
void open_file(FILE *fp) {
    if (fp == NULL) {
        system("cls");
        printf("\033[1;31m警告:\033[0m\n\n");
        printf("\033[1m程序异常,打开文件时出错!!!");
        getchar();
        exit(0);
    }
}

//暂停时间
void countdown(int pause_time) {
    int sleep_time, actual_time;
    if (pause_time > 0) {
        // 如果提供了参数,使用参数指定的休眠时间
        sleep_time = pause_time;
        while (sleep_time > 0) {
            sleep_time--;
            printf("\r倒计时 %d 秒 ", sleep_time);;
            fflush(stdout);
            if (kbhit()) {
                char input = getchar();
                if (input == '\n') {
                    break;
                }
            }
            Sleep(1000);
        }
    } else {
        // 否则,使用随机数生成一个指定范围内的休眠时间
        srand(time(NULL));
        sleep_time = rand() % (25 - 15 + 1) + 10;
        for (actual_time = 30; actual_time > sleep_time; actual_time--) {
            printf("正在操作,请稍等 %d \r", actual_time);
            fflush(stdout);
            Sleep(1000);
        }
    }
    system("cls");
}

//隐藏输入密码,用*代替
void hide_password(char *pswd, unsigned maxlen) {
    int index = 0;
    char buff;
    // 当输入的字符不是回车,或者输入的字符数还没有达到最大长度时进入循环
    while ((buff = getch()) != '\r' || index < maxlen - 1) {
        // 检查字符是否为数字,否则如果输入的字符是退格,并且密码中有字符,则删除最后一个字符
        if (isdigit(buff)) {
            // 如果输入的字符数还没有达到最大长度,将字符加入密码中
            if (index < maxlen - 1) {
                pswd[index++] = buff;
                putchar('*'); // 将输入的字符替换成 *
            }
        } else if (buff == '\b' && index != 0) {
            index--;
            printf("\b \b"); // 将光标向前移动一位,并将字符清除
        }
    }
    pswd[index] = '\0'; // 在密码的末尾加上终止符
    printf("\n");
}

//密码验证,正确返回1,错误返回0
int verify_password() {
    char key[7], password[7];
    int sum = 3;
    // 打开文件
    FILE *fp = fopen("password.txt", "r");
    open_file(fp);
    // 读取密码并写入数组
    fscanf(fp, "%s", key);
    fclose(fp);
    printf("请输入密码(初始密码为123456):");
    while (1) {
        hide_password(password, 7);
        countdown(0);
        sum--;
        if (sum > 0) {
            if (strcmp(key, password) == 0) {
                break;
            } else {
                system("cls");
                printf("密码错误,你还有 %d 次机会\n", sum);
                printf("请重新输入密码:");
            }
        } else {
            printf("密码错误3次,请联系银行工作人员取卡");
            return 0;
        }
    }
    system("cls");
    return 1;
}

//记录模块
void recording(char *str) {
    FILE *fp = fopen("recording.txt", "a");
    open_file(fp);
    // 获取当前时间
    time_t t = time(NULL);
    struct tm *timeinfo = localtime(&t);
    // 将时间转换为 24 小时制字符串
    char timestr[20];
    strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", timeinfo);
    // 写入时间和字符串
    fprintf(fp, "[%s] %s\n", timestr, str);
    // 关闭文件
    fclose(fp);
}

//查询记录
void print_recording() {
    int choose = 2, balance;
    while (choose == 2) {
        if (access("recording.txt", F_OK) == -1) {
            // 文件不存在
            FILE *fa = fopen("balance.txt", "r");
            open_file(fa);
            fscanf(fa, "%d", &balance);
            printf("您当前余额为 %d 元\n", balance);
            fclose(fa);
            printf("没有操作记录!!!\n");
            goto anew;
        }
        // 打开文件
        FILE *fp = fopen("recording.txt", "r");
        FILE *fa = fopen("balance.txt", "r");
        open_file(fp);
        open_file(fa);
        fscanf(fa, "%d", &balance);
        printf("您当前余额为 %d 元\n", balance);
        fclose(fa);
        // 判断文件是否为空
        fseek(fp, 0, SEEK_END);
        long file_size = ftell(fp);
        rewind(fp);
        if (file_size == 0) {
            printf("没有操作记录!!!\n");
            goto anew;
        } else {
            // 逐行读取文件内容
            char line[1024];
            while (fgets(line, sizeof(line), fp) != NULL) {
                // 输出行内容
                printf("%s", line);
            }
        }
        // 关闭文件
        fclose(fp);
        anew:
        choose = menu3();
    }
}

//修改密码
void change_password() {
    int choose = 2;
    while (choose == 2) {
        // 打开文件
        FILE *fp = fopen("password.txt", "r+");
        open_file(fp);
        char new_password1[7], new_password2[7];
        printf("请输入新密码:");
        while (1) {
            hide_password(new_password1, 7);
            printf("请再次输入新密码:");
            hide_password(new_password2, 7);
            if (strcmp(new_password1, new_password2) == 0) {
                break;
            } else {
                printf("两次输入不一致,请重新输入:");
            }
        }
        // 将文件指针移动到文件开头
        rewind(fp);
        // 写入新密码
        fprintf(fp, "%s", new_password1);
        // 关闭文件
        fclose(fp);
        choose = menu3();
    }
}

//取款
void withdraw() {
    // 从文件中读取余额
    int balance, amount, choose;
    FILE *fp = fopen("balance.txt", "r");
    open_file(fp);
    fscanf(fp, "%d", &balance);
    fclose(fp);
    do {
        printf("请输入取款金额:");
        scanf("%d", &amount);
        while (amount <= 0 || amount % 10 != 0) {
            printf("您的输入不合法,请重新输入:");
            scanf("%d", &amount);
        }
        countdown(0);
        // 判断余额是否足够
        if (balance < amount) {
            printf("余额不足!!!\n");
            goto anew;
        }
        // 执行取款操作
        balance -= amount;
        printf("成功取款 %d 元\n", amount);
        // 写入操作记录
        char str[50];
        sprintf(str, "取款 %d 元", amount);
        recording(str);
        // 将新的余额写入文件
        fp = fopen("balance.txt", "w");
        open_file(fp);
        fprintf(fp, "%d", balance);
        fclose(fp);
        anew:
        choose = menu3();
    } while (choose == 2);
}

// 存款函数
void deposit() {
    // 打开 balance.txt 文件
    FILE *fp = fopen("balance.txt", "r");
    open_file(fp);
    // 从 balance.txt 文件中读取之前的余额
    int balance, amount, choose;
    fscanf(fp, "%d", &balance);
    // 关闭文件
    fclose(fp);
    do {
        printf("请输入存款金额:");
        scanf("%d", &amount);
        countdown(0);
        // 校验输入的余额是否合法
        while (amount < 0 || amount % 10 != 0) {
            // 余额不合法,输出错误信息并要求用户重新输入
            printf("错误:金额无效\n请重新输入存款金额:");
            scanf("%d", &amount);
            countdown(0);
        }
        // 计算新的余额
        balance += amount;
        // 写入操作记录
        char str[50];
        sprintf(str, "存款 %d 元", amount);
        recording(str);
        // 打开 balance.txt 文件(用于写入)
        fp = fopen("balance.txt", "w");
        open_file(fp);
        // 将新的余额写入 balance.txt 文件
        fprintf(fp, "%d", balance);
        // 关闭文件
        choose = menu3();
        fclose(fp);
    } while (choose == 2);
}

main.h

这里面包含了所有引用的头文件以及函数声明

#ifndef C_HOME_MAIN_H
#define C_HOME_MAIN_H

#endif //C_HOME_MAIN_H
//头文件
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include <conio.h>
#include <unistd.h>
#include <string.h>
#include <tchar.h>
#include <math.h>

//函数声明
//暂停时间
void countdown(int pause_time);

//列表函数
void menu1();

void menu2();

int menu3();

void menu4();

void menu5();

//校验函数
void open_file(FILE *fp);

//隐藏输入密码,用*代替
void hide_password(char *pswd, unsigned maxlen);

//密码验证函数
int verify_password();

//修改密码
void change_password();

//记录模块
void recording(char *str);

//查询记录
void print_recording();

//取款
void withdraw();

// 存款函数
void deposit();

int love();

main.c

这里面包含了主函数,以及两个校验函数

#include "main.h"

// 判余额文件是否存在,如果不存在,则创建文件并向里面写入数字 10000
void check_balance_file() {
    // 判断文件是否存在
    FILE *fp = fopen("balance.txt", "r");
    if (fp == NULL) {
        // 如果文件不存在,则创建文件并写入数字 10000
        fp = fopen("balance.txt", "w");
        open_file(fp);
        fprintf(fp, "10000");
        fclose(fp);
        return;
    }
    int balance;
    if (fscanf(fp, "%d", &balance) != 1 || balance < 0) {
        // 如果不包含有效余额,则用默认余额(10000)覆盖它
        fp = freopen("balance.txt", "w", fp);
        open_file(fp);
        fprintf(fp, "%d", 10000);
        fclose(fp);
    }
}

// 判断密码文件是否存在,如果存在,则判断内容是否为 6 位数字的字符串,如果不是,则更改内容为字符串 123456
void check_password_file() {
    // 判断文件是否存在
    FILE *fp = fopen("password.txt", "r");
    if (fp == NULL) {
        // 如果文件不存在,则创建文件并写入字符串 123456
        fp = fopen("password.txt", "w");
        open_file(fp);
        fprintf(fp, "123456");
        fclose(fp);
    } else {
        // 如果文件存在,则读取内容
        char password[1000];
        fscanf(fp, "%s", password);
        fclose(fp);
        // 判断内容是否为 6 位数字的字符串
        if (strlen(password) != 6 || !isdigit(password[0]) || !isdigit(password[1]) || !isdigit(password[2]) ||
            !isdigit(password[3]) || !isdigit(password[4]) || !isdigit(password[5])) {
            // 如果不是,则更改内容为字符串 123456
            fp = fopen("password.txt", "w");
            open_file(fp);
            fprintf(fp, "123456");
            fclose(fp);
        }
    }
}

int main() {
    setbuf(stdout, NULL);
    menu1();
    menu5();
    check_password_file();
    check_balance_file();
    switch (verify_password()) {
        case 1:
            menu2();
            break;
        default:
            getchar();
            return 0;
    }
    love();
    return 0;
}

menu.c

这是一个菜单函数的文件,所有菜单显示全部在里面,还包括程序退出时显示的爱心函数

#include "main.h"

void menu1() {
    system("cls");//清屏
    time_t t;
    struct tm *p;
    time(&t);
    p = gmtime(&t);
    printf("\t\t\t\t\033[1m**********************************************\n");
    printf("\t\t\t\t**--------------\033[31m%d年%02d月%02d日\033[0m\033[1m--------------**\n", 1900 + p->tm_year,
           1 + p->tm_mon, p->tm_mday);
    printf("\t\t\t\t****************当前时间%02d时%02d分**************\n", 8 + p->tm_hour, p->tm_min);
    printf("\t\t\t\t**********************************************\n");
    printf("\t\t\t\t**                                          **\n");
    printf("\t\t\t\t**\033[32m               ATM模拟系统                \033[0m\033[1m**\n");
    printf("\t\t\t\t**                                          **\n");
    printf("\t\t\t\t**********************************************\n");
    printf("\t\t\t\t**\033[1;31m     感谢使用本系统,希望您使用愉快!     \033[0m\033[1m**\n");
    printf("\t\t\t\t**********************************************\n");
    printf("\t\t\t\t**    制作者:刘**    学号:22041132**      **\n");
    printf("\t\t\t\t**           班级:计应程序2班              **\n");
    printf("\t\t\t\t**           学院:xxxxxx学院               **\n");
    printf("\t\t\t\t**********************************************\n");
    printf("按下 \033[1;32mEnter\033[0m 键或等待 \033[1;32m倒计时\033[0m \033[1;31m结束\033[0m 可以继续操作\n");
    countdown(60);
}

void menu2() {
    int choose;
    while (1) {
        menu4();
        choose:
        scanf("%d", &choose);
        countdown(0);
        switch (choose) {
            case 1:
                deposit();
                break;
            case 2:
                withdraw();
                break;
            case 3:
                printf("开发中·······");
                break;
            case 4:
                change_password();
                break;
            case 5:
                print_recording();
                break;
            case 6:
                return;
            default:
                printf("您的输入不合法,请重新输入:");
                goto choose;
        }
    }
}

int menu3() {
    int choose;
    printf("\t\t\t\t★——————————————————————————————————————————————★\n\n");
    printf("\t\t\t\t             | 1. 返回上级 |\n\n");
    printf("\t\t\t\t             | 2. 继续操作 |\n\n");
    printf("\t\t\t\t★——————————————————————————————————————————————★\n");
    printf("请选择:");
    while (1) {
        scanf("%d", &choose);
        countdown(0);
        if (choose == 1 || choose == 2)
            return choose;
        printf("您的输入不合法,请重新输入:");
    }
}

void menu4() {
    printf("\t\t\t\t★——————————————————————————————————————————————★\n\n");
    printf("\t\t\t\t   | 1. 存款       2. 取款       3. 转账     |\n\n");
    printf("\t\t\t\t   | 4. 修改密码   5. 查询记录   6. 退出系统 |\n\n");
    printf("\t\t\t\t★——————————————————————————————————————————————★\n");
    printf("请选择:");
}

void menu5() {
    printf("\033[1;31m程序说明:\033[0m\n\n");
    printf("\033[1m本程序会在当前目录下创建\033[32m'balance.txt'、'password.txt'、'recording.txt'\033[0m三个文件,用于存储数据,如果已经存在这三个文件,请做好备份,\n");
    printf("因为本程序可能会\033[1;31m修改\033[0m\033[1m这三个文件的内容(提示:不在使用本程序后请自行删除)\n\n");
    printf("\033[1;31m警告:\n");
    printf("如不接受,请立即关闭此程序!!!\n\n\033[0m");
    printf("按下 \033[1;32mEnter\033[0m 键或等待 \033[1;32m倒计时\033[0m \033[1;31m结束\033[0m 可以继续操作\n");
    countdown(60);
}

float f(float x, float y, float z) {
    float a = x * x + 9.0f / 4.0f * y * y + z * z - 1;
    return a * a * a - x * x * z * z * z - 9.0f / 80.0f * y * y * z * z * z;
}

float h(float x, float z) {
    for (float y = 1.0f; y >= 0.0f; y -= 0.001f) {
        if (f(x, y, z) <= 0.0f) {
            return y;
        }
    }
    return 0.0f;
}

int love() {
    HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
    _TCHAR buffer[25][80] = { _T(' ') };
    _TCHAR ramp[] = _T(".:-=+*#%@");

    for (float t = 0.0f;; t += 0.1f) {
        int sy = 0;
        float s = sinf(t);
        float a = s * s * s * s * 0.2f;
        for (float z = 1.3f; z > -1.2f; z -= 0.1f) {
            _TCHAR *p = &buffer[sy++][0];
            float tz = z * (1.2f - a);
            for (float x = -1.5f; x < 1.5f; x += 0.05f) {
                float tx = x * (1.2f + a);
                float v = f(tx, 0.0f, tz);
                if (v <= 0.0f) {
                    float y0 = h(tx, tz);
                    float ny = 0.01f;
                    float nx = h(tx + ny, tz) - y0;
                    float nz = h(tx, tz + ny) - y0;
                    float nd = 1.0f / sqrtf(nx * nx + ny * ny + nz * nz);
                    float d = (nx + ny - nz) * nd * 0.5f + 0.5f;
                    *p++ = ramp[(int) (d * 5.0f)];
                }
                else {
                    *p++ = ' ';
                }
            }
        }

        for (sy = 0; sy < 25; sy++) {
            COORD coord = { 0, sy };
            SetConsoleCursorPosition(console_handle, coord);
            WriteConsole(console_handle, buffer[sy], 79, NULL, 0);
        }
        Sleep(33);
    }
}

参考文章

参考文章:
C语言详细学生成绩管理系统_北以晨光的博客-CSDN博客_数据结构学生信息管理系统

C语言隐藏密码实现(隐藏密码的函数我是使用这篇文章里面的)

C语言打印爱心代码(打印爱心的代码我是在这找的)

(C语言实现)班级学生成绩管理系统_xiaoyuer2815的博客-CSDN博客_c语言学生成绩管理系统