打卡机核心功能实现:
应市场需求,某工程师现设计了一款新上下班打卡机,打卡机具有以下功能:
(1) 上班打卡,员工具有编号(首位为 1 的六位编号),输入编号后,再 输入校验码,校验码生成规则:员工编号除首位反序,再与员工编号 求和,如:员工编号,110086,校验码为 178087。校验码错误即打 卡失败。记录打卡时间
(2) 下班打卡,只需输入员工编号即可。记录打卡时间,显示该人员今天上班时长,如果上班时长不够,显示早退 xx 分钟。可以更新下班打卡时间。无下班打卡显示缺卡。
(3) 可以设置规定上班时长,如 9 小时
(4) 测试需要可以规定 6 秒=实际 1 小时,每次测试,输入指令后,开启 打卡机,打卡机开启模拟时间为:周一早上七点。程序运行结束为周五晚 12 点。
(5) 实行弹性打卡制,如前一天上班时长超过规定时长 3 小时以上,第 二天迟到 2 小时以内不算迟到。
(6) 打卡机运行结束之前,每周该打卡机会生成每周考勤周报,显示周平 均上班时长,周迟到,早退,缺卡次数等。
我的代码:
问题:
<time.h>中的计时函数clock() 经测试发现该计时方法不准
改用<.ctime>中的gettimeofday()实现,因此虽然是c代码,程序的后缀名需要为*.cpp
to do:
1.bug
在do while循环中第一次循环,time等于设定的初值7,因此第一次打卡的时间始终为早上七点,
此处必须刷新一次,即输入1或2之外的其他值,使其结束第一次循环,此时打卡为正确时间。
2.多员工打卡
思路:对于多个员工的打卡,已经定义了staff的结构体,考虑输入员工id时与struct中的id进行对比,返回对应的struct指针,完成id和员工的匹配。
struct staff{
char id[7];
timeval in_time;
timeval out_time;
double workhour_count = 0;//mytimer1(in_time,out_time);
int late_count = 0;//迟到
int absence_count = 0;//缺勤
int leave_early_count = 0;//早退
int check1 = 0;//正常上班打卡check
int check2 = 0;//不正常上班打卡check
int check3 = 0;//不正常下班打卡check
int check4 = 0;//正常下班打卡check
int check5 = 0;//弹性打卡check
};
3.优化
冗余的一些代码可以写成函数,比如打印时间
printf("工作时间\n");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
printf("输入1上班打卡,输入2下班打卡,输入其他刷新\n");
全部代码如下
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
//clock_t start_time1;
//clock_t end_time1;
#define WORKDAY 3
//#define WORKHOUR 9
#define PROGRAMSTARTTIME 7.0 //程序开始时间为周一早上7点
#define WORKSTARTTIME 9 //上班时间
#define WORKENDTIME 18 //下班时间
//用于程序测试
#define HOUR_PER_SECOND 1 //测试时以2s表示一个小时
#define DAY_PER_HOUR 24 //测试时以24h表示一天
timeval program_start_time;
timeval program_end_time;
int date_count_hour=0,date_count_day = 0;
struct staff{
char id[7];
timeval in_time;
timeval out_time;
double workhour_count = 0;//mytimer1(in_time,out_time);
int late_count = 0;//迟到
int absence_count = 0;//缺勤
int leave_early_count = 0;//早退
int check1 = 0;//正常上班打卡check
int check2 = 0;//不正常上班打卡check
int check3 = 0;//不正常下班打卡check
int check4 = 0;//正常下班打卡check
int check5 = 0;//弹性打卡check
};
staff staff1,staff2,staff3;
void log_in()
{
strcpy(staff1.id,"123456");
strcpy(staff2.id,"110086");
strcpy(staff3.id,"168001");
}
void printStaff(struct staff staffx)
{
printf( "Staff id : %s\n", staffx.id);
printf( "Average work time : %.2f\n",staffx.workhour_count/WORKDAY);
printf( "Late : %d\n", staffx.late_count);
printf( "Absence : %d\n", staffx.absence_count);
printf( "Learly Leave : %d\n", staffx.leave_early_count);
}
//计时函数clock() 经测试发现该计时方法不准
/*
void mytimer(clock_t start_time1,clock_t end_time1)
{
start_time=clock(); //程序开始计时
int ans=0;
for(int i=1;i<=1e8;i++)
ans++;
end_time=clock(); //程序结束用时
double total_time=(double)(end_time1-start_time1)/CLOCKS_PER_SEC;
cout<<"Total time:"<<total_time<<"s"<<endl; //s为单位
cout<<"Total time:"<<total_time*1000<<"ms"<<endl; //ms为单位
//system("pause");
};
*/
//计时函数gettimeofday
double mytimer1(timeval start_time,timeval end_time)
{
//timeval start_time, end_time;
//gettimeofday(&start_time, NULL);
//gettimeofday(&end_time, NULL);
double second = (end_time.tv_sec - start_time.tv_sec) +
(end_time.tv_usec - start_time.tv_usec)/1e6;
//1秒一个小时,24小时一天
date_count_hour = second / HOUR_PER_SECOND;
date_count_day = date_count_hour / DAY_PER_HOUR ;
return date_count_hour;
};
//判断编号是否符合规范
//及匹配到人to do
int judge_Verification(char *p)
{
char s[7]={0};
strcpy(s,p);
int i = strlen(s);
if(i==6 && s[0]=='1')
{
printf("员工编号正确\n");
return 1;
}
else
{
printf("员工编号错误\n");
return 0;
}
};
//校验码检查函数
int Verification(char *p1,char *p2)
{
char s[7];
for(int i=0;i<6;i++)
{
s[i] = *p1;
}
//s数组反序
for(int i=1;i<6;i++)
{
s[i]=*(p1+6-i);
}
//新数组
for(int i=1;i<6;i++)
{
//ASCII码 数字'0'编号为48,减48或'0'
s[i]+=*(p1+i)-'0';
}
if(strcmp(s,p2)==0) return 1;
else return 0;
};
void clock_in(double time_cpy) //上班打卡
{
int flag = 1;
char number[7] = {0};
while(flag)
{
printf("请输入员工编号\n");
gets(number);
if(judge_Verification(number))
{
flag = 0;
}
//else judge_Verification();
}
char check[7] = {0};
flag = 1;
while(flag)
{
printf("请输入校验码\n");
gets(check);
if(Verification(number,check))
{
flag = 0,printf("上班打卡成功\n\n");
gettimeofday(&staff1.in_time, NULL);
if(staff1.check5 == 1)
{
//弹性打卡
if(time_cpy<WORKSTARTTIME+2) staff1.check1 = 1;
else if(time_cpy>WORKSTARTTIME+2 && time_cpy<WORKENDTIME) staff1.check2 = 1;
staff1.check5 = 0;
}
else
{
if(time_cpy<WORKSTARTTIME) staff1.check1 = 1;//正常上班
else if(time_cpy>WORKSTARTTIME && time_cpy<WORKENDTIME) staff1.check2 = 1;//迟到
}
}
else printf("校验码错误\n\n");
}
}
void clock_out(double time_cpy) //下班打卡
{
char number[7] = {0};
int flag = 1;
while(flag)
{
printf("请输入员工编号\n");
gets(number);
if(judge_Verification(number))
{
flag = 0;
}
//else judge_Verification();
}
printf("下班打卡成功\n\n");\
if(time_cpy>WORKSTARTTIME && time_cpy<WORKENDTIME) staff1.check3 = 1;
else if(time_cpy>WORKENDTIME) staff1.check4 = 1;
gettimeofday(&staff1.out_time, NULL);
staff1.workhour_count += mytimer1(staff1.in_time,staff1.out_time);
}
void clockin_machine_start() //打卡机
{
//开启打卡机
printf("输入1开启打卡机\n");
int flag = 1;
while(flag)
{
char s = getchar();
char ss = getchar();//存入换行符
if(s == '1')
{
flag = 0;
printf("打卡机已开启\n");
gettimeofday(&program_start_time, NULL);
}
else printf("指令错误,输入1开启打卡机\n");
}
log_in();
//start_time1 = clock();
//程序总的运行时间
double time = PROGRAMSTARTTIME;//存在bug,第一次打卡的时间始终为早上七点,此处必须刷新一次即输入3,再打卡为正确时间
do{
//所有时间单位为h
int time_cpy = (int)time % DAY_PER_HOUR;//打卡机当前时间
int time_cpy2 = time / DAY_PER_HOUR;//打卡机工作了几天
while(time_cpy<=WORKSTARTTIME)
{
//上班打卡
printf("上班时间\n");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
//记录每个人的上班打卡时间,并且令check1 = 1
//若该段时间没有打卡,check1 = 0
printf("输入1上班打卡,输入2下班打卡,输入其他刷新\n");
char s = getchar();
char ss = getchar();//存入换行符
switch (s)
{
case '1':{
printf("上班打卡\t");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
clock_in(time_cpy);
break;
}
case '2':{
printf("该时间无法下班打卡\n");
break;
}
default:{
printf("\n");break;
}
}
break;
}
while(time_cpy>WORKSTARTTIME && time_cpy<WORKENDTIME)
{
printf("工作时间\n");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
printf("输入1上班打卡,输入2下班打卡,输入其他刷新\n");
char s = getchar();
char ss = getchar();//存入换行符
switch (s)
{
case '1':{
printf("上班打卡\t");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
clock_in(time_cpy);
break;
}
case '2':{
printf("下班打卡\t");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
clock_out(time_cpy);
break;
}
default:{
printf("\n");break;
}
}
//若check1 == 0,该时间段打卡,则为迟到
if(staff1.check2 ==1) staff1.late_count += 1;
//若check1 == 0,该时间段未打卡,在下班时间后记录为缺勤
//若check1 == 1,该时间段打卡记为早退
if(staff1.check1 == 1 && staff1.check3 == 1) staff1.leave_early_count += 1;
break;
}
while(time_cpy>=WORKENDTIME)
{
printf("下班时间\n");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
//记录缺勤
if(staff1.check1 == 0 && staff1.check2 ==0) staff1.absence_count += 1;
//下班打卡时间
printf("输入1上班打卡,输入2下班打卡,输入其他刷新\n");
char s = getchar();
char ss = getchar();//存入换行符
switch (s)
{
case '1':{
printf("当前无法上班打卡\t");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
break;
}
case '2':{
printf("下班打卡\t");
printf("当前时间:周%d, %d点\n",time_cpy2+1,time_cpy);
clock_out(time_cpy);
break;
}
default:{
printf("\n");break;
}
}
break;
}
//每经过一天的操作
while(time_cpy2>1)
{
//忘记下班打卡,记录为缺勤
if((staff1.check1 == 1 || staff1.check2 == 1) && staff1.check3 == 0 && staff1.check4 == 0)
{
staff1.workhour_count += 0;
staff1.absence_count += 1;
}
//状态归零
staff1.check1 = 0;
staff1.check2 = 0;
staff1.check3 = 0;
staff1.check4 = 0;
//弹性打卡制,若前一天上班时长超过规定时长3小时以上,第二天迟到2小时以内不算迟到
if(mytimer1(staff1.in_time,staff1.out_time)-3>=(WORKSTARTTIME-WORKENDTIME))
{
staff1.check5 = 1;
}
break;
}
gettimeofday(&program_end_time, NULL);
time = mytimer1(program_start_time,program_end_time) + PROGRAMSTARTTIME;
}while(time < DAY_PER_HOUR * WORKDAY);
//打印员工的打卡信息
printStaff(staff1);
//printStaff(staff2);
//printStaff(staff3);
}
int main()
{
clockin_machine_start();
return 0;
}
其它问题
编写博客的时候发现的问题
输入的ctime显示不出来
原因:所有“< >"之间的内容都会被默认被HTML的标签而不予显示。此时,就需要使用转义字符以示区别, " <“使用”<“代替,而”>“则使用”>"代替
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLzMzN5IzN0AjMxEDOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)