C语言 具备信息管理功能的打卡机

Punch_Clock_Machine.h

#ifndef _Punch_Clock_Machine_H_
#define _Punch_Clock_Machine_H_

#include<stdio.h>
#include<stdlib.h>
#include<time.h>                                            //生成随机数
#include<unistd.h>                                          //sleep函数的头文件
#include<sys/time.h>                                        //gettimeofday(struct timeval * tv, struct timezone * tz)计时函数
#include<pthread.h>                                         //多线程头文件

#define Standard_Worktime   9.0
#define Staff_Max   20
#define Test_Proportion     30                              //测试以30秒为1小时
#define Number_Length   6                                   //员工编码长度设置为6位

struct Punch_Clock_Note{                                    //打卡记录类
    struct timeval Punch_StartTime;                         //上班打卡时刻
    struct timeval Punch_EndTime;                           //下班打卡时刻
    char Start_Flag;                                        //上班打卡标记    
    char End_Flag;                                          //下班打卡标记
    char Elasticity_Flag;                                   //弹性打卡标记
    float Work_Timeuse;                                     //上班耗时
    float Week_Work_Timeuse;                                //周上班耗时
    int Late_Number;                                        //迟到次数    
    int Early_Number;                                       //早退次数
    int Absenteeism_Number;                                 //旷工次数
    int Lack_Number;                                        //缺卡次数                              
}PCN;

struct Staff_Massege{                                       //员工信息类
    char Name[30];                                          //姓名
    char Mailbox[30];                                       //邮箱
    char Sex[10];                                           //性别
    int Age;                                                //年龄
    int Staff_Number;                                       //员工编号
    int Staff_Check_Number;                                 //效验码
    long int Phone;                                         //电话号码
    struct Punch_Clock_Note Staff_Work_Note;                //员工的工作记录
}SM;

struct Staff{                                               //员工类
    struct Staff_Massege Staff_Array[Staff_Max];
    int Size;                                               //一开始没有员工
}S;

struct Machine_Time{  
    int Month;                                          
    int Week;                                           
    int Time;                                           
    struct timeval Machine_StartTime;                       //打卡机开始工作时刻 
    struct timeval Machine_EndTime;                         //打卡机目前工作时刻 
    float Machine_Timeuse;                                  //机器运行时长
}MT;

void *Clockin_Machine_Work();                               //打卡机运行计时函数
void Main_Menu();                                           //主界面
void Select_Menu();                                         //打卡菜单
void Get_Staff_Number(struct Staff*);                       //员工编码与效验码生成
void Add_Staff_Massege(struct Staff*);                      //添加员工信息
void Delete_Staff_Massege(struct Staff*);                   //删除员工信息
void Find_Staff_Massege(struct Staff*);                     //查找员工信息
void Modify_Staff_Massege(struct Staff*);                   //修改员工信息
void Staff_Massege_Menu(struct Staff*);                     //员工信息管理菜单
void Morning_Punch_Clock(struct Staff*);                    //上班打卡
void Night_Punch_Clock(struct Staff*);                      //下班打卡
void Machine_Record_Refresh(struct Staff*);                 //打卡机记录数据并刷新
void Punch_Clock_List(struct Staff*);                       //打卡记录表
void Week_Reward_Punish(struct Staff*);                     //每周奖励与惩罚 
void Clear_Screen();                                        //清屏函数
void Clockin_Machine_Start();                               //打卡机实现总函数

#endif

Punch_Clock_Machine.c

#include"../header/Punch_Clock_Machine.h"

void *Clockin_Machine_Work(void *arg){
    MT.Month = 1;
    MT.Week = 1;
    MT.Time = 7;                                            //初始为第一周早上七点                       
    gettimeofday(&MT.Machine_StartTime,NULL);
    while (1){
        sleep(1);
        gettimeofday(&MT.Machine_EndTime,NULL);
        MT.Machine_Timeuse = MT.Machine_EndTime.tv_sec - MT.Machine_StartTime.tv_sec;
        if (0 == ((int)MT.Machine_Timeuse)%Test_Proportion){
            MT.Time++;
            if (0==(MT.Time%24)){
                MT.Time=0;
                MT.Week++;
                Machine_Record_Refresh(&S);
                if ((5 == MT.Week) && (24 == MT.Time)){        
                    Week_Reward_Punish(&S);                 //测试在周五晚上12点结束测试结束自动打印本周的报告                                 
                    break;
                }
                if (0==(MT.Week%7)){
                    MT.Week=1;
                    MT.Month++;
                }
            } 
        }
    }
    return NULL;
}

