打卡机核心功能实现
程序员文章站
2024-01-03 09:07:46
...
C语言小项目—上下班打卡机(核心功能实现)
项目简介:
应市场需求,某工程师现设计了一款新上下班打卡机,打卡机具有以下功能:
(1) 上班打卡,员工具有编号(首位为 1 的六位编号),输入编号后,再
输入校验码,校验码生成规则:员工编号除首位反序,再与员工编号
求和,如:员工编号,110086,校验码为 178087。校验码错误即打
卡失败。记录打卡时间
(2) 下班打卡,只需输入员工编号即可。记录打卡时间,显示该人员今天
上班时长,如果上班时长不够,显示早退 xx 分钟。可以更新下班打
卡时间。无下班打卡显示缺卡。
(3) 可以设置规定上班时长,如 9 小时
(4) 测试需要可以规定 6 秒=实际 1 小时,每次测试,输入指令后,开启
打卡机,打卡机开启模拟时间为:周一早上七点。程序运行结束为周
五晚 12 点。
(5) 实行弹性打卡制,如前一天上班时长超过规定时长 3 小时以上,第
二天迟到 2 小时以内不算迟到。
(6) 打卡机运行结束之前,每周该打卡机会生成每周考勤周报,显示周平
均上班时长,周迟到,早退,缺卡次数等。
任务过程:
1、创建项目
2、合理定义所需函数,主函数中只允许有 clockin_machine_start()调用
3、按照任务概述实现函数流程
4、调试修改
测试及部分代码:
一、上班时长设置
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include "Global.h"
void ClockIn_machine_start();
void ClockIn();
void ClockOut();
int Check();
void ReHours();
void UpDateTime(int pattern);
void WeekChart(int day, int duringTime);
int number; //员工编号
int pattern = 1; //打卡模式(1为上班打卡,2为下班打卡)
int startTimes[5] = { 0 }; //上班打卡次数限制(每日1次)
int stopTimes[5] = { 0 }; //下班打卡次数限制(每日3次,允许误打)
clock_t openTime, insert, start, stop;
long duration; //打卡持续时长
int officeHours = 9; //上班时间,默认为9小时
int day = 0; //打卡日期
int hour; //打卡当天时间(时)
int minute; //打卡当天时间(分)
int duringTime; //实际上班时间
int times_1 = 0; //迟到次数
int times_2 = 0; //早退次数
int times_3 = 0; //缺卡次数
int chart[5] = { 0 };
int main(int argv, char *argc[]) {
ClockIn_machine_start();
system("PAUSE");
return 0;
}
void ClockIn_machine_start()
{
//规定上班时间
ReHours();
while (1)
{
//打卡模式选择
printf("\n***************************************************************\n\n");
printf(" 1.上班打卡\n");
printf(" 2.下班打卡\n");
printf(" 3.当前时间\n");
printf("\n***************************************************************\n\n");
printf("输入“3”可获取当前时间\n输入“1”或“2”进行打卡模式选择:\n");
scanf_s("%d", &pattern);
if (pattern == 1)
{
if (startTimes[day] == 0) {
//上班打卡
ClockIn();
}
else
{
printf("请勿在一天中重复上班打卡\n");
UpDateTime(0);
}
}
else if (pattern == 2)
{
if (stopTimes[day] < 3) {
//下班打卡
ClockOut();
}
else
{
printf("今日下班打卡次数已达上线\n");
UpDateTime(0);
}
}
else if (pattern == 3)
{
//显示当前时间
UpDateTime(0);
}
else
{
printf("打卡失败,请输入正确的指令!!!\n");
}
}
}
void ReHours()
{
printf("***************************************************************");
printf("\n\n 上班时长设置\n");
printf("\n***************************************************************\n\n");
char reFlag = 'n';
printf("是否自定义上班时长(默认上班时长为 9 小时) [Y/n]\n");
reFlag = getchar();
if (reFlag == 'Y' || reFlag == 'y')
{
printf("设置上班时长:\n");
scanf_s("%d", &officeHours);
}
printf("打卡机开启\n");
openTime = clock(); //设置好打卡时长后,打卡机开启
}
二、上班打卡
void ClockIn()
{
printf("\n***************************************************************");
printf("\n\n 上班打卡");
printf("\n");
printf("\n***************************************************************\n\n");
int checkFlag = 0;
//效验编号
checkFlag = Check();
if (checkFlag)
{
int checkNumber;
int tempNumber;
int times = 0;
checkNumber = number + number % 10 * 10000 + (number % 100 - number % 10) * 100
+ (number % 1000 - number % 100) + number % 10000 / 1000 * 10 + number % 100000 / 10000;
printf("效验码:%d\n", checkNumber);
printf("请输入上述效验码:\n");
scanf_s("%d", &tempNumber);
if (tempNumber == checkNumber)
{
printf("上班打卡成功!!!\n");
startTimes[day] += 1; //当日上班打卡次数加 1
UpDateTime(pattern);
times = 0;
return;
}
else
{
do {
times++;
printf("效验码错误,请重新输入效验码:%d\n", checkNumber);
scanf_s("%d", &tempNumber);
if (tempNumber == checkNumber)
{
printf("上班打卡成功!!!\n");
startTimes[day] += 1;
UpDateTime(pattern);
times = 0;
return;
}
} while (times < 3);
if (times == 3)
{
printf("错误次数过多,请重新打卡\n");
times = 0;
return;
}
}
checkFlag = 0;
}
return;
}
每日仅支持一次上班打卡
上班打卡迟到记录
三、下班打卡
void ClockOut()
{
printf("\n***************************************************************");
printf("\n\n 2.下班打卡");
printf("\n");
printf("\n***************************************************************\n\n");
int tempNumber;
printf("请输入您的编号:\n");
scanf_s("%d", &tempNumber);
while (1)
{
if (number == tempNumber)
{
printf("下班打卡成功!!!\n");
UpDateTime(pattern);
stopTimes[day] += 1; //当日下班打卡次数加 1
break;
}
else
{
printf("请先进行上班打卡\n");
break;
}
}
}
下班打卡早退记录
每日允许三次下班误打卡
四、弹性打卡
计时部分代码
void UpDateTime(int pattern_1)
{
insert = clock();
duration = (insert - openTime) / CLOCKS_PER_SEC; //将时间转换为秒
hour = (7 + duration / 6) % 24;
minute = (int)(duration / 6.0 * 60) % 60;
printf("当前时间: ");
if (duration / 6 < 17)
{
day = 0;
}
else
{
day = 1 + (duration / 6 - 17) / 24;
}
switch (day % 5)
{
case 0:
printf("星期一");
break;
case 1:
printf("星期二");
break;
case 2:
printf("星期三");
break;
case 3:
printf("星期四");
break;
case 4:
printf("星期五");
break;
}
printf(" %d : %d\n", hour, minute);
if (pattern_1 == 1)
{
start = clock();
if (hour > 9)
{
printf("上班打卡迟到\n");
times_1++;
if (hour - 9 <= 2 && day != 0)
{
if (chart[day - 1] > (3 + officeHours) * 60)
{
times_1--;
printf("但由于昨日超时长工作,今日上班迟到撤销\n");
}
}
}
}
else if (pattern_1 == 2)
{
stop = clock();
duringTime = (stop - start) / CLOCKS_PER_SEC; //将时间转换为秒
if (duringTime / 6 * 60 + minute < officeHours * 60)
{
printf("今日上班时长: %d小时%d分钟\n", duringTime / 6, minute);
printf("早退 %d分钟\n", officeHours * 60 - duringTime / 6 * 60 - minute);
times_2++;
}
if (stopTimes[day] > 0)
{
times_2--; //允许误打卡,一天中多次打卡则减去累加的早退次数
}
WeekChart(day, duringTime);
}
}
五、周日报测试(周五下班后自动生成周日报,显示周平均上班时长,周迟到、早退、缺卡次数)
void WeekChart(int day, int duringTime_1)
{
chart[day] = (int)(duringTime_1 / 6.0 * 60);
if (day == 4)
{
printf("本周打卡结束,生成周报表\n\n");
for (int i = 0; i < 5; i++)
{
switch (i)
{
case 0:
printf("星期一 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 1:
printf("星期二 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 2:
printf("星期三 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 3:
printf("星期四 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 4:
printf("星期五 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
}
}
int sum = 0;
for (int j = 0; j < 5; j++)
{
sum += chart[j];
}
printf("周平均上班时长: %d分钟\n", sum / 5);
printf("迟到次数: %d\n", times_1);
printf("早退次数: %d\n", times_2);
printf("缺卡次数: %d\n", times_3);
}
}
完整代码(欢迎各位在评论区交流)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include "Global.h"
void ClockIn_machine_start();
void ClockIn();
void ClockOut();
int Check();
void ReHours();
void UpDateTime(int pattern);
void WeekChart(int day, int duringTime);
int number; //员工编号
int pattern = 1; //打卡模式(1为上班打卡,2为下班打卡)
int startTimes[5] = { 0 }; //上班打卡次数限制(每日1次)
int stopTimes[5] = { 0 }; //下班打卡次数限制(每日3次,允许误打)
clock_t openTime, insert, start, stop;
long duration; //打卡持续时长
int officeHours = 9; //上班时间,默认为9小时
int day = 0; //打卡日期
int hour; //打卡当天时间(时)
int minute; //打卡当天时间(分)
int duringTime; //实际上班时间
int times_1 = 0; //迟到次数
int times_2 = 0; //早退次数
int times_3 = 0; //缺卡次数
int chart[5] = { 0 };
int main(int argv, char *argc[]) {
ClockIn_machine_start();
system("PAUSE");
return 0;
}
void ClockIn_machine_start()
{
//规定上班时间
ReHours();
while (1)
{
//打卡模式选择
printf("\n***************************************************************\n\n");
printf(" 1.上班打卡\n");
printf(" 2.下班打卡\n");
printf(" 3.当前时间\n");
printf("\n***************************************************************\n\n");
printf("输入“3”可获取当前时间\n输入“1”或“2”进行打卡模式选择:\n");
scanf_s("%d", &pattern);
if (pattern == 1)
{
if (startTimes[day] == 0) {
//上班打卡
ClockIn();
}
else
{
printf("请勿在一天中重复上班打卡\n");
UpDateTime(0);
}
}
else if (pattern == 2)
{
if (stopTimes[day] < 3) {
//下班打卡
ClockOut();
}
else
{
printf("今日下班打卡次数已达上线\n");
UpDateTime(0);
}
}
else if (pattern == 3)
{
//显示当前时间
UpDateTime(0);
}
else
{
printf("打卡失败,请输入正确的指令!!!\n");
}
}
}
void ReHours()
{
printf("***************************************************************");
printf("\n\n 上班时长设置\n");
printf("\n***************************************************************\n\n");
char reFlag = 'n';
printf("是否自定义上班时长(默认上班时长为 9 小时) [Y/n]\n");
reFlag = getchar();
if (reFlag == 'Y' || reFlag == 'y')
{
printf("设置上班时长:\n");
scanf_s("%d", &officeHours);
}
printf("打卡机开启\n");
openTime = clock(); //设置好打卡时长后,打卡机开启
}
void ClockIn()
{
printf("\n***************************************************************");
printf("\n\n 上班打卡");
printf("\n");
printf("\n***************************************************************\n\n");
int checkFlag = 0;
//效验编号
checkFlag = Check();
if (checkFlag)
{
int checkNumber;
int tempNumber;
int times = 0;
checkNumber = number + number % 10 * 10000 + (number % 100 - number % 10) * 100
+ (number % 1000 - number % 100) + number % 10000 / 1000 * 10 + number % 100000 / 10000;
printf("效验码:%d\n", checkNumber);
printf("请输入上述效验码:\n");
scanf_s("%d", &tempNumber);
if (tempNumber == checkNumber)
{
printf("上班打卡成功!!!\n");
startTimes[day] += 1; //当日上班打卡次数加 1
UpDateTime(pattern);
times = 0;
return;
}
else
{
do {
times++;
printf("效验码错误,请重新输入效验码:%d\n", checkNumber);
scanf_s("%d", &tempNumber);
if (tempNumber == checkNumber)
{
printf("上班打卡成功!!!\n");
startTimes[day] += 1;
UpDateTime(pattern);
times = 0;
return;
}
} while (times < 3);
if (times == 3)
{
printf("错误次数过多,请重新打卡\n");
times = 0;
return;
}
}
checkFlag = 0;
}
return;
}
int Check()
{
//首先录入员工编号
printf("请输入您的编号:\n");
scanf_s("%d", &number);
int i = 0;
//判断员工编号输入是否正确
while (number / 100000 != 1)
{
i++;
printf("编号输入有误,请重新输入\n");
scanf_s("%d", &number);
if (number / 100000 == 1)
{
i = 0;
return 1;
}
else if (i > 2)
{
printf("编号输入错误次数过多,打卡失败\n");
i = 0;
return 0;
}
}
return 1;
}
void ClockOut()
{
printf("\n***************************************************************");
printf("\n\n 2.下班打卡");
printf("\n");
printf("\n***************************************************************\n\n");
int tempNumber;
printf("请输入您的编号:\n");
scanf_s("%d", &tempNumber);
while (1)
{
if (number == tempNumber)
{
printf("下班打卡成功!!!\n");
UpDateTime(pattern);
stopTimes[day] += 1; //当日下班打卡次数加 1
break;
}
else
{
printf("请先进行上班打卡\n");
break;
}
}
}
void UpDateTime(int pattern_1)
{
insert = clock();
duration = (insert - openTime) / CLOCKS_PER_SEC; //将时间转换为秒
hour = (7 + duration / 6) % 24;
minute = (int)(duration / 6.0 * 60) % 60;
printf("当前时间: ");
if (duration / 6 < 17)
{
day = 0;
}
else
{
day = 1 + (duration / 6 - 17) / 24;
}
switch (day % 5)
{
case 0:
printf("星期一");
break;
case 1:
printf("星期二");
break;
case 2:
printf("星期三");
break;
case 3:
printf("星期四");
break;
case 4:
printf("星期五");
break;
}
printf(" %d : %d\n", hour, minute);
if (pattern_1 == 1)
{
start = clock();
if (hour > 9)
{
printf("上班打卡迟到\n");
times_1++;
if (hour - 9 <= 2 && day != 0)
{
if (chart[day - 1] > (3 + officeHours) * 60)
{
times_1--;
printf("但由于昨日超时长工作,今日上班迟到撤销\n");
}
}
}
}
else if (pattern_1 == 2)
{
stop = clock();
duringTime = (stop - start) / CLOCKS_PER_SEC; //将时间转换为秒
if (duringTime / 6 * 60 + minute < officeHours * 60)
{
printf("今日上班时长: %d小时%d分钟\n", duringTime / 6, minute);
printf("早退 %d分钟\n", officeHours * 60 - duringTime / 6 * 60 - minute);
times_2++;
}
if (stopTimes[day] > 0)
{
times_2--; //允许误打卡,一天中多次打卡则减去累加的早退次数
}
WeekChart(day, duringTime);
}
}
void WeekChart(int day, int duringTime_1)
{
chart[day] = (int)(duringTime_1 / 6.0 * 60);
if (day == 4)
{
printf("本周打卡结束,生成周报表\n\n");
for (int i = 0; i < 5; i++)
{
switch (i)
{
case 0:
printf("星期一 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 1:
printf("星期二 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 2:
printf("星期三 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 3:
printf("星期四 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
case 4:
printf("星期五 ");
if (chart[i])
{
printf("打卡时长:%d分钟\n", chart[i]);
}
else
{
printf("缺卡\n");
times_3++;
}
break;
}
}
int sum = 0;
for (int j = 0; j < 5; j++)
{
sum += chart[j];
}
printf("周平均上班时长: %d分钟\n", sum / 5);
printf("迟到次数: %d\n", times_1);
printf("早退次数: %d\n", times_2);
printf("缺卡次数: %d\n", times_3);
}
}