C语言考勤系统如何实现学生高效管理?

99ANYc3cd6
预计阅读时长 35 分钟
位置: 首页 C语言 正文

C语言课程设计:学生考勤系统

项目概述

本项目旨在设计并实现一个基于命令行的学生考勤管理系统,该系统使用C语言进行开发,通过文件存储学生信息和考勤记录,实现了对学生基本信息的增、删、改、查,以及对考勤记录的录入、查询和统计功能,系统采用模块化设计,结构清晰,易于维护和扩展。

c语言课程设计学生考勤系统
(图片来源网络,侵删)

需求分析

根据课程设计的要求,系统需要具备以下核心功能:

  • 学生信息管理:

    • 添加学生: 输入学号、姓名、班级等信息,将新学生信息存入系统。
    • 删除学生: 根据学号删除指定学生的所有信息。
    • 修改学生信息: 根据学号查找学生,并修改其姓名、班级等基本信息。
    • 查询学生信息: 根据学号或姓名查询并显示学生的详细信息。
    • 显示所有学生: 以列表形式展示系统中所有学生的基本信息。
  • 考勤记录管理:

    • 录入考勤: 为指定学号的学生录入考勤状态(如:正常、迟到、早退、请假、旷课)。
    • 查询考勤记录: 查询指定学号学生的所有考勤记录。
    • 统计考勤: 统计指定学生或班级的出勤率、迟到次数等。
  • 数据持久化:

    c语言课程设计学生考勤系统
    (图片来源网络,侵删)

    所有学生信息和考勤记录都应保存在文件中,确保程序关闭后数据不丢失,系统启动时自动从文件加载数据。

系统设计

1 功能模块设计

系统将划分为以下几个主要功能模块,并通过一个主菜单进行统一调度。

+---------------------+
|      主菜单         |
+---------------------+
|  1. 学生信息管理    |
|  2. 考勤记录管理    |
|  3. 退出系统        |
+---------------------+
  • 学生信息管理模块:

    • addStudent() - 添加学生
    • deleteStudent() - 删除学生
    • modifyStudent() - 修改学生信息
    • queryStudent() - 查询学生
    • displayAllStudents() - 显示所有学生
  • 考勤记录管理模块:

    c语言课程设计学生考勤系统
    (图片来源网络,侵删)
    • recordAttendance() - 录入考勤
    • queryAttendance() - 查询考勤记录
    • statisticsAttendance() - 统计考勤
  • 数据管理模块:

    • saveStudentsToFile() - 将学生信息保存到文件
    • loadStudentsFromFile() - 从文件加载学生信息
    • saveAttendanceToFile() - 将考勤记录保存到文件
    • loadAttendanceFromFile() - 从文件加载考勤记录

2 数据结构设计

为了高效地管理数据,我们采用结构体(struct)来定义学生和考勤记录的类型。

// 学生信息结构体
typedef struct {
    char id[20];        // 学号
    char name[50];      // 姓名
    char className[50]; // 班级
} Student;
// 考勤记录结构体
typedef struct {
    char studentId[20]; // 学号
    char date[20];      // 日期 (格式: YYYY-MM-DD)
    char status[20];    // 考勤状态 (正常, 迟到, 早退, 请假, 旷课)
} Attendance;
// 为了方便管理,我们可以使用数组来存储学生和考勤记录
// 在实际项目中,可能会使用链表或数据库,但对于课程设计,数组足够了。
#define MAX_STUDENTS 100
#define MAX_ATTENDANCE 1000
Student students[MAX_STUDENTS];
Attendance attendances[MAX_ATTENDANCE];
int studentCount = 0;
int attendanceCount = 0;

3 文件存储设计

为了实现数据持久化,我们将数据保存在文本文件中。

  • students.dat: 存储所有学生信息,每行一个学生,字段之间用逗号或制表符分隔。
    • 格式示例: 2025001,张三,计算机1班
  • attendance.dat: 存储所有考勤记录,每行一条记录,字段之间用逗号或制表符分隔。
    • 格式示例: 2025001,2025-10-26,正常

核心代码实现

以下是关键功能的C语言代码实现。

