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;
}
相关推荐
charlie1145141911 小时前
嵌入式现代C++教程: 构造函数优化:初始化列表 vs 成员赋值
开发语言·c++·笔记·学习·嵌入式·现代c++
IT=>小脑虎2 小时前
C++零基础衔接进阶知识点【详解版】
开发语言·c++·学习
#眼镜&2 小时前
嵌入式学习之路2
学习
码农小韩2 小时前
基于Linux的C++学习——指针
linux·开发语言·c++·学习·算法
微露清风2 小时前
系统性学习C++-第十九讲-unordered_map 和 unordered_set 的使用
开发语言·c++·学习
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs]seq_file
linux·笔记·学习
行业探路者3 小时前
二维码标签是什么?主要有线上生成二维码和文件生成二维码功能吗?
学习·音视频·语音识别·二维码·设备巡检
li星野3 小时前
OpenCV4X学习—核心模块Core
人工智能·opencv·学习
@zulnger3 小时前
python 学习笔记(多线程和多进程)
笔记·python·学习
凉、介4 小时前
SylixOS 中的 Unix Socket
服务器·c语言·笔记·学习·嵌入式·sylixos