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;
}
相关推荐
代码游侠5 小时前
应用——Linux进程编程实例分析
linux·运维·网络·笔记·学习·算法
大道之简5 小时前
SpringAI入门学习
学习
在坚持一下我可没意见5 小时前
Spring 开发小白学习过程中常用通用配置文件,即拿即用!(持续更新中)
java·数据库·后端·学习·spring·tomcat·mybatis
m0_689618285 小时前
这款微光学天线让机器人拥有“超灵敏多感官”,重量仅0.1克
网络·笔记·学习
野老杂谈6 小时前
【Solidity学习】合约基本结构与状态变量
学习·区块链
承渊政道7 小时前
C++学习之旅【C++类和对象(下)】
c++·学习·visual studio
旖旎夜光13 小时前
多态(11)(下)
c++·学习
全栈陈序员15 小时前
【Python】基础语法入门(十七)——文件操作与数据持久化:安全读写本地数据
开发语言·人工智能·python·学习
啄缘之间15 小时前
11. UVM Test [uvm_test]
经验分享·笔记·学习·uvm·总结