void Main_Menu(){                                               
    printf("**********************\n");
    printf("**********************\n");
    printf("******  打卡机  ******\n");
    printf("**********************\n");
    printf("**********************\n");
    printf("    星期%d   %d时\n",MT.Week,MT.Time);
    printf("----------------------\n");
}

void Select_Menu(){
    int i = 1;
    while (i != 0){
        int Choice_1 = 0; 
        int Choice_2 = 0;
        Main_Menu();
        printf("0(信息管理)1(开始打卡)\n2(查询记录)3(退出程序)\n");                                     
        scanf("%d",&Choice_1);
        Clear_Screen();
        switch (Choice_1){
            case 0:{
                Staff_Massege_Menu(&S);
                break;
            }
            case 1:{
                Main_Menu();
                printf("1(上班打卡)2(下班打卡)\n");
                scanf("%d",&Choice_2);
                Clear_Screen();
                switch (Choice_2){
                    case 1:{
                        Morning_Punch_Clock(&S);
                        break;
                    }
                    case 2:{
                        Night_Punch_Clock(&S);
                        break;    
                    }
                }
                break;
            }
            case 2:{
                Punch_Clock_List(&S);
                break;
            }
            case 3:{
                printf("感谢使用\n");
                Clear_Screen();
                i = 0;
                break;
            }
        }
    }                                          
}

void Get_Staff_Number(struct Staff *S){
    int Staff_Number[6];
    int Inverse_5_Number;
    int temp;
    int ret = 0;
    while (ret != 1){
        ret = 1;
        Staff_Number[0] = 1;
        for (int i = 1; i < Number_Length; i++){
            Staff_Number[Number_Length-i] = rand()%10;            
        }
        S->Staff_Array[S->Size].Staff_Number = 100000;
        temp = 10000;
        for (int i = 1; i < Number_Length; i++){
            S->Staff_Array[S->Size].Staff_Number += Staff_Number[i] * temp;
            temp /= 10;
        }
        for (int i = 0; i < S->Size; i++){
            if (S->Staff_Array[S->Size].Staff_Number == S->Staff_Array[i].Staff_Number){
                ret = 2;
            }
        }   
    }

    temp = 10000;
    for (int i = 1; i < Number_Length; i++){
        Inverse_5_Number += Staff_Number[Number_Length-i] * temp;
        temp /= 10;
    }
    S->Staff_Array[S->Size].Staff_Check_Number = Inverse_5_Number + S->Staff_Array[S->Size].Staff_Number;
}

void Add_Staff_Massege(struct Staff *S){
    Main_Menu();
    if (Staff_Max == S->Size){                                 
        printf("打卡机存储空间已满已满\n");
    }
    else{
        printf("请录入员工姓名\n");
        scanf("%s",S->Staff_Array[S->Size].Name);
        
        printf("请录入员工年龄\n");
        scanf("%d",&S->Staff_Array[S->Size].Age);
        
        printf("请录入员工性别\n");
        scanf("%s",S->Staff_Array[S->Size].Sex);

        printf("请录入员工电话\n");
        scanf("%ld",&S->Staff_Array[S->Size].Phone);

        printf("请录入员工邮箱\n");
        scanf("%s",S->Staff_Array[S->Size].Mailbox);

        Get_Staff_Number(S);
        printf("%s的员工编号为:%d\n",S->Staff_Array[S->Size].Name,S->Staff_Array[S->Size].Staff_Number);
        printf("%s的效验码为:%d\n",S->Staff_Array[S->Size].Name,S->Staff_Array[S->Size].Staff_Check_Number);

        S->Size++;
        printf("添加成功\n");
        Clear_Screen(); 
    }
}

void Delete_Staff_Massege(struct Staff *S){
    int ret = -1;
    int Staff_Number = 0;
    Main_Menu();
    printf("请输入需要删除的员工编号\n");
    scanf("%d",&Staff_Number);
    for (int i = 0; i < S->Size; i++){
        if (Staff_Number == S->Staff_Array[i].Staff_Number){
            ret = i;
        }  
    }
    if (-1 != ret){
        for (int i = ret; i < S->Size; i++){
            S->Staff_Array[i] = S->Staff_Array[i+1];
        }
        S->Size--;
        printf("删除成功\n");
    }
    else{
        printf("没有该员工信息\n");
    }
    Clear_Screen();
}   

