用c写打卡机:实现上下班打卡和考勤等功能

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

首先打码需要包含头文件:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

声明函数:

//声明函数
int start();//判断是否为工作时间,是则开启打卡机,否则关闭
void gettime();//获得上班时间
void show();//展示上班时间
void gettime_back();//得到下班时间
void show_back();//展示下班时间

定义一个结构体,保存用户的信息:

struct member {
	int number2;//员工编号
	int check_code_right;//校验码
	int hour;//上班时间
	int minute;
	int sec;
	int hour_back;//下班时间
	int minute_back;
	int sec_back;
}member1;

定义缓冲变量、工作时间、迟到次数、早退次数、缺卡次数的全局变量:

static double working_time;
static int timelate,leave_early,lack_punch_card;
static int buffer_mechanism;

打卡机开始程序:

void clockin_machine_start()
{
	//调用start()函数,判断是否为工作日,否则退出程序
	if(start() == 0)
	{
		printf("现在是休息时间!\n");
		exit(0);
	}
	//要求用户输入员工编号保存在number变量中
	printf("请输入员工编号:\n");
	int number = 0;
	scanf("%d",&number);
	//将传入的变量number的值传递给结构体中的员工编号
	member1.number2 = number;
	//完成对员工编号的处理得到校验码
	int number1 = number - 100000;
	int tmp = 0;
	while(number1 != 0)
	{
		tmp = tmp * 10 + number1 % 10;
		number1 = number1 / 10;
	}
	int check_code_right = number + tmp;
	//将得到的校验码传给结构体
	member1.check_code_right = check_code_right;
	//要求用户输入自己的校验码
	printf("请输入校验码:(方便调试,1秒钟等于1小时)\n");
	int check_code = 0;
	scanf("%d",&check_code);
	//当校验码错误的时候,循环要求用户重新输入
	while(check_code_right != check_code)
	{
		printf("校验码错误,请重新输入\n");
		scanf("%d",&check_code);
	}
	printf("正确!\n");
	printf("---------------------------------\n");
	//获取当前上班时间,并传递给结构体
	gettime();
	//向用户展示当前上班时间和是否迟到
	show();
	printf("---------------------------------\n");
	//下班要求用户输入员工编号完成打卡
	printf("下班请打卡:\n");
	printf("请输入员工编号:\n");
	int number_back = 0;
	//先获取一次员工编号,判断是否与之前输入的相等,若不相等则重新要求用户输入
	do
	{
		scanf("%d",&number_back);
		if(number_back != number)
			printf("请重新输入!\n");
	}while(number_back != number);
	//获取下班时间,并传递给结构体
	gettime_back();
	//若没有下班时间,则显示缺卡,且缺卡次数加一,否则显示下班时间、当天的工作时长、是否实行缓冲机制
	if(member1.hour_back == 0){
		printf("缺卡!\n");
		lack_punch_card++;
	}
	else{
		show_back();
	}
	printf("---------------------------------\n");
}

开始函数,判断是否为工作日:

int start()
{
	//时间函数,获取电脑本地时间
	time_t t;
	struct tm* It;
	time(&t);
	It = localtime(&t);
	//若不是星期六(6)或者星期天(0),再判断时间是否大于7点,若是,则返回1,函数继续往下执行,若返回0,则程序退出
	int wday = It->tm_wday;
	int hour = It->tm_hour;
	if(wday != 0 && wday != 6)
	{
		if(hour >= 7)
		{
			return 1;
		}
		return 0;
	}
	return 0;
}

获取上班时间:

void gettime()
{
	//获取上班时间
	time_t t;
	struct tm* It;
	time(&t);
	It = localtime(&t);
	//将时间传递给结构体
	member1.hour = It->tm_hour;
	member1.minute = It->tm_min;
	member1.sec = It->tm_sec;
	//展示当前时间
	printf("当前时间:%d年%d月%d日 星期%d %d:%d:%d\n",(1900 + It->tm_year),(1 + It->tm_mon),It->tm_mday,It->tm_wday,It->tm_hour, It->tm_min, It->tm_sec);
}

打印上班时间:


void show()
{
	//展示员工编号和上班时间
	printf("员工编号:%d\n",member1.number2);
	printf("上班时间:%d:%d:%d\n",member1.hour,member1.minute,member1.sec);
	//上班时间为7点前,在7点到9点之间属于迟到,9点后属于缺卡
	//如果触发了缓冲机制,则判断上班时间是不是迟到两小时内
	if(member1.hour >= 9)
	{
		printf("上午缺卡\n");
		lack_punch_card++;
	}
	else if(member1.hour < 9 && member1.hour >= 7)
	{
		printf("您迟到了!\n");
		timelate++;
	}
	else if(member1.hour < 9 && member1.hour >= 7 && huanchong == 1)
	{
		printf("上班打卡成功!\n");
	}
	else
	{
		printf("上班打卡成功!\n");
	}
	buffer_mechanism = 0}

获取下班时间:

void gettime_back()
{
	//获取下班时间
	time_t t2;
	struct tm* ti;
	time(&t2);
	ti = localtime(&t2);
	//下班时间传递给结构体
	//member1.hour_back = ti->tm_hour;
	member1.minute_back = ti->tm_min;
	member1.sec_back = ti->tm_sec;
	//方便调试,一秒钟等于一小时
	if(ti->tm_sec < member1.sec)
	{
		ti->tm_sec += 60;
	}
	member1.hour_back = ti->tm_hour + ((ti->tm_sec - member1.sec));
	printf("---------------------------------\n");
	//展示当前时间
	printf("当前时间:%d年%d月%d日 星期%d %d:%d:%d\n",(1900 + ti->tm_year),(1 + ti->tm_mon),ti->tm_mday,ti->tm_wday,ti->tm_hour,ti->tm_min, ti->tm_sec);
}

