本系统通过建立文件储存数据,从而达到多次操作的效果
最后提醒下初学者:因为这个系统用到的库函数比较多,所以我不可能每一个都要讲清楚它的作用、头文件,所以就需要你们动动勤快的小手去百度啦!(我是这么过来的,这样真的很有用!
一、设计题目与要求
简单概括需求:
- 取款
- 存款
- 查询余额、操作记录
- 修改密码
- 可以保存每次启动程序的数据
非必须需求:
- 数据加密存储
- 隐藏密码输入
- 美观的界面
二、设计软硬件环境
开发环境为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语言学生成绩管理系统
版权属于:瞳瞳too
本文链接:https://letanml.xyz/study-notes/4.html
本站未注明转载的文章均为原创,并采用
CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!