void Find_Staff_Massege(struct Staff *S){
    int ret = -1; 
    int Staff_Number = 0;
    Main_Menu();
    printf("请输入需要查找的员工编号\n");
    scanf("%d",&Staff_Number);
    for (int i = 0; i < S->Size; i++){
        if (Staff_Number == S->Staff_Array[i].Staff_Number){
            ret = i;
        }  
    }
    if (-1 != ret){
        printf("----------------------\n");
        printf("员工姓名:%s",S->Staff_Array[ret].Name);
        printf("\t编号:%d",S->Staff_Array[ret].Staff_Number);
        printf("\t性别:%s",S->Staff_Array[ret].Sex);
        printf("\t年龄:%d\n",S->Staff_Array[ret].Age);
        printf("电话:%ld",S->Staff_Array[ret].Phone);
        printf("\t邮箱:%s\n",S->Staff_Array[ret].Mailbox);
        printf("周均工作时长:%.1f",S->Staff_Array[ret].Staff_Work_Note.Week_Work_Timeuse/5.0);
        printf("\t周迟到次数:%d",S->Staff_Array[ret].Staff_Work_Note.Late_Number);
        printf("\t周早退次数:%d",S->Staff_Array[ret].Staff_Work_Note.Early_Number);
        printf("\t周旷工次数:%d",S->Staff_Array[ret].Staff_Work_Note.Absenteeism_Number);
        printf("\t周缺卡次数:%d\n",S->Staff_Array[ret].Staff_Work_Note.Lack_Number);
    }
    else{
        printf("没有该员工信息\n");
    }
    Clear_Screen();
}   

void Modify_Staff_Massege(struct Staff *S){
    int Choice = 0;
    int ret = -1; 
    int Staff_Number = 0;
    Main_Menu();
    printf("请输入需要修改的员工编号\n");
    scanf("%d",&Staff_Number);
    for (int i = 0; i < S->Size; i++){
        if (Staff_Number == S->Staff_Array[i].Staff_Number){
            ret = i;
        }  
    }
    if (-1 != ret){
        printf("请输入需要修改的信息\n1(电话)2(邮箱)3(迟到次数)4(早退次数)5(缺卡次数)6(旷工次数)\n");
        scanf("%d",&Choice);
        switch (Choice){
            case 1:{
                printf("请输入新的电话\n");
                scanf("%ld",&S->Staff_Array[ret].Phone);
                break;
            }
            case 2:{
                printf("请输入新的邮箱\n");
                scanf("%s",S->Staff_Array[ret].Mailbox);
                break;
            }
            case 3:{
                printf("请输入更正后的迟到次数\n");
                scanf("%d",&S->Staff_Array[ret].Staff_Work_Note.Late_Number);
                break;
            }
            case 4:{
                printf("请输入更正后的早退次数\n");
                scanf("%d",&S->Staff_Array[ret].Staff_Work_Note.Early_Number);
                break;
            }
            case 5:{
                printf("请输入更正后的缺卡次数\n");
                scanf("%d",&S->Staff_Array[ret].Staff_Work_Note.Lack_Number);
                break;
            }
            case 6:{
                printf("请输入更正后的旷工次数\n");
                scanf("%d",&S->Staff_Array[ret].Staff_Work_Note.Absenteeism_Number);
                break;
            }
        }
    }
    else{
        printf("没有该员工信息\n");
    }
    Clear_Screen();
}

void Staff_Massege_Menu(struct Staff *S){
    int Choice = 0;
    Main_Menu();
    printf("1(添加员工)2(查找员工)\n3(删除员工)4(修改信息)\n");
    scanf("%d",&Choice);
    Clear_Screen();
    switch (Choice){
        case 1:{
            Add_Staff_Massege(S);
            break;
        }
        case 2:{
            Find_Staff_Massege(S);
            break;
        }
        case 3:{
            Delete_Staff_Massege(S);
            break;
        }
        case 4:{
            Modify_Staff_Massege(S);
            break;
        }
    }
}                    

