打卡机核心功能实现(C语言)

任务分析

应市场需求,某工程师现设计了一款新上下班打卡机,打卡机具有以下功能:
(1)上班打卡,员工具有编号(首位为 1 的六位编号),输入编号后,再输入校验码,校验码生成规则:员工编号除首位反序,再与员工编号求和,如:员工编号,110086,校验码为 178087。校验码错误即打卡失败。记录打卡时间 。
(2)下班打卡,只需输入员工编号即可。记录打卡时间,显示该人员今天上班时长,如果上班时长不够,显示早退 xx 分钟。可以更新下班打卡时间。无下班打卡显示缺卡。
(3)可以设置规定上班时长,如 9 小时
(4)测试需要可以规定 6 秒=实际 1 小时,每次测试,输入指令后,开启打卡机,打卡机开启模拟时间为:周一早上七点。程序运行结束为周五晚 12 点。
(5)实行弹性打卡制,如前一天上班时长超过规定时长 3 小时以上,第二天迟到 2 小时以内不算迟到。
(6)打卡机运行结束之前,每周该打卡机会生成每周考勤周报,显示周平均上班时长,周迟到,早退,缺卡次数等。
要求:合理定义所需函数,主函数中只允许有 clockin_machine_start() 调用。

任务要求是主函数中只允许有clockin_machine_start()的调用,因此在主函数中仅进行该函数的调用,具体实现放在主函数外部。

int main()
{clockin_machine_start();return 0;
}

将任务划分为三个主要的模块,分别是员工上班打卡、下班打卡、时间统计与处理。

首先是员工上班打卡的实现,打卡所需的工作封装在ClockIn()函数中,该函数传入的参数含义分别为编号、验证码和编号长度,其中InitInfor()函数用于实现员工编号和验证码的录入,其中包括信息格式的判断,并通过CheckInfor(id, captcha, size)函数来判断录入的信息内容是否通过校验。

void ClockIn(char id[SIZE], char captcha[SIZE], int size)
{while(1){printf("Please input the id:>"); InitInfor(id, size);printf("Please input the code:>"); InitInfor(captcha, size);if(CheckInfor(id, captcha, size) == 0){printf("Ok! You've clocked in.'\n");break;}else if(CheckInfor(id, captcha, size) != 0){printf("Sorry, please input the right infor.\n");} }
}

第二部分是员工下班打卡,因为下班只需要输入员工编号,所以此时传入参数为员工编号和编号长度,将下班打卡时录入的信息与员工编号进行匹配,如果匹配成功,则打卡成功。

void ClockOut(char id[SIZE], int size)
{char id_buf[SIZE] = {'0'};while(1){printf("Please input the id:>");InitInfor(id_buf, size);if(memcmp(id_buf, id, size) == 0){printf("Ok! You've clocked out.\n");break;}else if(memcmp(id_buf, id, size) != 0){printf("Sorry, please input the right infor.\n");}}
}

第三部分为时间管理,通过time()函数来记录当前程序语句运行时的时间,通过对多个程序点的时间计算,完成员工上班工作时长、迟到、早退等信息的统计。

time_t clockin_time;
time(&clockin_time);

因为打卡机在周内要一直执行,此时就需要在每个阶段进行时间的获取及处理,但是在打卡机功能中,有这样一个需求,员工在每天工作结束后如果无下班打卡则记为缺卡,但是如果要实现该功能,则程序获取输入与程序统计时间就会产生矛盾,员工一直没有输入,则程序处于获取输入的阻塞状态中,那么时间就无法计算。
在Linux系统下可以通过以下方法解决此问题:(使用非阻塞IO)

#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>int flag1, flag2;
if(flag1 = fcntl(STDIN_FILENO, F_GETFL, 0) < 0)
{perror("fcntl");return -1;
}
flag2 = flag1 | O_NONBLOCK;
fcntl(STDIN_FILENO, F_SETFL, flag2);  //非阻塞// 执行动作fcntl(STDIN_FILENO, F_SETFL, flag1);  //阻塞

代码实现

clockin_machine.h

#ifndef __CLOCKIN_MACHINE_H__
#define __CLOCKIN_MACHINE_H__#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>#define SIZE 6  // bits of id
#define WEEKDAY 5  // weekday
#define ONEDAY 86400  // ONEDAY is 86400s long
#define TWOHOUR 7200  // TWOHOUR is 86400s long
#define THREEHOUR 10800  // THREEHOUR is 86400s long
#define ALL 0  // ALL is the first line of the time table, means working time
#define IN 1  // ALL is the second line of the time table, means clock_in time
#define OUT 2  // ALL is the third line of the time table, means clock_out timetime_t start_time;  // the machine start at 7 am Mon.
int open_time;  // clock_in time = 9 am
int close_time;  // clock_out time = 5 pm
int work_time[3][WEEKDAY];  // time table
int arrive_late;
int leave_early;void clockin_machine_start();
void BannerIn(int day);
void ClockIn(char id[SIZE], char captcha[SIZE], int size);
void InitInfor(char buf[SIZE], int size);
int CheckInfor(char id[SIZE], char captcha[SIZE], int size);
void BannerOut();
void ClockOut(char id[SIZE], int size);
void BannerFin(int day);
time_t reTime(time_t time);
void CountTime(time_t clockin_time, time_t clockout_time, int day);
void IsArriveLate(int day);
void IsLeaveEarly(int day);
int AverageTime(int weekday);
void DisplayCount(int ave_time, int arrive_late, int leave_early);#endif //__CLOCKIN_MACHINE_H__