1 主函数与菜单

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ... (结构体定义和全局变量) ...
void displayMainMenu();
void manageStudents();
void manageAttendance();
int main() {
    // 程序启动时,从文件加载数据
    loadStudentsFromFile();
    loadAttendanceFromFile();
    int choice;
    do {
        displayMainMenu();
        printf("请输入您的选择: ");
        scanf("%d", &choice);
        getchar(); // 清除输入缓冲区中的换行符
        switch (choice) {
            case 1:
                manageStudents();
                break;
            case 2:
                manageAttendance();
                break;
            case 3:
                printf("感谢使用,即将退出系统...\n");
                // 退出前保存数据
                saveStudentsToFile();
                saveAttendanceToFile();
                break;
            default:
                printf("无效的选择,请重新输入!\n");
        }
    } while (choice != 3);
    return 0;
}
void displayMainMenu() {
    system("cls || clear"); // 清屏 (Windows: cls, Linux/Mac: clear)
    printf("========== 学生考勤系统 ==========\n");
    printf("      1. 学生信息管理\n");
    printf("      2. 考勤记录管理\n");
    printf("      3. 退出系统\n");
    printf("==================================\n");
}

2 学生信息管理 - 添加学生

void addStudent() {
    if (studentCount >= MAX_STUDENTS) {
        printf("学生数量已达上限,无法添加!\n");
        return;
    }
    Student s;
    printf("请输入学号: ");
    scanf("%s", s.id);
    getchar(); // 清除缓冲区
    // 检查学号是否已存在
    for (int i = 0; i < studentCount; i++) {
        if (strcmp(students[i].id, s.id) == 0) {
            printf("该学号已存在!\n");
            return;
        }
    }
    printf("请输入姓名: ");
    scanf("%s", s.name);
    getchar();
    printf("请输入班级: ");
    scanf("%s", s.className);
    getchar();
    students[studentCount++] = s;
    printf("学生信息添加成功!\n");
}

3 学生信息管理 - 查询学生

void queryStudent() {
    if (studentCount == 0) {
        printf("系统中没有学生信息!\n");
        return;
    }
    int choice;
    printf("按学号查询请按 1,按姓名查询请按 2: ");
    scanf("%d", &choice);
    getchar();
    char keyword[50];
    printf("请输入查询关键词: ");
    scanf("%s", keyword);
    getchar();
    int found = 0;
    printf("\n--- 查询结果 ---\n");
    printf("学号\t\t姓名\t\t班级\n");
    printf("--------------------------------\n");
    for (int i = 0; i < studentCount; i++) {
        if ((choice == 1 && strcmp(students[i].id, keyword) == 0) ||
            (choice == 2 && strcmp(students[i].name, keyword) == 0)) {
            printf("%s\t\t%s\t\t%s\n", students[i].id, students[i].name, students[i].className);
            found = 1;
        }
    }
    if (!found) {
        printf("未找到匹配的学生信息,\n");
    }
    printf("----------------\n");
}

4 考勤记录管理 - 录入考勤

void recordAttendance() {
    if (studentCount == 0) {
        printf("请先添加学生信息!\n");
        return;
    }
    char studentId[20];
    printf("请输入要考勤的学生学号: ");
    scanf("%s", studentId);
    getchar();
    // 检查学号是否存在
    int studentIndex = -1;
    for (int i = 0; i < studentCount; i++) {
        if (strcmp(students[i].id, studentId) == 0) {
            studentIndex = i;
            break;
        }
    }
    if (studentIndex == -1) {
        printf("未找到该学号的学生!\n");
        return;
    }
    Attendance a;
    strcpy(a.studentId, studentId);
    printf("请输入考勤日期 (YYYY-MM-DD): ");
    scanf("%s", a.date);
    getchar();
    printf("请输入考勤状态 (正常/迟到/早退/请假/旷课): ");
    scanf("%s", a.status);
    getchar();
    attendances[attendanceCount++] = a;
    printf("考勤记录录入成功!\n");
}

5 文件操作 - 保存与加载

void saveStudentsToFile() {
    FILE *fp = fopen("students.dat", "w");
    if (fp == NULL) {
        printf("无法打开文件 students.dat 进行写入!\n");
        return;
    }
    for (int i = 0; i < studentCount; i++) {
        fprintf(fp, "%s,%s,%s\n", students[i].id, students[i].name, students[i].className);
    }
    fclose(fp);
}
void loadStudentsFromFile() {
    FILE *fp = fopen("students.dat", "r");
    if (fp == NULL) {
        // 文件不存在是正常情况,说明是第一次运行
        return;
    }
    studentCount = 0;
    while (fscanf(fp, "%[^,],%[^,],%[^\n]\n", students[studentCount].id, students[studentCount].name, students[studentCount].className) == 3) {
        studentCount++;
    }
    fclose(fp);
}