void Morning_Punch_Clock(struct Staff *S){                                     
    int Staff_Number = 0;
    int Check_Number = 0;
    int ret = 0;
    Main_Menu(); 
    printf("请输入你的员工编号\n");
    scanf("%d",&Staff_Number);
    for (int i = 0; i < S->Size; i++){
        if (Staff_Number == S->Staff_Array[i].Staff_Number){
            ret = 1;
            if ('T' != S->Staff_Array[i].Staff_Work_Note.Start_Flag){
                printf("请输入你的效验码:\n");
                scanf("%d",&Check_Number);
                if (Check_Number == S->Staff_Array[i].Staff_Check_Number){
                    printf("打卡成功\n");
                    gettimeofday(&S->Staff_Array[i].Staff_Work_Note.Punch_StartTime,NULL);              //记录开工时间
                    S->Staff_Array[i].Staff_Work_Note.Start_Flag = 'T';                                 //上班打卡标记                                                    
                    if (9 < MT.Time){                                                                   //判断是否迟到 设置9点为标准上班时间
                        if ('T' == S->Staff_Array[i].Staff_Work_Note.Elasticity_Flag){
                            S->Staff_Array[i].Staff_Work_Note.Elasticity_Flag = 'F';
                        }
                        else{
                            printf("已迟到\n");
                            S->Staff_Array[i].Staff_Work_Note.Late_Number++;
                        }  
                    }
                    else{
                        S->Staff_Array[i].Staff_Work_Note.Elasticity_Flag = 'F';
                    }
                }
                else{
                    printf("效验码错误\n");
                }    
            }
            else{
                printf("今天上班已打卡\n");
                break;
            }            
        }
    }
    if (0 == ret){
        printf("没有该员工编号信息\n");
    }
    Clear_Screen();
}

void Night_Punch_Clock(struct Staff *S){
    int Staff_Number = 0;
    int ret = 0;
    Main_Menu();                                                          
    printf("请输入你的员工编号\n");                                                     
    scanf("%d",&Staff_Number);
    for (int i = 0; i < S->Size; i++){
        if (Staff_Number == S->Staff_Array[i].Staff_Number){
            ret = 1;
            if ('T' == S->Staff_Array[i].Staff_Work_Note.Start_Flag){
                printf("打卡成功\n");
                S->Staff_Array[i].Staff_Work_Note.End_Flag = 'T';
                gettimeofday(&S->Staff_Array[i].Staff_Work_Note.Punch_EndTime,NULL);
                S->Staff_Array[i].Staff_Work_Note.Work_Timeuse = (S->Staff_Array[i].Staff_Work_Note.Punch_EndTime.tv_sec - S->Staff_Array[i].Staff_Work_Note.Punch_StartTime.tv_sec)/Test_Proportion;
                S->Staff_Array[i].Staff_Work_Note.Week_Work_Timeuse += S->Staff_Array[i].Staff_Work_Note.Work_Timeuse;
                if(S->Staff_Array[i].Staff_Work_Note.Work_Timeuse < Standard_Worktime){
                    printf("今日早退:%.1f小时\n",Standard_Worktime - S->Staff_Array[i].Staff_Work_Note.Work_Timeuse); 
                    S->Staff_Array[i].Staff_Work_Note.Early_Number++;
                }
                if(S->Staff_Array[i].Staff_Work_Note.Work_Timeuse/Test_Proportion > Standard_Worktime + 3.0){
                    S->Staff_Array[i].Staff_Work_Note.Elasticity_Flag = 'T';
                }      
            }
            else{
                printf("打卡失败!员工%d今天还没有上班\n",Staff_Number);
                break;  
            }
        }
    }
    if (0 == ret){
        printf("没有该员工编号信息\n");
    }
    Clear_Screen();
}

void Machine_Record_Refresh(struct Staff *S){                              
    for (int i = 0; i < S->Size; i++){
        if ('T' == S->Staff_Array[i].Staff_Work_Note.Start_Flag){
            if ('T' != S->Staff_Array[i].Staff_Work_Note.End_Flag){
                S->Staff_Array[i].Staff_Work_Note.Lack_Number++;
            } 
        }
        else{
            S->Staff_Array[i].Staff_Work_Note.Absenteeism_Number++;
        }
    }
    for (int i = 0; i < S->Size; i++){
        S->Staff_Array[i].Staff_Work_Note.Start_Flag = 'F';
        S->Staff_Array[i].Staff_Work_Note.End_Flag = 'F';
    }
}

