打卡机核心功能实现(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);