当前位置: 首页 > 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.lryc.cn/news/616073.html

相关文章:

  • CompletableFuture实现Excel sheet页导出
  • RabbitMQ面试精讲 Day 19:网络调优与连接池管理
  • GitHub上为什么采用Gradle编译要多于Maven
  • Excel合并同步工具V1.0
  • Pytorch深度学习框架实战教程10:Pytorch模型保存详解和指南
  • Spring Boot集成WebSocket
  • Spring Boot与WebSocket构建物联网实时通信系统
  • Android Intent 解析
  • Leetcode 3644. Maximum K to Sort a Permutation
  • 数学建模——回归分析
  • 香橙派 RK3588 部署 DeepSeek
  • 【2025CVPR-图象分类方向】ProAPO:视觉分类的渐进式自动提示优化
  • 【Linux】通俗易懂讲解-正则表达式
  • WAIC2025逛展分享·AI鉴伪技术洞察“看不见”的伪造痕迹
  • Jetpack系列教程(二):Hilt——让依赖注入像吃蛋糕一样简单
  • JavaWeb(苍穹外卖)--学习笔记17(Apache Echarts)
  • 【鸿蒙/OpenHarmony/NDK】什么是NDK? 为啥要用NDK?
  • 【图像算法 - 11】基于深度学习 YOLO 与 ByteTrack 的目标检测与多目标跟踪系统(系统设计 + 算法实现 + 代码详解 + 扩展调优)
  • 机器学习——DBSCAN 聚类算法 + 标准化
  • Python 实例属性和类属性
  • 安卓录音方法
  • Java 后端性能优化实战:从 SQL 到 JVM 调优
  • 深入解析React Diff 算法
  • Word XML 批注范围克隆处理器
  • React:useEffect 与副作用
  • MyBatis的xml中字符串类型判空与非字符串类型判空处理方式
  • 秋招春招实习百度笔试百度管培生笔试题库百度非技术岗笔试|笔试解析和攻略|题库分享
  • wordpress语言包制作工具
  • python正则表达式里面有特殊符号如何处理
  • 亚麻云之静态资源管家——S3存储服务实战