打印下班时间:

void show_back()
{
	if(member1.hour_back >= 24)
	{
		member1.hour_back = member1.hour_back - 24;
	}
	//展示员工编号,下班时间,打卡成功
	printf("员工编号:%d\n",member1.number2);
	printf("下班时间:%d:%d:%d\n",member1.hour_back , member1.minute_back , member1.sec_back);
	printf("打卡成功!\n");
	//累计每天的上班时间,在周报里展示
	worktime += (member1.hour_back - member1.hour)*60 + (member1.minute_back - member1.minute);
	//上班时长为9小时
	int time = 9;
	//获得用户上班时长
	int tmp = member1.hour_back - member1.hour;
	switch(tmp){
		//上班时长为0\1\2\3\4\5\6\7小时的用户
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
			//上班时间刚好为n小时
			if(member1.minute_back == member1.minute)
			{
				printf("早退:%d小时%d分钟\n",(time - (member1.hour_back - member1.hour)),0);
			}
			//上班时间不足n小时
			else if(member1.minute_back < member1.minute)
			{
				printf("早退:%d小时%d分钟\n",time - (member1.hour_back - member1.hour),member1.minute - member1.minute_back);
			}
			//上班时间超过n小时,但不足n+1小时
			else
			{
				printf("早退:%d小时%d分钟\n",(time - (member1.hour_back - member1.hour)) , 60 - (member1.minute_back - member1.minute));
			}
			//以上时段都为早退,则早退次数加一
			leave_early++;
			break;
		case 8:
			//上班时间不足8小时
			if(member1.minute > member1.minute_back)
			{
				printf("早退:%d小时%d分钟\n",time - 1 , member1.minute - member1.minute_back);
			}
			//上班时间刚好或超过8小时
			else
			{
				printf("早退:%d分钟\n",(member1.minute + (60 - member1.minute_back)));
	       	}
	       	//为早退,早退次数加一
			leave_early++;
			break;
	 	case 9:
			//上班时间不足9小时,为早退,早退次数加一
			if(member1.minute > member1.minute_back){
				printf("早退:%d\n",member1.minute - member1.minute_back);
				leave_early++;
			}
			//上班时长超过9小时,正常下班,打印上班时长
			else
			{
				printf("上班时长:%d小时%d分钟\n",time , member1.minute_back - member1.minute);
			}
			break;
		case 10:
		case 11:
		case 12:
			//上班时长还没超过缓冲机制时间
			if(member1.minute > member1.minute_back)
			{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour - 1 , 60 - member1.minute + member1.minute_back);
			}
			else
			{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour , member1.minute_back - member1.minute);
			}
			break;
		case 13:
		case 14:
		case 15:
		case 16:
			//上班时长超过缓冲机制时间
			if(member1.minute > member1.minute_back)
			{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour - 1 , 60 - member1.minute + member1.minute_back);
			}
			else{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour , member1.minute_back - member1.minute);
				buffer_mechanism = 1;
				printf("上班时长超过3小时及以上,第二天迟到2小时以内不算迟到!\n");
			}
			break;
		//工作超过17小时的属于下午缺卡
		default:
			printf("下午缺卡!\n");
			lack_punch_card++;
	}			
}

主函数:

int main(int argc,char *argv[])
{
	//累加上班天数,一周五天
	int i = 1;
	while(i < 6){
		clockin_machine_start();
		i++;
	}
	//计算平均上班时长
	worktime = (worktime / 5) / 60;
	//打印周报
	printf("打卡周报:\n");
	printf("上班平均时长:%f小时\n",working_time);
	printf("周迟到数:%d次\n",timelate);
	printf("早退次数:%d次\n",leave_early);
	printf("缺卡次数:%d次\n",lack_punch_card);
	return 0;
}

扩展:
关于时间的函数:
必须包含时间的头文件:

#include<time.h>

time函数的原型:

time_t time(time_t *t)

time()函数返回值的数据类型是time_t
传递给time()函数的参数是指向time_t数据类型的指针

结构体tm:用来保存时间和日期

struct tm 
{
   int tm_sec;         /* 秒,范围从 0 到 59      */
   int tm_min;         /* 分,范围从 0 到 59      */
   int tm_hour;        /* 小时,范围从 0 到 23     */
   int tm_mday;        /* 一月中的第几天,范围从 1 到 31    */
   int tm_mon;         /* 月,范围从 0 到 11(注意)  */
   int tm_year;        /* 自 1900 年起的年数      */
   int tm_wday;        /* 一周中的第几天,范围从 0 到 6 */
   int tm_yday;        /* 一年中的第几天,范围从 0 到 365   */
   int tm_isdst;       /* 夏令时               */
};

localtime函数:
函数原型:

struct tm *localtime(const time_t *timer)

函数功能:使用 timer 的值来填充 tm 结构。timer 的值被分解为 tm 结构,并用本地时区表示。
函数返回: 以tm结构表达的时间

程序任然有部分地方未完善,完善后继续更新

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值