当前位置: 首页 > news >正文

基于C语言(兼容C++17编译器)的记账系统实现

基于C语言(兼容C++17编译器)的记账系统实现>/h1>

#define _CRT_SECURE_NO_WARNINGS  // 禁用安全警告#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <time.h>
#include <ctype.h>
#include <locale.h>
#include <windows.h>#define MAX_RECORDS 1000
#define FILENAME "C:/Users/33430/Desktop/myAlvin/Cfile/account_data.txt"
#define TEMPFILE "C:/Users/33430/Desktop/myAlvin/Cfile/temp_data.txt"typedef struct {int year, month, day;char type[10];       // "收入" 或 "支出"double amount;char description[100];int id;              // 唯一标识符
} Record;Record records[MAX_RECORDS];
int record_count = 0;
int next_id = 1;// 设置控制台颜色
void setColor(int color) {HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleTextAttribute(hConsole, color);
}// 清屏
void clearScreen() {system("cls");
}// 等待按键
void waitKey() {printf("\n按任意键继续...");_getch();
}// 加载数据
void loadData() {FILE* file = fopen(FILENAME, "r");if (!file) return;while (fscanf(file, "%d %d-%d-%d %9s %lf %99[^\n]",&records[record_count].id,&records[record_count].year,&records[record_count].month,&records[record_count].day,records[record_count].type,&records[record_count].amount,records[record_count].description) == 7) {record_count++;if (records[record_count - 1].id >= next_id)next_id = records[record_count - 1].id + 1;}fclose(file);
}// 保存数据
void saveData() {FILE* file = fopen(FILENAME, "w");if (!file) {printf("无法保存数据!\n");return;}for (int i = 0; i < record_count; i++) {fprintf(file, "%d %04d-%02d-%02d %s %.2lf %s\n",records[i].id,records[i].year,records[i].month,records[i].day,records[i].type,records[i].amount,records[i].description);}fclose(file);
}// 添加记录
void addRecord() {if (record_count >= MAX_RECORDS) {printf("记录已满,无法添加!\n");waitKey();return;}Record new_record;time_t t = time(NULL);struct tm* now = localtime(&t);new_record.year = now->tm_year + 1900;new_record.month = now->tm_mon + 1;new_record.day = now->tm_mday;new_record.id = next_id++;clearScreen();setColor(11);printf("════════════════ 添加新记录 ════════════════\n");setColor(15);printf("日期: %04d-%02d-%02d (自动获取)\n", new_record.year, new_record.month, new_record.day);printf("类型 (1.收入 / 2.支出): ");int choice;if (scanf("%d", &choice) != 1) {  // 添加输入验证printf("输入无效!\n");while (getchar() != '\n'); // 清除输入缓冲区waitKey();return;}strcpy(new_record.type, (choice == 1) ? "收入" : "支出");printf("金额: ");if (scanf("%lf", &new_record.amount) != 1) {  // 添加输入验证printf("金额无效!\n");while (getchar() != '\n'); // 清除输入缓冲区waitKey();return;}getchar(); // 消耗换行符printf("描述: ");fgets(new_record.description, 100, stdin);new_record.description[strcspn(new_record.description, "\n")] = '\0'; // 移除换行符records[record_count++] = new_record;saveData();setColor(10);printf("\n记录添加成功!\n");setColor(15);waitKey();
}// 显示记录
void displayRecord(int index) {printf("│ %-4d │ %04d-%02d-%02d │ %-6s │ %-10.2lf │ %-30s │\n",records[index].id,records[index].year,records[index].month,records[index].day,records[index].type,records[index].amount,records[index].description);
}// 查看所有记录
void viewAllRecords() {clearScreen();setColor(14);printf("════════════════════════════ 所有记录 ════════════════════════════\n");setColor(15);if (record_count == 0) {printf("没有记录!\n");waitKey();return;}printf("┌──────┬────────────┬────────┬────────────┬────────────────────────────────┐\n");printf("│ ID   │ 日期       │ 类型   │ 金额       │ 描述                          │\n");printf("├──────┼────────────┼────────┼────────────┼────────────────────────────────┤\n");for (int i = 0; i < record_count; i++) {displayRecord(i);}printf("└──────┴────────────┴────────┴────────────┴────────────────────────────────┘\n");waitKey();
}// 修改记录
void modifyRecord() {viewAllRecords();if (record_count == 0) return;printf("\n输入要修改的记录ID: ");int id;if (scanf("%d", &id) != 1) {  // 添加输入验证printf("ID无效!\n");while (getchar() != '\n'); // 清除输入缓冲区waitKey();return;}int found = -1;for (int i = 0; i < record_count; i++) {if (records[i].id == id) {found = i;break;}}if (found == -1) {printf("未找到该记录!\n");waitKey();return;}clearScreen();setColor(11);printf("════════════════ 修改记录 (ID: %d) ════════════════\n", id);setColor(15);printf("当前日期: %04d-%02d-%02d\n", records[found].year, records[found].month, records[found].day);printf("修改日期? (y/n): ");char choice = _getche();printf("\n");if (choice == 'y' || choice == 'Y') {printf("输入新日期 (YYYY-MM-DD): ");if (scanf("%d-%d-%d", &records[found].year, &records[found].month, &records[found].day) != 3) {printf("日期格式无效!\n");while (getchar() != '\n'); // 清除输入缓冲区waitKey();return;}}printf("\n当前类型: %s\n", records[found].type);printf("修改类型? (y/n): ");choice = _getche();printf("\n");if (choice == 'y' || choice == 'Y') {printf("类型 (1.收入 / 2.支出): ");int type_choice;if (scanf("%d", &type_choice) != 1) {printf("输入无效!\n");while (getchar() != '\n'); // 清除输入缓冲区waitKey();return;}strcpy(records[found].type, (type_choice == 1) ? "收入" : "支出");}printf("\n当前金额: %.2lf\n", records[found].amount);printf("修改金额? (y/n): ");choice = _getche();printf("\n");if (choice == 'y' || choice == 'Y') {printf("输入新金额: ");if (scanf("%lf", &records[found].amount) != 1) {printf("金额无效!\n");while (getchar() != '\n'); // 清除输入缓冲区waitKey();return;}}getchar(); // 消耗换行符printf("\n当前描述: %s\n", records[found].description);printf("修改描述? (y/n): ");choice = _getche();printf("\n");if (choice == 'y' || choice == 'Y') {printf("输入新描述: ");fgets(records[found].description, 100, stdin);records[found].description[strcspn(records[found].description, "\n")] = '\0';}saveData();setColor(10);printf("\n记录修改成功!\n");setColor(15);waitKey();
}// 汇总统计
void summary() {clearScreen();setColor(14);printf("════════════════════════ 汇总统计 ════════════════════════\n");setColor(15);if (record_count == 0) {printf("没有记录可汇总!\n");waitKey();return;}double total_income = 0, total_expense = 0;double monthly_income[13] = { 0 }; // 索引1-12对应月份double yearly_income[3000] = { 0 }; // 年份索引for (int i = 0; i < record_count; i++) {if (strcmp(records[i].type, "收入") == 0) {total_income += records[i].amount;monthly_income[records[i].month] += records[i].amount;yearly_income[records[i].year - 2000] += records[i].amount;}else {total_expense += records[i].amount;monthly_income[records[i].month] -= records[i].amount;yearly_income[records[i].year - 2000] -= records[i].amount;}}printf("\n总收入: %.2lf\n", total_income);printf("总支出: %.2lf\n", total_expense);printf("净收益: %.2lf\n\n", total_income - total_expense);// 月度汇总setColor(11);printf("────────────── 月度汇总 ──────────────\n");setColor(15);for (int m = 1; m <= 12; m++) {if (monthly_income[m] != 0) {printf("月份 %02d: %+.2lf\n", m, monthly_income[m]);}}// 年度汇总setColor(11);printf("\n────────────── 年度汇总 ──────────────\n");setColor(15);for (int y = 0; y < 3000; y++) {if (yearly_income[y] != 0) {printf("年份 %d: %+.2lf\n", y + 2000, yearly_income[y]);}}waitKey();
}// 主菜单
int mainMenu() {clearScreen();setColor(14);printf("════════════════════════ 记账管理系统 ════════════════════════\n");setColor(11);printf("┌───────────────────────────────────────────────────────────────┐\n");printf("│                                                               │\n");printf("│                  请使用 ↑ ↓ 键选择操作                     │\n");printf("│                                                               │\n");printf("├───────────────────────────────────────────────────────────────┤\n");setColor(15);setColor(11);printf("└───────────────────────────────────────────────────────────────┘\n");setColor(14);printf("═══════════════════════════════════════════════════════════════\n");setColor(15);int selection = 1;int key;while (1) {// 高亮当前选项for (int i = 1; i <= 5; i++) {COORD pos = { 2, 7 + i };HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(hConsole, pos);if (i == selection) setColor(224); // 白底红字else setColor(15);printf("%s", (i == 1) ? "1. 添加新记录" :(i == 2) ? "2. 查看所有记录" :(i == 3) ? "3. 修改记录" :(i == 4) ? "4. 汇总统计" : "5. 退出系统");}key = _getch();if (key == 224 || key == 0) { // 方向键key = _getch();if (key == 72 && selection > 1) selection--; // 上if (key == 80 && selection < 5) selection++; // 下}else if (key == 13) { // 回车return selection;}else if (isdigit(key)) { // 数字键int num = key - '0';if (num >= 1 && num <= 5) return num;}}
}int main() {// 设置中文环境setlocale(LC_ALL, "");SetConsoleOutputCP(65001);// 初始化数据loadData();while (1) {int choice = mainMenu();switch (choice) {case 1: addRecord(); break;case 2: viewAllRecords(); break;case 3: modifyRecord(); break;case 4: summary(); break;case 5:clearScreen();setColor(10);printf("感谢使用记账系统,再见!\n");setColor(15);exit(0);}}return 0;
}

在这里插入图片描述

http://www.dtcms.com/a/324895.html

相关文章:

  • 虚拟机安装 爱快ikuai 软路由 浏览器无法访问/拒绝连接
  • 数据库面试题集
  • Effective C++ 条款34:区分接口继承和实现继承
  • 数据结构(17)排序(下)
  • 深度剖析 P vs NP 问题:计算领域的世纪谜题
  • Graham 算法求二维凸包
  • PG靶机 - Resourced
  • 【51单片机按键闪烁流水灯方向】2022-10-26
  • 【LeetCode】102 - 二叉树的层序遍历
  • MVC结构变种——第三章核心视图及控制器的整体逻辑
  • idea中使用maven造成每次都打印日志
  • matlab实现随机森林算法
  • [SUCTF 2019]Pythonginx
  • JS中typeof与instanceof的区别
  • 【精彩回顾·成都】成都 User Group×柴火创客空间:开源硬件驱动 AI 与云的创新实践!
  • JS 注释类型
  • ADK[3]历史对话信息保存机制与构建多轮对话机器人
  • scanpy单细胞转录组python教程(四):单样本数据分析之降维聚类及细胞注释
  • 【Canvas与戳记】黑底金Z字
  • 正确使用SQL Server中的Hint(10)— 常用Hint(2)
  • Spring WebSocket安全认证与权限控制解析
  • 研究揭示 Apple Intelligence 数据处理中可能存在隐私漏洞
  • 【redis初阶】------List 列表类型
  • 通过脚本修改MATLAB的数据字典
  • 【15】OpenCV C++实战篇——fitEllipse椭圆拟合、 Ellipse()画椭圆
  • 【人工智能99问】BERT的原理什么?(23/99)
  • Elasticsearch 保姆级入门篇
  • SpringBoot查询方式全解析
  • 在Mac上搭建本地AI工作流:Dify与DeepSeek的完美结合
  • 数字图像处理2——图像增强