注意:fscanf的格式%[^,]表示读取直到遇到逗号为止的字符。%[^\n]表示读取直到遇到换行符为止的字符。

6 考勤统计功能

void statisticsAttendance() {
    if (attendanceCount == 0) {
        printf("没有考勤记录可以统计!\n");
        return;
    }
    char studentId[20];
    printf("请输入要统计的学生学号: ");
    scanf("%s", studentId);
    getchar();
    int totalDays = 0;
    int normalDays = 0;
    int lateDays = 0;
    int earlyLeaveDays = 0;
    int leaveDays = 0;
    int absentDays = 0;
    for (int i = 0; i < attendanceCount; i++) {
        if (strcmp(attendances[i].studentId, studentId) == 0) {
            totalDays++;
            if (strcmp(attendances[i].status, "正常") == 0) normalDays++;
            else if (strcmp(attendances[i].status, "迟到") == 0) lateDays++;
            else if (strcmp(attendances[i].status, "早退") == 0) earlyLeaveDays++;
            else if (strcmp(attendances[i].status, "请假") == 0) leaveDays++;
            else if (strcmp(attendances[i].status, "旷课") == 0) absentDays++;
        }
    }
    if (totalDays == 0) {
        printf("未找到该学生的考勤记录!\n");
        return;
    }
    printf("\n--- 学生 %s 的考勤统计 ---\n", studentId);
    printf("总考勤天数: %d\n", totalDays);
    printf("正常: %d 天\n", normalDays);
    printf("迟到: %d 天\n", lateDays);
    printf("早退: %d 天\n", earlyLeaveDays);
    printf("请假: %d 天\n", leaveDays);
    printf("旷课: %d 天\n", absentDays);
    float attendanceRate = (float)(totalDays - absentDays) / totalDays * 100;
    printf("出勤率: %.2f%%\n", attendanceRate);
    printf("--------------------------\n");
}

功能演示流程

  1. 启动系统: 运行程序,显示主菜单。
  2. 添加学生: 选择 1 -> 1,输入学号 2025001,姓名 张三,班级 计算机1班,重复添加 2025002, 李四, 计算机1班
  3. 查询学生: 选择 1 -> 4,选择按学号查询,输入 2025001,应能看到张三的信息。
  4. 录入考勤: 选择 2 -> 1,为学号 2025001 录入今天的考勤,状态选择 正常,再为 2025001 录录一条昨天的考勤,状态为 迟到
  5. 统计考勤: 选择 2 -> 3,输入学号 2025001,系统应显示张三的总考勤天数、迟到次数和出勤率。
  6. 退出系统: 选择 3,程序自动将数据保存到 students.datattendance.dat 文件中。
  7. 重新启动: 再次运行程序,数据应被自动加载,所有操作结果依然存在。

项目总结与展望

1 总结

本项目成功实现了一个功能完整的学生考勤系统,满足了课程设计的所有要求,系统通过结构化编程思想,将不同功能模块化,提高了代码的可读性和可维护性,文件I/O操作保证了数据的持久化存储,整个系统界面友好,操作流程清晰。

2 不足与展望

  • 数据结构局限: 当前使用数组存储数据,数据量受限于数组大小,未来可以改用链表动态数组来管理,实现数据的动态增长。
  • 文件格式: 使用文本文件存储,数据安全性不高,且不易进行复杂查询,未来可以升级为使用数据库(如SQLite)来存储数据,以获得更好的性能、安全性和查询能力。
  • 用户界面: 界面为纯命令行,较为简陋,可以引入图形用户界面库(如GTK, Qt)来开发更美观、易用的桌面应用。
  • 功能扩展:
    • 增加批量导入/导出功能(如从Excel/CSV导入)。
    • 增加按班级统计功能。
    • 增加权限管理,区分管理员和学生用户。
    • 增加数据备份与恢复功能。

这个项目不仅巩固了C语言的基础知识(如结构体、数组、文件操作、函数指针等),也锻炼了分析和解决实际问题的能力,是一个非常好的课程设计实践。

-- 展开阅读全文 --
头像
dede如何修改管理员账号?
« 上一篇 03-04
C语言课程设计总结心得,如何高效提炼与实用?
下一篇 » 03-04

相关文章

取消
微信二维码
支付宝二维码

目录[+]