get到的新东西:
1、时间函数一定要同时定义在一个作用域下,否则会出现紊乱;
2、结构体数组的定义、初始化与函数调用(数组的函数调用)。
代码详情
#include <stdio.h>
#include <time.h>
/** 模拟:每小时长度,工作规定时长 */
#define HOUR 6
#define POWER 7
#define WORKTIME 54
#define WEEKDAY 5
#define STUFF 2
#define CD 6
/** 每天开、关机时间*/
time_t TimeOn,TimeOff;
/** 员工考勤表 */
struct Info
{
char code[CD];
int Schedule[2]; //每日上下班时间
int L; //迟到
int E; //早退
int X; //旷工
int F; //全勤
int D[5]; // 每周持续上班时间
int AVED;
};
/** 开机,打卡,退卡等子函数声明 */
void clockin_machine_start();
int CardOn(struct Info *ct, time_t tempClock);
int CardOff(struct Info *ct, time_t tempClock);
int main()
{
clockin_machine_start();
return 0;
}
void clockin_machine_start()
{
/** 一、初始化模式*/
/** 1.1 员工信息录入与显示 */
printf("---事先录入员工信息---\n");
struct Info ct[STUFF]={};
for(int i=0; i<STUFF; i++){
printf("请输入%d/3员工的工号:", i+1);
gets(ct[i].code);
}
for(int i=0; i<STUFF; i++){
printf("%d/3员工的工号: %s\n", i+1, ct[i].code);
}
/** 1.2 时间更新 */
int day = 1;
/** 二、 工作模式 */
while(day<=WEEKDAY){
/** 1 报时 */
printf("---星期 %d---\n", day);
/** 2 模拟一天工作*/
/** 2.1 初始化各时间节点、员工起始表 */
time(&TimeOn);
printf("!!!实际时间为: %s\n", ctime(&TimeOn));
for(int i=0; i<STUFF; i++){
ct[i].Schedule[0]=0;
ct[i].Schedule[1]=0;
}
/** 2.2 初始化操作符、通常结束符、提前结束符 */
int opt;
int flag_uni = 1;
int flag_cnt = 0;
/** 2.3 功能循环放送(整天内可以随时打/退卡) */
while(flag_uni){
printf("--*--1.打卡--*--2.退卡--*--\n>>");
scanf("%d", &opt);
getchar();
/** 2.3.1 打卡操作 */
if(opt==1){
/** 2.3.1.1 避免子函数内定义造成计时紊乱 */
time_t tempClock;
/** 2.3.1.2 打卡操作子程序 */
int tempId = CardOn(ct, tempClock);
/** 2.3.1.3 打卡反馈信息 */
if(tempId != -1){
/** 显示信息 */
printf("$ %s 号员工上班时间为 ", ct[tempId].code);
int Gap = ct[tempId].Schedule[0]-TimeOn;
printf(" %d : %2d", Gap/HOUR + POWER, Gap%HOUR*10);
/** 记录信息:弹性迟到法则 */
if(ct[tempId].Schedule[0]-TimeOn <= 2*HOUR){
printf(",今日按时到岗。\n");
}else if(day>1 && ct[tempId].D[day-2]>=10*HOUR && ct[tempId].Schedule[0]-TimeOn<=4*HOUR){
printf(",昨日加班,不算迟到。\n");
}else{
printf(",上班迟到,予以警告!\n");
ct[tempId].L++;
}
}
/** 2.3.2 退卡操作 */
}else if(opt==2){
/** 2.3.2.1 避免子函数内定义造成计时紊乱 */
time_t tempClock;
/** 2.3.2.2 退卡操作子程序 */
int tempId = CardOff(ct, tempClock);
/** 2.3.2.3 退卡反馈信息 */
if(tempId != -1){
/** 所有人都下班时,自动关机 */
flag_cnt++;
if(flag_cnt == STUFF) flag_uni = 0;
/** 显示信息 */
printf("$ %s 号员工下班时间为 ", ct[tempId].code);
int Gap = ct[tempId].Schedule[1]-TimeOn;
printf(" %d : %2d", Gap/HOUR + POWER, Gap%HOUR*10);
/** 记录信息:工作时长,早退 */
int tempDuration = ct[tempId].Schedule[1]-ct[tempId].Schedule[0];
ct[tempId].D[day-1] = tempDuration;
if(tempDuration < 8*HOUR){
ct[tempId].E++;
printf(",早退 %d 分钟,予以警告!\n", (8*HOUR-tempDuration)*10);
}else{
printf(",多工作 %d 分钟,", (tempDuration-8*HOUR)*10);
/** 全勤判断:既不迟到也不早退 */
if(ct[tempId].Schedule[0]-TimeOn <= 2*HOUR){
ct[tempId].F++;
printf("全勤鼓励!\n");
}else if(day>1 && ct[tempId].D[day-2]>=10*HOUR && ct[tempId].Schedule[0]-TimeOn<=4*HOUR){
ct[tempId].F++;
printf("全勤鼓励!\n");
}
}
}
}
/** 2.3.3 重置操作符 */
opt = 0;
/** 2.3.4 是否到达截止时间并关机 */
time(&TimeOff);
if(TimeOff >= TimeOn + 17*HOUR){
printf("%s\n", ctime(&TimeOff));
printf("PowerOff!\n");
flag_uni = 0;
/** 2.3.3.1 每日结算,是否有旷工*/
for(int i=0; i<STUFF; i++){
if(ct[i].Schedule[1]==0 || ct[i].Schedule[1]==0){
ct[i].X++;
printf("%s 号员工今日旷工\n", ct[i].code);
}
}
}
}
/** 每日总结 */
printf("-*-星*期*%d*总*结-*-\n", day);
printf("员工编号\t迟到\t早退\t旷工\t全勤\n");
for(int i=0; i<STUFF; i++){
printf("%s\t\t%d\t%d\t%d\t%d\n", ct[i].code, ct[i].L, ct[i].E, ct[i].X, ct[i].F);
}
day++;
}
printf("-*-*-周-*-总-*-结-*-*-\n", day);
for(int i=0; i<STUFF; i++){
ct[i].AVED = ct[i].D[0];
for(int j=1; j<WEEKDAY; j++){
ct[i].AVED += ct[i].D[j];
}
ct[i].AVED = ct[i].AVED *10/5;
}
printf("员工编号\t平均到岗时间\n");
for(int i=0; i<STUFF; i++){
printf("%s\t\t%d\n", ct[i].code, ct[i].AVED);
}
printf("回车\n");
getchar();
return;
}
/** 打卡程序 */
int CardOn(struct Info *ct, time_t tempClock)
{
/** 设置缓冲区,比较符 */
char tempCode[CD];
printf("上班打卡模式\n");
int bingo = 0;
/** 打卡输入模块 */
while(!bingo){
time(&tempClock);
printf("请输入工号:\n");
gets(tempCode);
for(int i=0; i<STUFF; i++){
bingo = 1;
for(int j=0; j<CD; j++){
/** 若不匹配,则下一个 */
if(tempCode[j]!=ct[i].code[j]){
bingo = 0;
break;
}
}
/** 若完全匹配,则停止for循环 */
if(bingo==1){
if(ct[i].Schedule[0]!=0){
/** 重复打卡 */
printf("请勿重复打卡!\n");
}else{
/** 首次打卡 */
ct[i].Schedule[0] = tempClock;
return i;
}
break;
};
}
/** 查无此号:继续尝试or重新选择操作 */
if(bingo==0){
printf("不存在此工号\n");
printf("是否退出?\n1.是\t0.否\n>>>");
scanf("%d", &bingo);
getchar();
if(bingo==1) printf("退出成功\n");
}
}
return -1;
}
/** 退卡程序 */
int CardOff(struct Info *ct, time_t tempClock)
{
/** 设置缓冲区,比较符 */
char tempCode[CD];
printf("下班退卡模式\n");
int bingo = 0;
/** 退卡输入模块 */
while(!bingo){
time(&tempClock);
printf("请输入工号:\n");
gets(tempCode);
for(int i=0; i<STUFF; i++){
bingo = 1;
for(int j=0; j<CD; j++){
/** 不匹配则下一个 */
if(tempCode[j]!=ct[i].code[j]){
bingo = 0;
break;
}
}
/** 完全匹配 */
if(bingo==1){
/** 比打卡操作多了这一步 */
if(ct[i].Schedule[0]==0){
printf("尚未打卡,强制退出!\n");
}else{
if(ct[i].Schedule[1]!=0){
printf("请勿重复退卡!\n");
}else{
ct[i].Schedule[1] = tempClock;
return i;
}
}
break;
};
}
if(bingo==0){
printf("不存在此工号\n");
printf("是否退出?\n1.是\t0.否\n>>>");
scanf("%d", &bingo);
getchar();
if(bingo==1) printf("退出成功\n");
}
}
return -1;
}
演示效果
---事先录入员工信息---
请输入1/3员工的工号:110000
请输入2/3员工的工号:110001
1/3员工的工号: 110000
2/3员工的工号: 110001
---星期 1---
!!!实际时间为: Sun Aug 30 10:34:32 2020
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110000
$ 110000 号员工上班时间为 7 : 20,今日按时到岗。
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110001
$ 110001 号员工上班时间为 8 : 10,今日按时到岗。
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110001
$ 110001 号员工下班时间为 11 : 0,早退 310 分钟,予以警告!
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110001
请勿重复退卡!
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110000
请勿重复打卡!
--*--1.打卡--*--2.退卡--*--
>>110002
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110002
不存在此工号
是否退出?
1.是 0.否
>>>0
请输入工号:
110003
不存在此工号
是否退出?
1.是 0.否
>>>1
退出成功
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110004
不存在此工号
是否退出?
1.是 0.否
>>>1
退出成功
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110000
$ 110000 号员工下班时间为 18 : 10,多工作 170 分钟,全勤鼓励!
-*-星*期*1*总*结-*-
员工编号 迟到 早退 旷工 全勤
110000 0 0 0 1
110001 0 1 0 0
---星期 2---
!!!实际时间为: Sun Aug 30 10:35:42 2020
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110001
$ 110001 号员工上班时间为 8 : 30,今日按时到岗。
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110000
$ 110000 号员工上班时间为 9 : 40,昨日加班,不算迟到。
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110001
$ 110001 号员工下班时间为 13 : 10,早退 200 分钟,予以警告!
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110000
$ 110000 号员工下班时间为 17 : 40,多工作 0 分钟,全勤鼓励!
-*-星*期*2*总*结-*-
员工编号 迟到 早退 旷工 全勤
110000 0 0 0 2
110001 0 2 0 0
---星期 3---
!!!实际时间为: Sun Aug 30 10:36:48 2020
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110001
$ 110001 号员工上班时间为 8 : 0,今日按时到岗。
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110000
$ 110000 号员工上班时间为 9 : 40,上班迟到,予以警告!
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110000
$ 110000 号员工下班时间为 14 : 10,早退 210 分钟,予以警告!
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110001
$ 110001 号员工下班时间为 15 : 40,早退 20 分钟,予以警告!
-*-星*期*3*总*结-*-
员工编号 迟到 早退 旷工 全勤
110000 1 1 0 2
110001 0 3 0 0
---星期 4---
!!!实际时间为: Sun Aug 30 10:37:42 2020
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110001
$ 110001 号员工上班时间为 31 : 10,上班迟到,予以警告!
Sun Aug 30 10:40:12 2020
PowerOff!
110000 号员工今日旷工
110001 号员工今日旷工
-*-星*期*4*总*结-*-
员工编号 迟到 早退 旷工 全勤
110000 1 1 1 2
110001 1 3 1 0
---星期 5---
!!!实际时间为: Sun Aug 30 10:40:12 2020
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110001
$ 110001 号员工上班时间为 7 : 50,今日按时到岗。
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110000
$ 110000 号员工上班时间为 9 : 0,今日按时到岗。
--*--1.打卡--*--2.退卡--*--
>>1
上班打卡模式
请输入工号:
110000
请勿重复打卡!
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110000
$ 110000 号员工下班时间为 18 : 20,多工作 80 分钟,全勤鼓励!
--*--1.打卡--*--2.退卡--*--
>>2
下班退卡模式
请输入工号:
110001
$ 110001 号员工下班时间为 19 : 20,多工作 210 分钟,全勤鼓励!
-*-星*期*5*总*结-*-
员工编号 迟到 早退 旷工 全勤
110000 1 1 1 3
110001 1 3 1 1
-*-*-周-*-总-*-结-*-*-
员工编号 平均到岗时间
110000 392
110001 320