C语言之考勤模拟系统平台(千行代码)

本文涉及的产品
数据管理 DMS,安全协同 3个实例 3个月
推荐场景:
学生管理系统数据库
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: C语言之考勤模拟系统平台(千行代码)

 考勤模拟系统平台目录

第一章软件需求分析... 1

第二章系统结构设计... 3

2.1 系统架构... 3

2.2 系统组件... 3

2.3 系统流程... 3

第三章数据结构设计... 4

第四章模块划分及各模块功能介绍... 6

4.1 用户模块(User Module)... 6

4.2 组模块(Group Module)... 6

4.3 打卡模块(Clockin Module)... 6

4.4 数据管理模块(Data Management Module)... 7

4.5 安全模块(Security Module)... 7

4.6 用户界面模块(User Interface Module)... 8

4.7 辅助功能模块(Utility Module)... 9

第五章流程图... 8

第六章调试与运行结果... 13

第七章设计心得... 16

参考文献... 17

第一章软件需求分析

1.1 项目背景

随着信息技术的快速发展,考勤管理作为组织管理的重要组成部分,需要更加高效、准确的系统来支持。传统的手工考勤方式存在效率低下、容易出错等问题。为了解决这些问题,我们提出了一个考勤模拟系统,旨在通过计算机程序实现自动化的考勤管理。

1.2 系统目标

本系统旨在实现以下目标:

  • 提供一个用户友好的界面,方便用户进行日常的考勤操作。
  • 实现用户登录和注册功能,确保考勤数据的安全性。
  • 支持用户打卡操作,记录用户考勤时间。
  • 允许用户创建和管理考勤组,以适应不同组织的需求。
  • 提供考勤数据的查询和统计功能,方便管理人员进行考勤审核。

1.3 功能需求

1.3.1 用户模块

  • 用户注册:允许新用户创建账户。
  • 用户登录:允许用户通过用户名和密码登录系统。
  • 用户信息管理:允许用户查看和修改个人信息。

1.3.2 组模块

  • 组创建:允许用户创建新的组,并设置组名。
  • 组成员管理:允许管理员邀请新成员加入组,设置成员的优先级。
  • 组成员查看:允许用户查看自己所在的所有组。

1.3.3 打卡模块

  • 打卡记录:允许用户在指定时间内打卡。
  • 打卡数据查看:允许用户查看自己的打卡记录。
  • 打卡事件创建:允许有权限的用户发布新的打卡事件。

1.3.4 数据管理

  • 数据持久化:系统需要将用户数据、组数据和打卡数据存储在文件中。
  • 数据读取:系统启动时需要从文件中读取现有数据。

1.4 性能需求

  • 系统应能够处理至少 MAX_USER 个用户,MAX_GROUP 个组,以及 MAX_CLOCKIN 条打卡记录。
  • 系统应保证数据的一致性和完整性。

1.5 安全需求

  • 用户密码应进行加密存储,保证用户信息安全。
  • 系统应提供基本的权限控制,确保数据访问安全。

1.6 系统环境

  • 系统应在常见的操作系统上运行,如 WindowsLinux 等。
  • 系统应使用标准 C 语言编写,确保良好的兼容性。

1.7 数据结构设计

1.7.1 用户(User

  • 用户IDuid):唯一标识符。
  • 密码(password):登录凭证。

