搭建框架
1、建立主文件main.c
2、编写自定义函数文件cmt.c
3、建立对应头文件cmt.h
主文件
1、包含头文件:#include <cmt.h>
2、声明存储信息的全局结构体变量以及对应指针
3、含有唯一主函数:int main()
4、含有专用的子函数和附加定义
// 员工信息录入,员工信息管理
// void staff_book(struct InfoM *stfm);
// void start_staff_manager();
头文件
1、公开的宏定义
// 定义一些常用变量
// 并外部添加
#ifndef CMT_H_
#define CMT_H_
#endif
防止重定义
2、公开的结构体定义
// 该结构体类型可由声明该头文件的任意文件调用
3、公开的库函数声明
// 其中定义的子函数可由声明该头文件的任意文件调用
自定义函数文件
将之前的打卡机文件改成自定义的函数库文件
修改1:去除主函数
// 保留原有的子函数
// 开机函数、打卡函数、退卡函数
void clockin_machine_start(struct InfoM *stfm)
int CardOn(struct InfoM *stfm, time_t tempClock);
int CardOff(struct InfoM *stfm, time_t tempClock);
修改2:修改原先的结构体
// 采用内嵌结构体的形式
// 通常信息+考勤信息
// 该文件中的函数对通常信息仅做读取,对考勤信息可以修改
修改3:添加头文件包含:#include <cmt.h>
运行流程
1、声明全局构造类型变量
2、录入员工信息
3、打卡机操作流程
4、每周打卡信息整理
5、按工时排序
其中1、2、4、5操作在主文件main.c下定义;
3操作在库文件cmt.c下定义,经由头文件cmt.h声明实现主文件的调用。
cmt.h
/** 宏定义与结构体定义 */
/** 模拟:每小时长度,转换为实际分钟 */
#define HOUR 6
#define TRANS 10 //60/6
#define POWER 7
#define WEEKDAY 5
#define STUFF 4
#define NUMS 6
#ifndef CMT_H_
#define CMT_H_
/** 员工考勤表 */
struct Info
{
//char code[NUMS];
int Schedule[2]; //每日上下班时间
int L; //迟到
int E; //早退
int X; //旷工
int F; //全勤
int D[5]; //每周持续上班时间
int AVED;
};
/** 员工信息表 */
struct InfoM
{
char name[16];
char code[NUMS];
short age;
char sex;
char call[16];
char mail[32];
struct Info ct;
};
/** 头文件中不能定义结构体数组 */
//struct InfoM stfm[STUFF]={};
/** 打卡操作声明 */
void clockin_machine_start(struct InfoM *stfm);
#endif // CMT_H_
main.c
#include <stdio.h>
#include <stdlib.h>
#include "cmt.h"
struct InfoM stfm[STUFF] = {};
struct InfoM st[STUFF] = {};
struct InfoM *p = &stfm[0];
void start_staff_manager();
void staff_book(struct InfoM *stfm);
int main()
{
start_staff_manager();
return 0;
}
void start_staff_manager()
{
/** 录入员工信息 */
staff_book(p);
/** 打卡操作 */
clockin_machine_start(p);
/** 信息备份 */
FILE *fp;
fp = fopen("result.txt","w+");
fwrite(&stfm,sizeof(stfm),1,fp);
/** 将文件内部指针fp指向文件内容开头 */
rewind(fp);
/** 信息读取 */
fread(&st,sizeof(st),1,fp);
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", st[i].name, st[i].ct.L, st[i].ct.E, st[i].ct.X, st[i].ct.F);
}
fclose(fp);
/** 排序模块 */
for(int i=0; i<STUFF; i++)
{
/** 大--->小 */
for(int j=0; j<STUFF-i-1; j++)
{
if( st[j].ct.AVED < st[j+1].ct.AVED)
{
/** 注意 temp 的类型 */
struct InfoM temp = st[j];
st[j] = st[j+1];
st[j+1] = temp;
}
}
}
/** 输出排序结果 */
for(int i=0; i<STUFF; i++)
{
printf("第 %d 名是:%s,日工作时间为 %d\n", i+1, st[i].name, st[i].ct.AVED);
}
}
/** 录入员工信息 */
void staff_book(struct InfoM *stfm)
{
for(int i=0; i<STUFF; i++)
{
printf("<<%d>>姓名:", i+1);
gets(stfm[i].name);
printf("<<%d>>确认姓名: %s\n", i+1, stfm[i].name);
printf("<<%d>>编号(%d位):", i+1, NUMS);
gets(stfm[i].code);
printf("<<%d>>确认编号: %s\n", i+1, stfm[i].code);
printf("<<%d>>年龄:", i+1);
scanf("%hd", &stfm[i].age);
getchar();
printf("<<%d>>确认年龄: %d\n", i+1, stfm[i].age);
printf("<<%d>>性别(m/f):", i+1);
scanf("%c", &stfm[i].sex);
getchar();
printf("<<%d>>确认性别: %c\n", i+1, stfm[i].sex);
printf("<<%d>>电话:", i+1);
gets(stfm[i].call);
printf("<<%d>>确认电话: %s\n", i+1, stfm[i].call);
printf("<<%d>>邮箱:", i+1);
gets(stfm[i].mail);
printf("<<%d>>确认邮箱: %s\n", i+1, stfm[i].mail);
}
}
cmt.c
#include <stdio.h>
#include <time.h>
#include "cmt.h"
/** 打卡操作定义 */
time_t TimeOn,TimeOff;
int CardOn(struct InfoM *stfm, time_t tempClock);
int CardOff(struct InfoM *stfm, time_t tempClock);
void clockin_machine_start(struct InfoM *stfm)
{
/** 一、初始化模式*/
/** 1.1 员工信息录入与显示 */
//printf("---事先录入员工信息---\n");
/** 为防止跨文件后内存被释放,设置为静态变量 */
/** static:仅能在文件内部被使用 */
//struct Info ct[STUFF]={};
for(int i=0; i<STUFF; i++)
{
printf("<<%d>>确认姓名: %s\n", i+1, stfm[i].name);
printf("<<%d>>确认编号: %s\n", i+1, stfm[i].code);
printf("<<%d>>确认年龄: %d\n", i+1, stfm[i].age);
printf("<<%d>>确认性别: %c\n", i+1, stfm[i].sex);
printf("<<%d>>确认电话: %s\n", i+1, stfm[i].call);
printf("<<%d>>确认邮箱: %s\n", i+1, stfm[i].mail);
}
/** 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++){
stfm[i].ct.Schedule[0]=0;
stfm[i].ct.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(stfm, tempClock);
/** 2.3.1.3 打卡反馈信息 */
if(tempId != -1){
/** 显示信息 */
printf("$ %s 上班时间为 ", stfm[tempId].name);
int Gap = stfm[tempId].ct.Schedule[0]-TimeOn;
printf(" %d : %2d", Gap/HOUR + POWER, Gap%HOUR*10);
/** 记录信息:弹性迟到法则 */
if(stfm[tempId].ct.Schedule[0]-TimeOn <= 2*HOUR){
printf(",今日按时到岗。\n");
}else if(day>1 && stfm[tempId].ct.D[day-2]>=10*HOUR && stfm[tempId].ct.Schedule[0]-TimeOn<=4*HOUR){
printf(",昨日加班,不算迟到。\n");
}else{
printf(",上班迟到,予以警告!\n");
stfm[tempId].ct.L++;
}
}
/** 2.3.2 退卡操作 */
}else if(opt==2){
/** 2.3.2.1 避免子函数内定义造成计时紊乱 */
time_t tempClock;
/** 2.3.2.2 退卡操作子程序 */
int tempId = CardOff(stfm, tempClock);
/** 2.3.2.3 退卡反馈信息 */
if(tempId != -1){
/** 所有人都下班时,自动关机 */
flag_cnt++;
if(flag_cnt == STUFF) flag_uni = 0;
/** 显示信息 */
printf("$ %s 下班时间为 ", stfm[tempId].name);
int Gap = stfm[tempId].ct.Schedule[1]-TimeOn;
printf(" %d : %2d", Gap/HOUR + POWER, Gap%HOUR*10);
/** 记录信息:工作时长,早退 */
int tempDuration = stfm[tempId].ct.Schedule[1]-stfm[tempId].ct.Schedule[0];
stfm[tempId].ct.D[day-1] = tempDuration;
if(tempDuration < 8*HOUR){
stfm[tempId].ct.E++;
printf(",早退 %d 分钟,予以警告!\n", (8*HOUR-tempDuration)*10);
}else{
printf(",多工作 %d 分钟,", (tempDuration-8*HOUR)*10);
/** 全勤判断:既不迟到也不早退 */
if(stfm[tempId].ct.Schedule[0]-TimeOn <= 2*HOUR){
stfm[tempId].ct.F++;
printf("全勤鼓励!\n");
}else if(day>1 && stfm[tempId].ct.D[day-2]>=10*HOUR && stfm[tempId].ct.Schedule[0]-TimeOn<=4*HOUR){
stfm[tempId].ct.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(stfm[i].ct.Schedule[1]==0 || stfm[i].ct.Schedule[1]==0){
stfm[i].ct.X++;
printf("%s 今日旷工\n", stfm[i].name);
}
}
}
}
/** 每日总结 */
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", stfm[i].name, stfm[i].ct.L, stfm[i].ct.E, stfm[i].ct.X, stfm[i].ct.F);
//printf("%s\t\t%d\t%d\t%d\t%d\n", stfm[i].ct.code, stfm[i].ct.L, stfm[i].ct.E, stfm[i].ct.X, stfm[i].ct.F);
//printf("%x\t\t%x\t%x\t%x\t%x\n", &stfm[i].name, &stfm[i].ct.L, &stfm[i].ct.E, &stfm[i].ct.X, &stfm[i].ct.F);
}
day++;
}
printf("-*-*-周-*-总-*-结-*-*-\n");
for(int i=0; i<STUFF; i++){
stfm[i].ct.AVED = stfm[i].ct.D[0];
for(int j=1; j<WEEKDAY; j++){
stfm[i].ct.AVED += stfm[i].ct.D[j];
}
stfm[i].ct.AVED = stfm[i].ct.AVED *10/5;
}
printf("员工姓名\t平均到岗时间\n");
for(int i=0; i<STUFF; i++){
printf("%s\t\t%d\n", stfm[i].name, stfm[i].ct.AVED);
}
printf("回车\n");
getchar();
//printf("\n p : %x", p);
}
/** 打卡程序 */
int CardOn(struct InfoM *stfm, time_t tempClock)
{
/** 设置缓冲区,比较符 */
char tempCode[NUMS];
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<NUMS; j++){
/** 若不匹配,则下一个 */
//if(tempCode[j]!=stfm[i].ct.code[j]){
if(tempCode[j]!=stfm[i].code[j]){
bingo = 0;
break;
}
}
/** 若完全匹配,则停止for循环 */
if(bingo==1){
if(stfm[i].ct.Schedule[0]!=0){
/** 重复打卡 */
printf("请勿重复打卡!\n");
}else{
/** 首次打卡 */
stfm[i].ct.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 InfoM *stfm, time_t tempClock)
{
/** 设置缓冲区,比较符 */
char tempCode[NUMS];
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<NUMS; j++){
/** 不匹配则下一个 */
//if(tempCode[j]!=stfm[i].ct.code[j]){
if(tempCode[j]!=stfm[i].code[j]){
bingo = 0;
break;
}
}
/** 完全匹配 */
if(bingo==1){
/** 比打卡操作多了这一步 */
if(stfm[i].ct.Schedule[0]==0){
printf("尚未打卡,强制退出!\n");
}else{
if(stfm[i].ct.Schedule[1]!=0){
printf("请勿重复退卡!\n");
}else{
stfm[i].ct.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;
}