个人学习计划管理系统计划管理模块
一、计划管理模块
- 添加新计划
- 查看所有计划
- 修改计划状态
- 删除已完成计划
- 统计计划完成情况
二、番茄钟模块
- 启动番茄钟
- 暂停/继续功能
- 时间显示
- 完成统计
三、数据管理模块
- 数据保存到文件
- 从文件加载数据
- 数据备份
四、用户界面模块
- 主菜单显示
- 计划列表显示
- 番茄钟界面
- 统计信息显示
cpp
/*
* 个人学习计划打卡 + 番茄钟 ------ 单文件版
* gcc study_plan.c -o study_plan
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
#include <windows.h>
#define CLEAR "cls"
#else
#include <unistd.h>
#define CLEAR "clear"
#endif
#define MAX_PLAN 100
#define DATA_FILE "plan.dat"
#define WORK_MIN 25
#define REST_MIN 5
typedef struct {
int id;
char name[80];
int total; /* 预计番茄数 */
int done; /* 已完成番茄数 */
int finish; /* 布尔:是否已完成 */
} Plan;
/* ====================== 全局变量 ====================== */
Plan plans[MAX_PLAN];
int plan_cnt = 0;
/* ====================== 工具函数 ====================== */
void pause_key() {
puts("\n按回车键继续...");
getchar();
}
int input_int(const char *tip) {
int x;
printf("%s", tip);
scanf("%d", &x);
getchar(); /* 吃掉回车 */
return x;
}
void save_data() {
FILE *fp = fopen(DATA_FILE, "wb");
if (!fp) { perror("save failed"); return; }
fwrite(&plan_cnt, sizeof(int), 1, fp);
fwrite(plans, sizeof(Plan), plan_cnt, fp);
fclose(fp);
}
void load_data() {
FILE *fp = fopen(DATA_FILE, "rb");
if (!fp) return;
fread(&plan_cnt, sizeof(int), 1, fp);
fread(plans, sizeof(Plan), plan_cnt, fp);
fclose(fp);
}
/* ====================== 计划管理 ====================== */
void list_plan() {
if (plan_cnt == 0) { puts("暂无计划"); return; }
printf("%-4s %-30s %-8s %-8s %-8s\n",
"ID", "计划名称", "预计番茄", "完成番茄", "状态");
for (int i = 0; i < plan_cnt; i++) {
printf("%-4d %-30s %-8d %-8d %-8s\n",
plans[i].id, plans[i].name, plans[i].total,
plans[i].done, plans[i].finish ? "已完成" : "进行中");
}
}
int find_id(int id) {
for (int i = 0; i < plan_cnt; i++)
if (plans[i].id == id) return i;
return -1;
}
void add_plan() {
if (plan_cnt >= MAX_PLAN) { puts("计划已满"); return; }
Plan p = {0};
p.id = plan_cnt ? plans[plan_cnt - 1].id + 1 : 1;
printf("请输入计划名称:");
fgets(p.name, sizeof(p.name), stdin);
p.name[strcspn(p.name, "\n")] = 0;
p.total = input_int("预计完成番茄数:");
p.done = 0;
p.finish = 0;
plans[plan_cnt++] = p;
save_data();
puts("添加成功!");
}
void mod_plan() {
list_plan();
int id = input_int("请输入要修改的计划ID:");
int idx = find_id(id);
if (idx < 0) { puts("ID 不存在"); return; }
printf("原名称:%s\n", plans[idx].name);
printf("新名称(直接回车跳过):");
char buf[80];
fgets(buf, sizeof(buf), stdin);
if (buf[0] != '\n') {
buf[strcspn(buf, "\n")] = 0;
strcpy(plans[idx].name, buf);
}
int t = input_int("新预计番茄数(<=0 跳过):");
if (t > 0) plans[idx].total = t;
save_data();
puts("修改成功!");
}
void del_plan() {
list_plan();
int id = input_int("请输入要删除的计划ID:");
int idx = find_id(id);
if (idx < 0) { puts("ID 不存在"); return; }
for (int i = idx; i < plan_cnt - 1; i++)
plans[i] = plans[i + 1];
plan_cnt--;
save_data();
puts("删除成功!");
}
void stat_plan() {
if (plan_cnt == 0) { puts("暂无计划"); return; }
int total = 0, done = 0;
for (int i = 0; i < plan_cnt; i++) {
total += plans[i].total;
done += plans[i].done;
}
printf("总计:%d 个番茄,已完成:%d 个,完成率:%.1f%%\n",
total, done, total ? 100.0 * done / total : 0.0);
}
/* ====================== 番茄钟 ====================== */
void countdown(int seconds) {
int pause = 0;
while (seconds > 0) {
printf("\r剩余时间:%02d:%02d (p 暂停,q 退出)",
seconds / 60, seconds % 60);
fflush(stdout);
#ifdef _WIN32
Sleep(1000);
if (_kbhit()) {
int c = _getch();
if (c == 'p' || c == 'P') pause = !pause;
if (c == 'q' || c == 'Q') return;
}
#else
sleep(1);
/* Linux 下简单处理:不实时检测按键,直接 Ctrl-C 退出 */
#endif
if (!pause) seconds--;
}
puts("\n时间到!");
}
void pomodoro() {
system(CLEAR);
puts("=== 番茄钟 ===");
list_plan();
int id = input_int("请选择本次专注的计划ID(0 表示无):");
int idx = -1;
if (id > 0) idx = find_id(id);
printf("开始 %d 分钟专注倒计时...\n", WORK_MIN);
countdown(WORK_MIN * 60);
if (idx >= 0) {
plans[idx].done++;
if (plans[idx].done >= plans[idx].total)
plans[idx].finish = 1;
save_data();
printf("已为计划【%s】记录 1 个番茄!\n", plans[idx].name);
}
printf("开始 %d 分钟休息...\n", REST_MIN);
countdown(REST_MIN * 60);
}
/* ====================== 主菜单 ====================== */
void menu() {
system(CLEAR);
puts("========== 个人学习计划打卡 + 番茄钟 ==========");
puts("1. 查看所有计划");
puts("2. 添加新计划");
puts("3. 修改计划");
puts("4. 删除计划");
puts("5. 统计完成情况");
puts("6. 启动番茄钟");
puts("0. 退出");
printf("请选择:");
}
int main() {
load_data();
while (1) {
menu();
int c = input_int("");
switch (c) {
case 1: list_plan(); pause_key(); break;
case 2: add_plan(); pause_key(); break;
case 3: mod_plan(); pause_key(); break;
case 4: del_plan(); pause_key(); break;
case 5: stat_plan(); pause_key(); break;
case 6: pomodoro(); pause_key(); break;
case 0: puts("Bye~"); return 0;
default: puts("输入有误"); pause_key(); break;
}
}
return 0;
}