c语言 个人学习计划打卡与番茄钟程序

个人学习计划管理系统计划管理模块

一、计划管理模块

  • 添加新计划
  • 查看所有计划
  • 修改计划状态
  • 删除已完成计划
  • 统计计划完成情况

二、番茄钟模块

  • 启动番茄钟
  • 暂停/继续功能
  • 时间显示
  • 完成统计

三、数据管理模块

  • 数据保存到文件
  • 从文件加载数据
  • 数据备份

四、用户界面模块

  • 主菜单显示
  • 计划列表显示
  • 番茄钟界面
  • 统计信息显示
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;
}
相关推荐
西岸行者3 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意3 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码3 天前
嵌入式学习路线
学习
毛小茛3 天前
计算机系统概论——校验码
学习
babe小鑫3 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms3 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下3 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。3 天前
2026.2.25监控学习
学习
im_AMBER3 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J3 天前
从“Hello World“ 开始 C++
c语言·c++·学习