基于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 }; 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;
}