main.c

#include "clockin_machine.h"int main()
{clockin_machine_start();return 0;
}

clockin_machine.c

#include "clockin_machine.h"void clockin_machine_start()
{time(&start_time);start_time = reTime(start_time);open_time = start_time + TWOHOUR; close_time = start_time + (10 * TWOHOUR);arrive_late = 0;leave_early = 0;int day = 0;do{char id[SIZE] = {'0'};  // the id of the employee char captcha[SIZE] = {'0'};  // identificationBannerIn(day);ClockIn(id, captcha, SIZE);  // clock intime_t clockin_time;time(&clockin_time);  // write down the time of clocking inclockin_time = reTime(clockin_time);  // change the form of the timeBannerOut();ClockOut(id, SIZE);  // clock out time_t clockout_time;time(&clockout_time);  // write down the time of clocking outclockout_time = reTime(clockout_time);  // change the form of the timeCountTime(clockin_time, clockout_time, day);  // count the worker's information all day  IsArriveLate(day);  // did the worker arrive late IsLeaveEarly(day);  // did the worker leave earlyBannerFin(day);day++; }while(day < WEEKDAY);int ave_time = AverageTime(WEEKDAY);DisplayCount(ave_time, arrive_late, leave_early);}void BannerIn(int day)
{switch(day+1){case 1:printf("Mon.\n");break;case 2:printf("Tue.\n");break;case 3:printf("Wed.\n");break;case 4:printf("Thur.\n");break;case 5:printf("Fri.\n");break;default:break;}printf("****************************************\n"); printf("------------please clock in-------------\n");
}void ClockIn(char id[SIZE], char captcha[SIZE], int size)
{while(1){printf("Please input the id:>"); InitInfor(id, size);printf("Please input the code:>"); InitInfor(captcha, size);if(CheckInfor(id, captcha, size) == 0){printf("Ok! You've clocked in.'\n");break;}else if(CheckInfor(id, captcha, size) != 0){printf("Sorry, please input the right infor.\n");} }}void InitInfor(char buf[SIZE], int size)
{int index = 0;char tmp;while((tmp=getchar()) != '\n'){buf[index] = tmp;index++;}if(index!=size || buf[0]!='1'){printf("Sorry, please input the right infor:>");InitInfor(buf, size);}
}int CheckInfor(char id[SIZE], char captcha[SIZE], int size)
{// if the code is right, retunr 0int i = 0;char tmp[size];strncpy(tmp, id, size);// Except for the first number of employees, sum up in reverse order for(i=1; i<size; i++){tmp[i] = (char)(((int)tmp[i])%48 + (int)id[size-i]); }return strcmp(tmp, captcha);
} void BannerOut()
{printf("------------please clock out------------\n");
}void ClockOut(char id[SIZE], int size)
{char id_buf[SIZE] = {'0'};while(1){printf("Please input the id:>");InitInfor(id_buf, size);if(memcmp(id_buf, id, size) == 0){printf("Ok! You've clocked out.\n");break;}else if(memcmp(id_buf, id, size) != 0){printf("Sorry, please input the right infor.\n");}}
}void BannerFin(int day)
{int hour = work_time[ALL][day] / 3600;int min = (work_time[ALL][day] - hour * 3600) / 60;printf("***************You worked%3dhour%3dmin**\n\n\n", hour, min);
}time_t reTime(time_t time)
{return time%ONEDAY;
}void CountTime(time_t clockin_time, time_t clockout_time, int day)
{work_time[ALL][day] = (clockout_time - clockin_time) * 10 * 60;work_time[IN][day] = clockin_time;work_time[OUT][day] = clockout_time;
}void IsArriveLate(int day)
{if(day > 0){if(work_time[OUT][day-1]-close_time >= THREEHOUR)//work hard last day {if(work_time[IN][day]-open_time <= TWOHOUR){}else if(work_time[IN][day]-open_time > TWOHOUR)// over two hours{arrive_late++;}}else if(work_time[OUT][day-1]-close_time < THREEHOUR)// did not work hard {if(work_time[IN][day] <= open_time){}else if(work_time[IN][day] > open_time)//arrive late{arrive_late++;}}}else if(day == 0) // if today is Mon.{if(work_time[IN][day] <= open_time){}else if(work_time[IN][day] > open_time)//arrive late{arrive_late++;}}
} void IsLeaveEarly(int day)
{if(work_time[OUT][day] >= close_time){}else if(work_time[OUT][day] < close_time){leave_early++;}
}int AverageTime(int weekday)
{int i = 0;int sum = 0;for(i=0; i<weekday; i++){sum = sum + work_time[ALL][i];}return sum/weekday;
}void DisplayCount(int ave_time, int arrive_late, int leave_early)
{int hour = ave_time / 3600;int min = (ave_time - hour * 3600) / 60;printf("vvvvvvvvvvvvv SUM vvvvvvvvvvvv\n");printf("··average time> %2dh%2dm\n", hour, min);printf("··arrive late > %dtimes\n", arrive_late);printf("··leave early > %dtimes\n", leave_early);
}

打卡机核心功能实现(C语言)相关推荐

  1. 关系数据库SQL语言核心功能

    SQL语言的功能极强,完成核心功能只要9个动词,分别为如下4类: 1. 数据查询:SELECT 说明:select是用于表信息查询,构成SQL唯一查询语句 2. 数据定义:CREATE.DROP.AL ...

  2. c语言蔬菜信息管理系统,蔬菜信息管理系统一般都有哪些核心功能?有什么好处?...

    古人云:"三日可无肉,日菜不可无",蔬菜使我们每天不可或缺的生鲜食材.随着信息化的不断发展,蔬菜等生鲜在管理上也逐渐与现代化接轨,蔬菜信息管理系逐渐取代了传统的人工管理模式,大行其 ...

  3. .NET gRPC核心功能初体验

    gRPC是高性能的RPC框架, 有效地用于服务通信(不管是数据中心内部还是跨数据中心). 由Google开源,目前是一个Cloud Native Computing Foundation(CNCF)孵 ...

  4. 史上最强Dubbo面试28题答案详解:核心功能+服务治理+架构设计等

    1.Dubbo是什么? Dubbo 是一个分布式.高性能.透明化的 RPC 服务框架,提供服务自动注册.自动发现等高效服务治理方案, 可以和 Spring 框架无缝集成. RPC 指的是远程调用协议, ...

  5. 大数据平台的3个核心功能

    导读:大数据平台可以分为操作数据存储(ODS).数据仓库(DW)和数据集市(DM)三层,分别对应着数据清洗.数据管理和数据应用这三个核心功能. 作者:蔡主希 来源:大数据DT(ID:hzdashuju ...

  6. Kubernetes-基本介绍/核心功能/相关术语(一)

    1 Kubernetes介绍 单词:Kubernetes这个单词起源于希腊语,意为舵手或领航员,K8S即为缩写,其中8代表了"ubernete"这8个字符. 来源:K8S前身是Go ...

  7. Cheat Enginee(CE)的详细使用指南~包含下载安装教程以及核心功能讲解

    Cheat Enginee(CE)的详细使用指南 Cheat Enginee(CE)的下载以及安装 首先:搜索并且进入官网,点击DownLoad按钮 选择下载路径:(根据自己计算机的实际情况进行下载) ...

  8. 实时计算 Flink SQL 核心功能解密

    2019独角兽企业重金招聘Python工程师标准>>> 实时计算 Flink SQL 核心功能解密 Flink SQL 是于2017年7月开始面向集团开放流计算服务的.虽然是一个非常 ...

  9. GitHub免费开放所有核心功能;告别纸币-央行牵头数字货币

    行 业 要 闻 Industry   News ▲▲▲ 0 1 一次登录,终身免费:GitHub宣布向所有人免费开放所有核心功能 每个私有库合作人数不设限,所有核心功能向所有人免费开放,这是 GitH ...

最新文章

  1. Mybatis是如何实现SQL语句复用功能的?
  2. Matplotlib图例中文乱码
  3. 1.12 四类向量组
  4. 全国计算机等级考试题库二级C操作题100套(第28套)
  5. 计算机硬盘共享配额,Win10磁盘配额是什么,怎么用?
  6. 各种移动GPU压缩纹理的使用方法
  7. 驱动拦截NT的API实现隐藏木马客户端
  8. usb3.0导入工具pe_BlackHat大会上,BlackBerry宣布开源逆向工具PE Tree
  9. JavaScript:字符串相关操作
  10. mysql dump 到的文件_MySQL用mysqldump命令导出文本文件
  11. bigemap 软件功能对比
  12. matlab单服务排队模型,MATLAB模拟银行单服务台排队模型
  13. thinkpad T500开机大于10分钟,黑屏
  14. vscode 未使用变量置灰
  15. 2021年4月程序员工资统计排行
  16. jquery实现歌词滚动
  17. 简单笔记(rsrp/mbps/session/dialog/dbm)
  18. 2021-3-22科研进展
  19. 谷歌浏览器双击打不开pdf问题
  20. 后缀表达式转中缀表达式

热门文章

  1. c盘文件被木马删怎么恢复?教你四步轻松找回文件!
  2. xp共享不同网络的win7计算机,win7和XP系统局域网共享电脑的操作方法【图】
  3. Hi Generator
  4. android7程序自启动管理在哪,开机启动管理最新版-开机启动管理软件下载v3.7.1 安卓版-腾牛安卓网...
  5. 毛绒玩具CPC认证,CPSC认证需要怎样申请
  6. angular4 环境变量配置
  7. docker ubuntu容器安装ping工具
  8. 【计算机毕业设计】汽车租赁管理系统
  9. vue实现word,pdf,xlsx文件下载
  10. Redis集群节点的变更