1.7.2 打卡记录(Clockin

  • 开始时间(begin_time):打卡开始的具体时间。
  • 结束时间(end_time):打卡结束的具体时间。
  • 用户打卡状态数组(in):记录哪些用户已打卡。
  • 所属组(group_from):打卡记录所属的组。

第二章系统结构设计

2.1 系统架构

系统采用分层架构,主要分为以下几个层次:

  1. 数据访问层:负责数据的存取,与文件系统交互,实现数据的持久化。
  2. 业务逻辑层:处理具体的业务需求,如用户注册、登录、打卡等。
  3. 表示层:提供用户界面,与用户进行交互,接收用户输入并展示处理结果。

2.2 系统组件

  1. 用户管理组件
  • 负责处理用户的注册、登录和信息管理。
  • 与数据访问层的用户数据存储进行交互。
  1. 组管理组件
  • 允许用户创建组、管理组成员和查看组信息。
  • 与数据访问层的组数据存储进行交互。
  1. 打卡管理组件
  • 处理用户的打卡请求,记录打卡时间。
  • 与数据访问层的打卡数据存储进行交互。
  1. 数据持久化组件
  • 负责将用户数据、组数据和打卡数据存储到文件系统。
  • 在系统启动时从文件中恢复数据。
  1. 安全组件
  • 负责密码加密和权限控制,确保数据安全。

2.3 系统流程

  1. 启动流程
  • 系统启动时,数据持久化组件从文件中加载数据到内存。
  1. 用户交互流程
  • 用户通过表示层与系统交互,输入命令或数据。
  • 表示层将用户请求转发至业务逻辑层。
  • 业务逻辑层处理请求,并与数据访问层交互以执行数据操作。
  1. 数据操作流程
  • 数据访问层执行数据的增删改查操作。
  • 操作结果反馈至业务逻辑层,最终呈现给用户。

第三章数据结构设计

3.1 用户数据结构 (user)

用户数据结构用于存储用户的基本信息,包括用户ID和密码。每个用户在系统中都是唯一的。

typedef struct user {
char uid[30]; // 用户ID,用于唯一标识一个用户
char password[30];// 用户密码,用于登录验证
} user;

image.gif

3.2 组数据结构 (group)

组数据结构用于存储关于考勤组的信息,包括组名、成员列表和成员的优先级。

typedef struct group {
char group_name[100]; // 组名,标识一个考勤组
int member[MAX_USER]; // 成员列表,记录属于该组的用户ID
int priority[MAX_USER]; // 成员优先级,通常管理员的优先级较高
} group;

image.gif

3.3 打卡记录数据结构 (clockin)

打卡记录数据结构用于存储关于打卡事件的详细信息,包括打卡的开始和结束时间,以及哪些用户参与了打卡。

typedef struct clockin {
    time_t begin_time;        // 打卡开始时间
    time_t end_time;          // 打卡结束时间
    int in[MAX_USER];         // 用户打卡状态数组,记录哪些用户已打卡
    int group_from;           // 所属组,标识这个打卡记录属于哪个考勤组
} clockin;

image.gif

3.4 系统级全局变量

系统级全局变量用于维护系统的当前状态和数据集合的规模。

user user_set[MAX_USER];             // 用户集合,存储所有用户的信息
int user_set_length = 0;             // 用户集合的当前大小
group group_set[MAX_GROUP];          // 组集合,存储所有考勤组的信息
int group_set_length = 0;            // 组集合的当前大小
clockin clockin_set[MAX_CLOCKIN];    // 打卡记录集合,存储所有打卡记录
int clockin_set_length = 0;          // 打卡记录集合的当前大小
int current_user = -1;               // 当前登录的用户ID
int global_target_group = -1;         // 全局目标组,用于某些操作中的上下文信息

image.gif

3.5 功能函数

系统还提供了一些功能函数来处理数据集合,例如:

  • search_user(user usr): 在用户集合中搜索特定用户。
  • search_uid(char *uid): 通过用户ID搜索用户。
  • read_user_set() write_user_set(): 从文件读取和写入用户数据集合。
  • read_group_set() write_group_set(): 从文件读取和写入组数据集合。
  • read_clockin_set() write_clockin_set(): 从文件读取和写打卡记录集合。

这些函数实现了数据的持久化和基本的增删查改操作。

第四章模块划分及各模块功能介绍

4.1 用户模块(User Module)

用户模块负责处理与用户相关的所有操作,包括用户注册、登录、信息管理等。

4.1.1 用户注册功能

  • 允许新用户创建账户,输入用户名和密码,并存储到用户数据集中。

4.1.2 用户登录功能

  • 允许用户通过输入用户名和密码登录系统,验证用户凭证。

4.1.3 用户信息管理功能

  • 用户可以查看和修改自己的个人信息,如更改密码等。

4.2 组模块(Group Module)

组模块管理用户的分组信息,包括创建组、管理组成员和查看组信息。

4.2.1 组创建功能

  • 允许用户创建新的组,并设置组名,同时成为该组的管理员。

4.2.2 组成员管理功能

  • 允许管理员邀请新成员加入组,设置成员的优先级(管理员或普通成员)。

4.2.3 组成员查看功能

  • 允许用户查看自己所在的所有组及其成员信息。

4.3 打卡模块(Clockin Module)

打卡模块处理用户的日常打卡操作,包括打卡记录、打卡数据查看和打卡事件创建。

4.3.1 打卡记录功能

  • 允许用户在指定时间内进行打卡操作,记录考勤时间。

4.3.2 打卡数据查看功能

  • 允许用户查看自己的打卡记录,包括打卡时间和打卡状态。

4.3.3 打卡事件创建功能

  • 允许有权限的用户(通常是管理员)发布新的打卡事件,设定打卡的起止时间和参与成员。

4.4 数据管理模块(Data Management Module)

数据管理模块负责系统的数据持久化和读取,确保数据的一致性和完整性。

4.4.1 数据持久化功能

  • 系统需要将用户数据、组数据和打卡数据存储在文件中,保证数据不会因程序关闭而丢失。

4.4.2 数据读取功能

  • 系统启动时需要从文件中读取现有数据,恢复系统状态。

4.5 安全模块(Security Module)

安全模块确保系统的安全性,包括密码加密和权限控制。

4.5.1 密码加密功能

  • 用户密码应进行加密存储,保证用户信息安全。

4.5.2 权限控制功能

  • 系统应提供基本的权限控制,确保用户只能访问授权的数据和功能。

4.6 用户界面模块(User Interface Module)

用户界面模块提供与用户的交互界面,接收用户输入并展示处理结果。

4.6.1 命令行界面

  • 系统通过命令行界面与用户交互,提供清晰的指令和反馈。

4.7 辅助功能模块(Utility Module)

辅助功能模块提供一些辅助性的功能,如搜索、数据验证等。

4.7.1 搜索功能

  • 提供搜索用户、组和打卡记录的功能。

4.7.2 数据验证功能

  • 对用户输入进行验证,确保数据的准确性和有效性。

第五章流程图

5.1整体流程图

image.gif 编辑

5.2用户模块部分流程图

image.gif 编辑

5.3打卡模块部分流程图

image.gif 编辑

5.4组模块部分流程图

image.gif 编辑

5.5数据管理模块部分流程图

image.gif 编辑

 

第六章调试与运行结果

6.1显示目前所有打卡

image.gif 编辑

6.2查看组打卡情况

image.gif 编辑

6.3管理员权限目录

image.gif 编辑

6.4正常打卡目录

image.gif 编辑

6.5打卡时间

image.gif 编辑

6.6显示成员在组的打卡情况

image.gif 编辑

6.7显示组的打卡情况

image.gif 编辑

第七章设计心得

在本章中,我将分享在开发考勤模拟系统过程中的心得体会、遇到的挑战、解决方案以及从中学到的经验。

7.1 项目启动阶段

项目启动初期,需求分析是关键步骤。与团队成员进行多轮讨论,确保对考勤模拟系统的需求有深刻理解。需求分析不仅帮助我们明确了系统目标和功能需求,而且为后续的设计和实现奠定了基础。

7.2 系统设计阶段

系统设计阶段是将需求转化为具体实现的桥梁。在这一阶段,我们采用了分层架构,明确了数据访问层、业务逻辑层和表示层的职责。分层架构的好处在于它提高了代码的可维护性和可扩展性。

7.3 数据结构设计

数据结构的设计是系统设计的核心。我们定义了用户(User)、组(Group)和打卡记录(Clockin)三个主要的数据结构,并在全局变量中维护了这些数据集合的状态。在设计数据结构时,我们注重了数据的一致性和完整性,为后续的数据操作打下了基础。

7.4 模块实现

在模块实现阶段,我们面临了如何高效管理用户、组和打卡数据的挑战。通过实现功能函数如search_userread_user_set等,我们确保了数据操作的便利性和准确性。此外,我们还实现了数据持久化,确保了系统的数据不会因为程序的关闭而丢失。

7.5 用户界面设计

用户界面是用户与系统交互的窗口。我们采用了命令行界面,因为它简单且易于实现。在设计用户界面时,我们注重了用户体验,提供了清晰的指令和反馈,使用户能够轻松地进行考勤操作。

7.6 安全性考虑

安全性是系统设计中不可忽视的一部分。我们意识到用户密码的安全性至关重要,因此在设计安全模块时,我们采用了加密存储密码的策略。此外,我们还实现了基本的权限控制,以确保数据访问的安全性。

7.7 测试与调试

在测试与调试阶段,我们发现并解决了多个问题。通过不断的测试,我们优化了系统的性能,确保了系统的稳定性。调试过程中,我们使用了多种调试工具和技术,以确保及时发现并修复问题。

7.8 项目总结

通过开发考勤模拟系统,我们团队学到了很多宝贵的经验。我们认识到了团队协作的重要性,以及在软件开发过程中持续沟通的必要性。此外,我们也意识到了代码的可读性和可维护性对于长期项目成功的重要性。

7.9 未来展望

考勤模拟系统目前虽然已经实现了基本功能,但仍有改进和扩展的空间。未来,我们计划添加更多的功能,如图形用户界面(GUI)、移动设备兼容性以及更高级的安全特性。

参考文献

C++员工考勤管理系统_c++程序设计课公司员工考勤管理系统-CSDN博客

C++员工管理系统(封装+多态+继承+分类化+函数调用+读写文件+指针+升序降序算法等一系列知识结合) - Bytezero! - 博客园 (cnblogs.com)

C++公司员工考勤管理系统[2023-01-01]_c++实现考勤系统-CSDN博客

simuler/AttendanceSystem: 员工考勤系统(C语言实现) (github.com)

代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
// 定义最大用户数、最大组数和最大打卡记录数
#define MAX_USER 100
#define MAX_GROUP 1000
#define MAX_CLOCKIN 1000
// 打卡记录结构体
typedef struct clockin
{
    time_t begin_time; // 打卡开始时间
    time_t end_time;   // 打卡结束时间
    int in[MAX_USER];  // 用户打卡状态数组
    int group_from;    // 该打卡记录所属的组编号
}clockin;
// 用户组结构体
typedef struct group
{
    char group_name[100];  // 组名
    int member[MAX_USER];  // 组成员数组
    int priority[MAX_USER]; // 用户在组中的优先级或角色
}group;
// 用户信息结构体
typedef struct user
{
    char uid[30];    // 用户ID
    char password[30]; // 用户密码
}user;
// 用户集合数组和长度
user user_set[MAX_USER];
int user_set_length = 0;
// 组集合数组和长度
group group_set[MAX_GROUP];
int group_set_length = 0;
// 打卡记录集合数组和长度
clockin clockin_set[MAX_CLOCKIN];
int clockin_set_length = 0;
// 用户界面功能选择变量
int ui_func;
// 当前登录用户编号和目标组编号
int current_user = -1;
int global_target_group = -1;
// 搜索用户函数
int search_user(user usr)
{
    int i;
    for (i = 0; i < user_set_length; i++)
    {
        if (strcmp(user_set[i].uid, usr.uid) == 0)
        {
            return i;
        }
    }
    return -1;
}
// 根据用户ID搜索用户编号
int search_uid(char *uid)
{
    int i;
    for (i = 0; i < user_set_length; i++)
    {
        if (strcmp(user_set[i].uid, uid) == 0)
        {
            return i;
        }
    }
    return -1;
}
// 读取用户数据函数
void read_user_set()
{
    FILE *userdata = fopen("data/user_data", "r+");
    if (userdata == NULL)
    {
        printf("读取用户数据失败\n");
        return;
    }
    fseek(userdata, 0, SEEK_END);
    if (ftell(userdata) == 0)           // 空文件
    {
        return;
    }
    fseek(userdata, 0, SEEK_SET);
    fscanf(userdata, "%d", &user_set_length);
    for (int i = 0 ; i < user_set_length; i++)
    {
        fscanf(userdata, "%s", user_set[i].uid);
        fscanf(userdata, "%s", user_set[i].password);
    }
    fclose(userdata);
    return;
}
// 写入用户数据函数
void write_user_set()
{
    FILE *userdata = fopen("data/user_data", "w");
    if (userdata == NULL)
    {
        printf("读取用户数据失败\n");
        return;
    }
    fprintf(userdata, "%d\n", user_set_length);
    for (int i = 0 ; i < user_set_length; i++)
    {
        fprintf(userdata, "%s\n", user_set[i].uid);
        fprintf(userdata, "%s\n", user_set[i].password);
    }
    fclose(userdata);
    return;
}
// 读取组数据函数
void read_group_set()
{
    FILE *groupdata = fopen("data/group_data", "r+");
    if (groupdata == NULL)
    {
        printf("读取组数据失败\n");
        return;
    }
    fseek(groupdata, 0, SEEK_END);
    if (ftell(groupdata) == 0)           // 空文件
    {
        return;
    }
    fseek(groupdata, 0, SEEK_SET);
    fscanf(groupdata, "%d", &group_set_length);
    for (int j = 0; j < group_set_length; j++)
    {
        char temp_str[110];
        fscanf(groupdata, "%s", &temp_str);
        strcpy(group_set[j].group_name, temp_str);
        fscanf(groupdata, "%s", &temp_str);
        for (int i = 0 ; i < MAX_USER; i++)
        {
            group_set[j].member[i] = temp_str[i] - 48;
        }
        fscanf(groupdata, "%s", &temp_str);
        for (int i = 0 ; i < MAX_USER; i++)
        {
            group_set[j].priority[i] = temp_str[i] - 48;
        }
    }
    fclose(groupdata);
    return;
}
// 写入组数据函数
void write_group_set()
{
    FILE *groupdata = fopen("data/group_data", "w");
    if (groupdata == NULL)
    {
        printf("读取组数据失败\n");
        return;
    }
    fprintf(groupdata, "%d\n", group_set_length);
    for (int i = 0 ; i < group_set_length; i++)
    {
        fprintf(groupdata, "%s\n", group_set[i].group_name);
        for (int j = 0; j < MAX_USER; j++)
        {
            fprintf(groupdata, "%d", group_set[i].member[j]);
        }
        fprintf(groupdata, "\n");
        for (int j = 0; j < MAX_USER; j++)
        {
            fprintf(groupdata, "%d", group_set[i].priority[j]);
        }
        fprintf(groupdata, "\n");
    }
    fclose(groupdata);
    return;
}
// 检查用户是否在组中
int is_usr_in_group(int groupNo, int usr)
{
    return group_set[groupNo].member[usr];
}
// 检查打卡记录是否在组中
int is_clockin_in_group(int groupNo, int clockinNo)
{
    return clockin_set[clockinNo].group_from == groupNo;
}
// 用户ID转换为用户编号
int uid_2_usr(char *uid)
{
    for (int i = 0; i < MAX_USER; i++)
    {
        if (strcmp(user_set[i].uid, uid) == 0)
        {
            return i;
        }
    }
    return -1;
}
// 读取打卡记录数据函数
void read_clockin_set()
{
    FILE *clockindata = fopen("data/clockin_data", "r+");
    if (clockindata == NULL)
    {
        printf("读取打卡数据失败\n");
        return;
    }
    for (int i = 0; i < MAX_CLOCKIN; i++)
    {
        clockin_set[i].group_from = -1;
    }
    fseek(clockindata, 0, SEEK_END);
    if (ftell(clockindata) == 0)           // 空文件
    {
        return;
    }
    fseek(clockindata, 0, SEEK_SET);
    fscanf(clockindata, "%d", &clockin_set_length);
    for (int j = 0; j < clockin_set_length; j++)
    {
        char temp_str[110];
        long temp_long;
        int temp_int;
        fscanf(clockindata, "%ld", &temp_long);
        clockin_set[j].begin_time = temp_long;
        fscanf(clockindata, "%ld", &temp_long);
        clockin_set[j].end_time = temp_long;
        fscanf(clockindata, "%s", &temp_str);
        for (int i = 0 ; i < MAX_USER; i++)
        {
            clockin_set[j].in[i] = temp_str[i] - 48;
        }
        fscanf(clockindata, "%d", &temp_int);
        clockin_set[j].group_from = temp_int;
    }
    fclose(clockindata);
    return;
}
// 写入打卡记录数据函数
void write_clockin_set()
{
    FILE *clockindata = fopen("data/clockin_data", "w");
    if (clockindata == NULL)
    {
        printf("读取打卡数据失败\n");
        return;
    }
    fprintf(clockindata, "%d\n", clockin_set_length);
    for (int i = 0 ; i < clockin_set_length; i++)
    {
        fprintf(clockindata, "%ld\n", clockin_set[i].begin_time);
        fprintf(clockindata, "%ld\n", clockin_set[i].end_time);
        for (int j = 0; j < MAX_USER; j++)
        {
            fprintf(clockindata, "%d", clockin_set[i].in[j]);
        }
        fprintf(clockindata, "\n");
        fprintf(clockindata, "%d\n", clockin_set[i].group_from);
    }
    fclose(clockindata);
    return;
}
// 检查用户是否在打卡记录中
int is_usr_in_clockin(int clockinNo)
{
    return group_set[clockin_set[clockinNo].group_from].member[current_user];
}
int main()
{
    ui_func = -1;
    // -2 -- welcome已登录
    // -1 -- welcome未登录
    // 0 -- 登录界面
    // 1 -- 注册界面
    read_user_set();
    read_group_set();
    read_clockin_set();
    while (1)
    {
        system("cls");
        if (ui_func == 0)           // 登录界面
        {
            user login_user;
            printf("请先登录\n用户名:");
            scanf("%s", login_user.uid);
            printf("密码:");
            scanf("%s", login_user.password);
            fflush(stdin);
            if (search_user(login_user) == -1)  // 未注册
            {
                printf("未找到该用户,是否注册?(y/n)\n");
                int temp_i = 1;
                char temp_c;
                while (temp_i)
                {
                    system("cls");
                    printf("未找到该用户,是否注册?(y/n)\n");
                    scanf("%c", &temp_c);
                    fflush(stdin);
                    if (temp_c == 'y' || temp_c == 'n')
                        break;
                }
                if (temp_c == 'y')
                {
                    ui_func = 1;
                    continue;
                }
                else if (temp_c == 'n')
                {
                    ui_func = -1;
                    continue;
                }
            }
            else
            {
                int No = search_user(login_user);
                if (strcmp(login_user.password, user_set[No].password) == 0)
                {
                    printf("登录成功\n");
                    current_user = No;
                    ui_func = -2;
                }
                else
                {
                    printf("密码错误\n");
                    getchar();
                }
            }
        }
        else if (ui_func == 1)          // 注册界面
        {
            user register_user;
            char re_password[30];
            printf("请先注册\n用户名:");
            scanf("%s", register_user.uid);
            printf("密码:");
            scanf("%s", register_user.password);
            printf("请重复密码:");
            scanf("%s", &re_password);
            fflush(stdin);
            if (search_user(register_user) != -1)
            {
                int temp_i = 1;
                char temp_c;
                while (temp_i)
                {
                    system("cls");
                    printf("该用户已存在,是否跳转到登录?(y/n)\n");
                    scanf("%c", &temp_c);
                    fflush(stdin);
                    if (temp_c == 'y' || temp_c == 'n')
                        break;
                }
                if (temp_c == 'y')
                {
                    ui_func = 0;
                    continue;
                }
                else if (temp_c == 'n')
                {
                    ui_func = -1;
                    continue;
                }
            }
            if (strcmp(re_password, register_user.password) != 0)
            {
                printf("两次密码不相同,请再次输入\n");
                ui_func = 1;
                continue;
            }
            else       
            {
                printf("注册成功,将自动为您登录\n");
                strcpy(user_set[user_set_length].uid, register_user.uid);
                strcpy(user_set[user_set_length].password, register_user.password);
                user_set_length++;
                write_user_set();
                current_user = user_set_length - 1;
                ui_func = -2;
            }
        }
        else if (ui_func == -1)         // welcome未登录
        {          
            char temp_c;
            while (1)
            {
                system("cls");
                printf("这是一句welcome\n输入序号以访问功能\n1 登录\n2 注册\n");
                scanf("%c", &temp_c);
                fflush(stdin);
                if (temp_c == '1' || temp_c == '2')
                    break;
            }
            if (temp_c == '1')
                ui_func = 0;
            else
                ui_func = 1;
        }
        else if (ui_func == -2)         // welcome已登录
        {
            int temp_i;
            while (1)
            {
                system("cls");
                printf("你好%s\n输入序号以访问功能\n1 打卡\n2 发布新的打卡\n3 查看我所在的组\n4 创建组\n5 管理组\n9 退出登录\n", user_set[current_user].uid);  
                scanf("%d", &temp_i);
                fflush(stdin);
                if ((temp_i >= 1 && temp_i <= 5) || temp_i == 9)
                    break;
            }
            if (temp_i == 1)
                ui_func = 20;
            else if (temp_i == 4)
                ui_func = 10;
            else if (temp_i == 3)
                ui_func = 11;
            else if (temp_i == 2)
                ui_func = 21;
            else if (temp_i == 9)
                ui_func = 99;
            else if (temp_i == 5)
                ui_func = 30;
        }
        else if (ui_func == 10)        // 创建组
        {
            const char end_str[10] = "$end";
            char temp_uid[30];
            char temp_group_name[100];
            group_set[group_set_length].member[current_user] = 1;
            group_set[group_set_length].priority[current_user] = 1;
            system("cls");
            printf("请输入小组名称:"); 
            scanf("%s", &temp_group_name); 
            strcpy(group_set[group_set_length].group_name, temp_group_name);
            while (1)
            {
                system("cls");
                printf("小组名称:%s\n", group_set[group_set_length].group_name);  
                printf("请输入其它用户的用户名进行邀请\n管理员:%s\n", user_set[current_user].uid);  
                printf("用户:");
                for (int i = 0; i < MAX_USER; i++)
                {
                    if (group_set[group_set_length].member[i] && i != current_user)
                    {
                        printf("%s  ", user_set[i].uid);
                    }
                }
                printf("\n\n其它用户的用户名(或输入%cend结束):", 36);
                scanf("%s", &temp_uid);
                fflush(stdin);
                if (strcmp(end_str, temp_uid) == 0)
                    break;
                if (search_uid(temp_uid) == -1)
                {
                    printf("未找到该用户(按下回车以继续)");
                    getchar();
                }
                else
                {
                    group_set[group_set_length].member[search_uid(temp_uid)] = 1;
                    group_set[group_set_length].priority[search_uid(temp_uid)] = 0;
                }
            }
            system("cls");
            printf("小组创建完毕\n小组名称:%s\n管理员:%s\n", group_set[group_set_length].group_name, user_set[current_user].uid);  
            printf("用户:");
            for (int i = 0; i < MAX_USER; i++)
            {
                if (group_set[group_set_length].member[i] && i != current_user)
                {
                    printf("%s  ", user_set[i].uid);
                }
            }
            printf("\n");
            group_set_length++;
            write_group_set();
            ui_func = -2;
            printf("按下回车以返回主界面\n");
            getchar();
        }
        else if (ui_func == 11)
        {
            system("cls");  
            printf("%s所在的所有组:\n", user_set[current_user].uid);  
            for (int i = 0; i < MAX_GROUP; i++)
            {
                if (is_usr_in_group(i, current_user))
                {
                    printf("%s\n", group_set[i].group_name);  
                }
            }
            ui_func = -2;
            printf("\n按下回车以返回主界面\n");
            getchar();
        }
        else if (ui_func == 20)
        {
            system("cls");  
            printf("%s目前有的所有打卡:\n", user_set[current_user].uid);  
            for (int i = 0; i < MAX_CLOCKIN; i++)
            {
                if (group_set[clockin_set[i].group_from].member[current_user])
                {
                    struct tm *showtime;
                    printf("打卡编号:%d\n", i);
                    showtime = localtime(&clockin_set[i].begin_time);
                    printf("起始:%s", asctime(showtime));
                    showtime = localtime(&clockin_set[i].end_time);
                    printf("结束:%s", asctime(showtime));
                    if (clockin_set[i].in[current_user] == 1)
                    {
                        printf("已打卡\n\n");
                    }
                    else
                    {
                        printf("未打卡\n\n");
                    } 
                }
            }
            int target_clockin = -2;
            printf("输入打卡编号进行打卡(或输入-1返回主界面)\n");
            scanf("%d", &target_clockin);
            fflush(stdin);
            if (target_clockin == -1 || is_usr_in_clockin(target_clockin))
            {
                if (target_clockin == -1)
                {
                    ui_func = -2;
                    continue;
                }
                else if (clockin_set[target_clockin].in[current_user] == 1)
                {
                    printf("已打卡,请勿重复打卡。\n");
                    getchar();
                    continue;
                }
                else
                {
                    time_t now_time = time(0);
                    time(&now_time);
                    if (now_time >= clockin_set[target_clockin].begin_time && now_time <= clockin_set[target_clockin].end_time)
                    {
                        printf("打卡成功。\n");
                        getchar();
                        clockin_set[target_clockin].in[current_user] = 1;
                        write_clockin_set();
                        continue;
                    }
                    else
                    {
                        printf("打卡失败。未在指定时间\n");
                        getchar();
                        continue;
                    }
                }
            }
            else
            {
                printf("输入有误,请重新输入\n");
                getchar();
            }
        }
        else if (ui_func == 21)
        {
            system("cls");  
            int have_any_p = 0;
            for (int i = 0; i < MAX_GROUP; i++)
            {
                if (is_usr_in_group(i, current_user))
                {
                    if (group_set[i].priority[current_user])
                        have_any_p = 1; 
                }
            }
            if (have_any_p == 0)
            {
                ui_func = -2;
                printf("你目前没有任何权限,即将返回\n");
                getchar();
                continue;
            }
            printf("%s所有有权限的组:\n", user_set[current_user].uid);  
            for (int i = 0; i < MAX_GROUP; i++)
            {
                if (is_usr_in_group(i, current_user))
                {
                    if (group_set[i].priority[current_user])
                        printf("%s\n", group_set[i].group_name);  
                }
            }
            printf("\n输入选择要创建打卡的组的名称:");
            char temp_gn[100];
            scanf("%s", &temp_gn);
            fflush(stdin);
            int target_group = 0;
            int flag = 0;
            for (; target_group < MAX_GROUP && flag == 0; target_group++)
            {
                if (is_usr_in_group(target_group, current_user))
                {
                    if (group_set[target_group].priority[current_user])
                    {
                        if (strcmp(temp_gn, group_set[target_group].group_name) == 0)
                        {
                            flag = 1;
                            break;
                        }
                    }
                }
            }
            if (flag == 0)
            {
                printf("\n未找到该组,请重新输入\n");
                getchar();
                continue;
            }
            else
            {
                clockin_set[clockin_set_length].group_from = target_group;
                
                int holding = 0;            // 分钟
                time_t begin = time(0);
                time_t end = time(0);
                struct tm *time_show;
                time(&begin);
                system("cls"); 
                printf("请输入打卡持续时间(分钟):");
                scanf("%d", &holding);
                fflush(stdin);
                end = begin + holding * 60;
                printf("小组:%s\n", group_set[target_group].group_name);
                time_show = localtime(&begin);
                printf("起始时间:%s", asctime(time_show));
                time_show = localtime(&end);
                printf("结束时间:%s", asctime(time_show));
                clockin_set[clockin_set_length].begin_time = begin;
                clockin_set[clockin_set_length].end_time = end;
                for (int i = 0; i < MAX_USER; i++)
                {
                    clockin_set[clockin_set_length].in[i] = 0;
                }
                clockin_set_length++;
                write_clockin_set();
                ui_func = -2;
                printf("\n打卡创建完毕,回车以返回主界面\n");
                getchar();
            }
            
        }
        else if (ui_func == 99)
        {
            ui_func = -1;
            current_user = -1;
            printf("已退出登录,将返回登录界面\n");
            getchar();
        }
        else if (ui_func == 30)
        {
            system("cls"); 
            printf("%s所在的所有组:\n", user_set[current_user].uid);  
            for (int i = 0; i < MAX_GROUP; i++)
            {
                if (is_usr_in_group(i, current_user))
                {
                    printf("%s\n", group_set[i].group_name);  
                }
            }
            printf("\n输入选择要查看的组的名称(输入$back返回):");
            char temp_gn[100];
            scanf("%s", &temp_gn);
            fflush(stdin);
            if (strcmp("$back", temp_gn) == 0)
            {
                ui_func = -2;
                continue;
            }
            int target_group = 0;
            int flag = 0;
            for (; target_group < MAX_GROUP && flag == 0; target_group++)
            {
                if (is_usr_in_group(target_group, current_user))
                {
                    if (strcmp(temp_gn, group_set[target_group].group_name) == 0)
                    {
                        flag = 1;
                        break;
                    }
                }
            }
            if (flag == 0)
            {
                printf("\n未找到该组,请重新输入\n");
                getchar();
                continue;
            }
            else
            {
                system("cls"); 
                printf("小组:%s\n", group_set[target_group].group_name);
                printf("管理员:");
                for (int i = 0; i < MAX_USER; i++)
                {
                    if (group_set[target_group].member[i] && group_set[target_group].priority[i])
                    {
                        printf("%s  ", user_set[i].uid);
                    }
                }
                printf("\n");
                printf("其它成员:");
                for (int i = 0; i < MAX_USER; i++)
                {
                    if (group_set[target_group].member[i] && group_set[target_group].priority[i] == 0)
                    {
                        printf("%s  ", user_set[i].uid);
                    }
                }
                printf("\n");
                if (group_set[target_group].priority[current_user])
                {
                    ui_func = 31;
                    global_target_group = target_group;
                    continue;
                }
                else
                {
                    printf("您是一般成员\n(回车以返回)");
                    getchar();
                }
            }
        }
        else if (ui_func == 31)
        {
            int temp_i;
            while (1)
            {
                system("cls");
                printf("小组:%s\n", group_set[global_target_group].group_name);
                printf("管理员:");
                for (int i = 0; i < MAX_USER; i++)
                {
                    if (group_set[global_target_group].member[i] && group_set[global_target_group].priority[i])
                    {
                        printf("%s  ", user_set[i].uid);
                    }
                }
                printf("\n");
                printf("其它成员:");
                for (int i = 0; i < MAX_USER; i++)
                {
                    if (group_set[global_target_group].member[i] && group_set[global_target_group].priority[i] == 0)
                    {
                        printf("%s  ", user_set[i].uid);
                    }
                }
                printf("\n您是管理员\n输入序号以访问功能\n1 查看个人数据\n2 查看打卡数据\n9 返回\n");
                scanf("%d", &temp_i);
                fflush(stdin);
                if ((temp_i >= 1 && temp_i <= 2) || temp_i == 9)
                    break;
            }
            if (temp_i == 1)
            {
                char temp_uid[30];
                while (1)
                {
                    system("cls");
                    printf("小组:%s\n", group_set[global_target_group].group_name);
                    printf("全部成员:");
                    for (int i = 0; i < MAX_USER; i++)
                    {
                        if (group_set[global_target_group].member[i])
                        {
                            printf("%s  ", user_set[i].uid);
                        }
                    }
                    printf("\n输入成员的uid以查看其打卡数据\n");
                    scanf("%s", &temp_uid);
                    fflush(stdin);
                    if (is_usr_in_group(global_target_group, uid_2_usr(temp_uid)))
                    {
                        break;
                    }
                    else
                    {
                        printf("\n该成员不在小组中\n");
                        getchar();
                    }
                }
                system("cls");  
                printf("成员:%s目前在组内所有打卡:\n", user_set[uid_2_usr(temp_uid)].uid);  
                int all = 0, intime = 0, outtime = 0;
                for (int i = 0; i < MAX_CLOCKIN; i++)
                {
                    if (group_set[clockin_set[i].group_from].member[uid_2_usr(temp_uid)] && clockin_set[i].group_from == global_target_group)
                    {
                        all++;
                        struct tm *showtime;
                        printf("打卡编号:%d\n", i);
                        showtime = localtime(&clockin_set[i].begin_time);
                        printf("起始:%s", asctime(showtime));
                        showtime = localtime(&clockin_set[i].end_time);
                        printf("结束:%s", asctime(showtime));
                        if (clockin_set[i].in[uid_2_usr(temp_uid)] == 1)
                        {
                            printf("已打卡\n\n");
                            intime++;
                        }
                        else
                        {
                            printf("未打卡\n\n");
                            outtime++;
                        } 
                    }
                }
                printf("\n总打卡%d次,准时%d次,迟到%d次,到勤率%.2lf\n", all, intime, outtime, (double)intime/(double)all);
                getchar();
                continue;
            }
            else if (temp_i == 2)
            {
                int temp_int;
                while (1)
                {
                    system("cls");
                    printf("小组:%s\n", group_set[global_target_group].group_name);
                    printf("全部打卡:\n");
                    for (int i = 0; i < clockin_set_length; i++)
                    {
                        if (clockin_set[i].group_from == global_target_group)
                        {
                            struct tm *showtime;
                            printf("打卡编号:%d\n", i);
                            showtime = localtime(&clockin_set[i].begin_time);
                            printf("起始:%s", asctime(showtime));
                            showtime = localtime(&clockin_set[i].end_time);
                            printf("结束:%s", asctime(showtime));
                        }
                    }
                    printf("\n输入打卡的编号以查看其打卡数据\n");
                    scanf("%d", &temp_int);
                    fflush(stdin);
                    if (is_clockin_in_group(global_target_group, temp_int))
                    {
                        break;
                    }
                    else
                    {
                        printf("\n小组中没有该打卡\n");
                        getchar();
                    }
                }
                struct tm *showtime;
                system("cls");
                printf("打卡编号:%d\n", temp_int);
                showtime = localtime(&clockin_set[temp_int].begin_time);
                printf("起始:%s", asctime(showtime));
                showtime = localtime(&clockin_set[temp_int].end_time);
                printf("结束:%s", asctime(showtime));
                int all = 0, intime = 0, outtime = 0;
                printf("已签到:\n");
                for (int i = 0; i < MAX_USER; i++)
                {
                    if (group_set[global_target_group].member[i])
                    {
                        all++;
                        if (clockin_set[temp_int].in[i])
                        {
                            intime++;
                            printf("%s  ", user_set[i].uid);
                        }
                    }
                }
                printf("\n未签到:\n");
                for (int i = 0; i < MAX_USER; i++)
                {
                    if (group_set[global_target_group].member[i])
                    {
                        if (clockin_set[temp_int].in[i] == 0)
                        {
                            outtime++;
                            printf("%s  ", user_set[i].uid);
                        }
                    }
                }
                printf("\n总共%d人参与打卡,准时%d人,迟到%d人,到勤率%.2lf\n", all, intime, outtime, (double)intime/(double)all);
            }
            else
            {
                global_target_group = -1;
                ui_func = -2;
                continue;
            }
            getchar();
        }
    }
}

image.gif


相关实践学习
MySQL基础-学生管理系统数据库设计
本场景介绍如何使用DMS工具连接RDS,并使用DMS图形化工具创建数据库表。
目录
相关文章
|
18天前
|
IDE 编译器 开发工具
【C语言】全面系统讲解 `#pragma` 指令:从基本用法到高级应用
在本文中,我们系统地讲解了常见的 `#pragma` 指令,包括其基本用法、编译器支持情况、示例代码以及与传统方法的对比。`#pragma` 指令是一个强大的工具,可以帮助开发者精细控制编译器的行为,优化代码性能,避免错误,并确保跨平台兼容性。然而,使用这些指令时需要特别注意编译器的支持情况,因为并非所有的 `#pragma` 指令都能在所有编译器中得到支持。
93 41
【C语言】全面系统讲解 `#pragma` 指令:从基本用法到高级应用
|
14天前
|
存储 编译器 C语言
【C语言】C语言的变量和声明系统性讲解
在C语言中,声明和定义是两个关键概念,分别用于告知编译器变量或函数的存在(声明)和实际创建及分配内存(定义)。声明可以多次出现,而定义只能有一次。声明通常位于头文件中,定义则在源文件中。通过合理组织头文件和源文件,可以提高代码的模块化和可维护性。示例包括全局变量、局部变量、函数、结构体、联合体、数组、字符串、枚举和指针的声明与定义。
43 12
|
24天前
|
存储 算法 程序员
C 语言递归算法:以简洁代码驾驭复杂逻辑
C语言递归算法简介:通过简洁的代码实现复杂的逻辑处理,递归函数自我调用解决分层问题,高效而优雅。适用于树形结构遍历、数学计算等领域。
|
1月前
|
存储 安全 物联网
C语言物联网开发之设备安全与代码可靠性隐患
物联网设备的C语言代码安全与可靠性至关重要。一是防范代码安全漏洞,包括缓冲区溢出和代码注入风险,通过使用安全函数和严格输入验证来预防。二是提高代码跨平台兼容性,利用`stdint.h`定义统一的数据类型,并通过硬件接口抽象与适配减少平台间的差异,确保程序稳定运行。
|
25天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
39 1
|
25天前
|
人工智能 安全 算法
基于C语言的嵌入式系统开发,涵盖嵌入式系统概述、C语言的优势、开发流程、关键技术、应用实例及面临的挑战与未来趋势。
本文深入探讨了基于C语言的嵌入式系统开发,涵盖嵌入式系统概述、C语言的优势、开发流程、关键技术、应用实例及面临的挑战与未来趋势。C语言因其高效、可移植、灵活及成熟度高等特点,在嵌入式系统开发中占据重要地位。文章还介绍了从系统需求分析到部署维护的完整开发流程,以及中断处理、内存管理等关键技术,并展望了嵌入式系统在物联网和人工智能领域的未来发展。
57 1
|
25天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
56 1
|
22天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
46 10
|
22天前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
43 9
|
22天前
|
存储 Unix Serverless
【C语言】常用函数汇总表
本文总结了C语言中常用的函数,涵盖输入/输出、字符串操作、内存管理、数学运算、时间处理、文件操作及布尔类型等多个方面。每类函数均以表格形式列出其功能和使用示例,便于快速查阅和学习。通过综合示例代码,展示了这些函数的实际应用,帮助读者更好地理解和掌握C语言的基本功能和标准库函数的使用方法。感谢阅读,希望对你有所帮助!
32 8