void Punch_Clock_List(struct Staff *S){                             
    Main_Menu();
    if (0 == S->Size)
    {
        printf("没有打卡记录\n");
    }
    else{
        for(int i=0;i<(S->Size);i++){
            printf("----------------------\n");
            printf("员工姓名:%s",S->Staff_Array[i].Name);
            printf("\t编号:%d",S->Staff_Array[i].Staff_Number);
            printf("\t性别:%s",S->Staff_Array[i].Sex);
            printf("\t年龄:%d\n",S->Staff_Array[i].Age);
            printf("电话:%ld",S->Staff_Array[i].Phone);
            printf("\t邮箱:%s\n",S->Staff_Array[i].Mailbox);
            printf("周均工作时长:%.1f",S->Staff_Array[i].Staff_Work_Note.Week_Work_Timeuse/5.0);
            printf("\t周迟到次数:%d",S->Staff_Array[i].Staff_Work_Note.Late_Number);
            printf("\t周早退次数:%d",S->Staff_Array[i].Staff_Work_Note.Early_Number);
            printf("\t周旷工次数:%d",S->Staff_Array[i].Staff_Work_Note.Absenteeism_Number);
            printf("\t周缺卡次数:%d\n",S->Staff_Array[i].Staff_Work_Note.Lack_Number);
        }  
    }
    Clear_Screen();
}

void Week_Reward_Punish(struct Staff *S){
    Main_Menu();
    if (0 == S->Size){
        printf("没有打卡记录\n");
    }
    else{
        for (int i = 0; i < S->Size; i++){
            if (0 == S->Staff_Array[i].Staff_Work_Note.Late_Number && 0 == S->Staff_Array[i].Staff_Work_Note.Early_Number && 0 == S->Staff_Array[i].Staff_Work_Note.Lack_Number && 0 == S->Staff_Array[i].Staff_Work_Note.Absenteeism_Number){
                printf("员工%s编号%d在本周工作中表现优秀\n",S->Staff_Array[i].Name,S->Staff_Array[i].Staff_Number);
            }
            if (0 != S->Staff_Array[i].Staff_Work_Note.Late_Number){
                printf("员工%s编号%d在本周工作中迟到%d次\n",S->Staff_Array[i].Name,S->Staff_Array[i].Staff_Number,S->Staff_Array[i].Staff_Work_Note.Late_Number);
            }
            if (0 != S->Staff_Array[i].Staff_Work_Note.Early_Number){
                printf("员工%s编号%d在本周工作中早退%d次\n",S->Staff_Array[i].Name,S->Staff_Array[i].Staff_Number,S->Staff_Array[i].Staff_Work_Note.Early_Number);
            }
            if (0 != S->Staff_Array[i].Staff_Work_Note.Lack_Number){
                printf("员工%s编号%d在本周工作中缺卡%d次\n",S->Staff_Array[i].Name,S->Staff_Array[i].Staff_Number,S->Staff_Array[i].Staff_Work_Note.Lack_Number);
            }
            if (0 != S->Staff_Array[i].Staff_Work_Note.Absenteeism_Number){
                printf("员工%s编号%d在本周工作中旷工%d次\n",S->Staff_Array[i].Name,S->Staff_Array[i].Staff_Number,S->Staff_Array[i].Staff_Work_Note.Absenteeism_Number);
            }
        }
    }
}

void Clear_Screen(){
    setbuf(stdin ,NULL);
    printf("\n请按下任意键继续......\n");
    getchar();
    system("clear");
    setbuf(stdin ,NULL);
}

void Clockin_Machine_Start(){
    srand((unsigned int)time(NULL));
    pthread_t Id;
    pthread_create(&Id,NULL,Clockin_Machine_Work,NULL);     //打卡机时间开始启动  
    Select_Menu();
}

main.c

#include<stdio.h>
#include<stdlib.h>
#include "../header/Punch_Clock_Machine.h"

int main(int argc, char const *argv[])
{
    Clockin_Machine_Start(); 
    return 0;
}

 

posted @ 2020-09-07 21:50  归江渡鸟泅白浪  阅读(34)  评论(0)    收藏  举报