自己早期写的一个简单上下班打卡统计工时的考勤系统【整理版】

原本这个帖子,是由回复组成的,整个代码分布在各个回复里面,读者不好阅读,现在整个把它们放到正文,方便查看。

这是早期写的一个,仅仅是简单的考勤系统,大致功能是有的,但并未写的很牛叉,采用了文本来记录考勤数据,供小菜一览。

 

 

[cpp]  view plain  copy
  1. //头文件:emp_head.h  
  2.   
  3. #ifndef EMP_HEAD_H  
  4. #define EMP_HEAD_H  
  5.   
  6. #include<stdio.h>  
  7. #include<stdlib.h>  
  8.   
  9. #define MAXNUM 1000  
  10.   
  11. enum {  
  12.      NORMAL           = 0,  
  13.      ABSENT           = 1,  
  14.      WORK_LATE        = 2,  
  15.      LEAVE_EARLY      = 3,  
  16.      LATE_AND_LEARLY  = 4,  
  17.      PUNCH_ABNORMAL   = 5  
  18. };  
  19.   
  20. enum {  
  21.      ERR_TIME_INVALID  = 1,  
  22.      ERR_ID_INVALID    = 2,  
  23.      ERR_CMD_INVALID   = 3,  
  24.      ERR_EXIT_SYS      = 9  
  25. };  
  26.   
  27. struct emp_data  
  28. {  
  29.     int id;  
  30.     char name[8];  
  31.     int type;  
  32.     char check_in[16];//19:58 20110804  
  33.     char check_out[16];  
  34.     int work_time; //1208 --> 12H12M  
  35. } emp_data1;  
  36.   
  37.   
  38. int cmd_process(char* cmdx);  
  39.   
  40. void p_err(int err);  
  41. int check_time(char *time);  
  42. int check_type(char *check_in, char *check_out);  
  43. void th_func(void);  
  44. void print_help(void);  
  45. int clean_data(char *fileaddr);  
  46. int request_data(char *fileaddr, char* cmdx);  
  47. int check_inout(char *fileaddr, char* cmdx);  
  48. int type_check(char* check_in, char *check_out, int* outlen);  
  49. char* ret_typestr(int typecode);  
  50.   
  51. //char* analy_cmd(char* cmdx, int* n);  
  52.   
  53. #endif  //end EMP_HEAD_H  


 

 

以下内容全部为一个c文件(主c文件),其实也就只有这个c文件。加上上面的头文件,整个可以编译通过生成我们的考勤系统。只是因为CSDN的语法高亮做的不好,如果代码太长的话,整个网页加载起来很慢,所以就分开为几小段了。

 

另外关于输入检查这一块,之前没有写一个函数,结果这个程序只能固定多少个字符,来进行偏移,少了不行,多了也不行,全都是用指针偏移来操作的。后来写了个函数(请参考从符号分隔的命令行获取任意参数的函数(逗号分隔,空格分隔等都可以)(2011-12-29 01:04)) ,但是,由于太懒,所以没有改写这个考勤系统。留给读者改改吧。

 

[cpp]  view plain  copy
  1. /* 
  2. *主c文件 
  3. *author:duanxufang 
  4. *time: 
  5. *description:考勤系统 
  6. * 
  7. */  
  8. #include <stdio.h>  
  9. #include <stdlib.h>  
  10. #include <pthread.h>  
  11. #include <string.h>  
  12. #include "../include/emp_head.h"  
  13.   
  14.   
  15. #define FILE_IN "emp_record.datafile"  
  16.   
  17. struct emp_data record[MAXNUM] = {0};  
  18.   
  19. int main()  
  20. {  
  21.     pthread_t th_id;  
  22.     printf("will create thread!\n");  
  23.     if(pthread_create(&th_id, NULL, (void*)th_func, NULL))  
  24.     {  
  25.     printf("create thread error!\n");  
  26.     exit(1);  
  27.     }  
  28.     if(pthread_join(th_id, NULL))  
  29.     {  
  30.     printf("thread quit error!");  
  31.     exit(1);  
  32.     }  
  33.     return 0;  
  34. }  


 

 

[cpp]  view plain  copy
  1. void p_err(int err)  
  2. {  
  3.     switch(err)  
  4.     {  
  5.     case ERR_TIME_INVALID : printf("[ERR:TIME INVALID]\n"); break;  
  6.     case ERR_ID_INVALID : printf("[ERR:ID INVALID]\n"); break;  
  7.     case ERR_CMD_INVALID : printf("[ERR:COMMAND INVALID]\n"); break;  
  8.     case 0 : break;  
  9.     default: printf("ERR:Not Known!\n");  
  10.     }  
  11.     return ;  
  12. }  
  13.   
  14. void th_func(void)  
  15. {  
  16.     char input_cmd[256] = {0};  
  17.     print_help();  
  18.     while(printf("cmd here>"),gets(input_cmd))  
  19.     {  
  20.         int err_no = 0;  
  21.         if((err_no = cmd_process(input_cmd)) == ERR_EXIT_SYS)  
  22.         {  
  23.         printf("EXIT SYSTEM\n");  
  24.         break;  
  25.         }  
  26.         p_err(err_no);  
  27.         printf("\nplease input next cmd:\n");  
  28.     }  
  29.     return ;  
  30. }  
  31.   
  32. void print_help(void)  
  33. {  
  34.     printf("--------cmd help:-----------\n\"0\":clean all the records \"1\":checktime input\n");  
  35.     printf("\"2\":request records q/Q for quit system\n");  
  36.     printf("h/H for help\n");  
  37.     printf("cmd format is: 1,0001,duan001,18:56\n \  
  38.     [id] like 0001 must be 4 chars\n \  
  39.     [name] like duan001 must be 7 chars\n");  
  40.     printf("--------cmd help end--------\n");  
  41.     return ;  
  42. }  
  43.   
  44. int cmd_process(char* cmdx)  
  45. {  
  46.     printf("Your cmd: %s\n", cmdx);  
  47.     int cmd_id = (int)(cmdx[0]-'0');  
  48.     switch(cmd_id)  
  49.     {  
  50.     case 0: clean_data(FILE_IN); break;  
  51.     case 1: check_inout(FILE_IN, cmdx); break;  
  52.     case 2: request_data(FILE_IN, cmdx); break;  
  53.     case 'h'-'0':  
  54.     case 'H'-'0': print_help(); break;  
  55.     case 'q'-'0':  
  56.     case 'Q'-'0'return ERR_EXIT_SYS; //quik system;  
  57.     defaultreturn ERR_CMD_INVALID;  
  58.     }  
  59.     return 0;  
  60. }  
  61.   
  62. int clean_data(char *fileaddr)  
  63. {  
  64.     int count = 0;  
  65.     char buf[60000];  
  66.     int read_n = 0;  
  67.     int i = 0;  
  68.     struct emp_data *pemp = (struct emp_data *)buf;  
  69.     FILE *fptr;  
  70.     printf("clean_data()\n");//for debug  
  71.     if(!(fptr = fopen(FILE_IN, "w")) )  
  72.     {  
  73.         printf("in clean _data open file[%s] failed!\n", FILE_IN);  
  74.         return 1;  
  75.     }  
  76.     if(!(read_n = fread(buf, 1, 60000, fptr)))  
  77.     {  
  78.         printf("no record!");  
  79.         return 1;  
  80.     }  
  81.     count =read_n/(sizeof(struct emp_data));  
  82.     for(i =0; i < count; i++)  
  83.     {  
  84.         pemp[i].type = PUNCH_ABNORMAL;  
  85.         strcpy(pemp[i].check_in, "");  
  86.         strcpy(pemp[i].check_out, "");  
  87.         pemp[i].work_time = 0;  
  88.     }  
  89.     fwrite(buf, 1, read_n, fptr);  
  90.     read_n = fread(buf, 1, 60000, fptr);  
  91.     for(i =0; i < count; i++)  
  92.     {  
  93.         printf("%d ", pemp[i].id);  
  94.         printf("%s ", pemp[i].name);  
  95.         printf("%s ", ret_typestr(pemp[i].type));  
  96.         printf("%s ", pemp[i].check_in);  
  97.         printf("%s ", pemp[i].check_out);  
  98.         printf("%d\n", pemp[i].work_time);  
  99.     }  
  100.     fclose(fptr);  
  101.     return 0;  
  102. }  


 

[cpp]  view plain  copy
  1. //request_data  
  2. int request_data(char *fileaddr, char* cmdx)  
  3. {  
  4.     int count = 0;  
  5.     char buf[60000];  
  6.     int read_n = 0;  
  7.     int i = 0;  
  8.     struct emp_data *pemp = (struct emp_data *)buf;  
  9.     printf("in request_data()\n");  
  10.     FILE *fptr;  
  11.     if(!(fptr = fopen(FILE_IN, "r")) )  
  12.     {  
  13.         printf("in request_data open file[%s] failed!\n", FILE_IN);  
  14.         return 1;  
  15.     }  
  16.     if(!(read_n = fread(buf, 1, 60000, fptr)))  
  17.     {  
  18.         printf("no record!");  
  19.         return 1;  
  20.     }  
  21.     count =read_n/(sizeof(struct emp_data));  
  22.     if(strlen(cmdx)==1)  
  23.     {  
  24.         for(i =0; i < count; i++)  
  25.         {  
  26.             printf("%4d ", pemp[i].id);  
  27.             printf("%10s ", pemp[i].name);  
  28.             printf("%-16s ", ret_typestr(pemp[i].type));  
  29.             printf("%6s ", pemp[i].check_in);  
  30.             printf("%6s ", pemp[i].check_out);  
  31.             printf("%6d\n", pemp[i].work_time);  
  32.         }  
  33.     }  
  34.     else  
  35.     {  
  36.         for(i =0; i < count; i++)  
  37.         {  
  38.             if(pemp[i].id==atoi(cmdx+2))  
  39.             {  
  40.             printf("%4d ", pemp[i].id);  
  41.             printf("%10s ", pemp[i].name);  
  42.             printf("%-16s ", ret_typestr(pemp[i].type));  
  43.             printf("%6s ", pemp[i].check_in);  
  44.             printf("%6s ", pemp[i].check_out);  
  45.             printf("%6d\n", pemp[i].work_time);  
  46.             }  
  47.         }  
  48.     }  
  49.     fclose(fptr);  
  50.     return 0;  
  51. }  
  52.   
  53. //check_inout的前半部分  
  54. int check_inout(char *fileaddr, char* cmdx)  
  55. {  
  56.     //取得数量  
  57.     int count = 0, read_n = 0;  
  58.     int worktime_len = 0;  
  59.     int i = 0;  
  60.     char buf[60000]={0};  
  61.     int emp_id = atoi(cmdx+2);  
  62.     struct emp_data *pemp = (struct emp_data *)buf;  
  63.   
  64.     printf("in check_inout() \n");  
  65.     if(strlen(cmdx)<=2)  
  66.     {  
  67.         p_err(ERR_CMD_INVALID);  
  68.         return 1;  
  69.     }  
  70.     if((atoi(cmdx+2)>1000)||(atoi(cmdx+2)<1))  
  71.     {  
  72.         p_err(ERR_ID_INVALID);  
  73.         return 1;  
  74.     }  
  75.     //检查时间格式  
  76.     if((cmdx[17]!=':')||(atoi(cmdx+15)>23)||(atoi(cmdx+15)<0)||  
  77.     (atoi(cmdx+18)>59)||(atoi(cmdx+18)<0))  
  78.     {  
  79.         p_err(ERR_TIME_INVALID);  
  80.         return 1;  
  81.     }  
  82.     FILE *fptr;  
  83.     if(!(fptr = fopen(FILE_IN, "r+")) )  
  84.     {  
  85.         printf("open file[%s] failed!\n", FILE_IN);  
  86.         return 1;  
  87.     }  
  88.     read_n = fread(buf, 1, 60000, fptr);  
  89.     printf("read_n is: %d \n", read_n);  
  90.     count =read_n/(sizeof(struct emp_data));  
  91.     fclose(fptr);  
  92.     check_inout的中间部分  
  93.     for(i = 0; i < count; i++)  
  94.     {  
  95.         if( (pemp->id)== emp_id)  
  96.         {  
  97.             //更新刷卡记录  
  98.             //strncpy 后面这个参数6害惨了我! 其实编译的时候会提示一个strncpy的警告!  
  99.             strncpy(pemp->check_out, cmdx+15, 6); //!!!之前的值为5,最后必需写一个'\0',且这个'\0'包含在6中会发生段错误  
  100.             //printf("-------typecheck----");  
  101.             pemp->type = type_check(pemp->check_in, pemp->check_out, &worktime_len);  
  102.             pemp->work_time = worktime_len;//worktime();  
  103.             if(!(fptr = fopen(FILE_IN, "w")) )  
  104.             {  
  105.                 printf("open file[%s] failed!\n", FILE_IN);  
  106.                 return 1;  
  107.             }  
  108.             read_n=fwrite(buf,1,count*(sizeof(struct emp_data)),fptr);  
  109.             fclose(fptr);  
  110.             printf("if [0 count]---write bytes :%d\n", read_n);  
  111.             break;  
  112.         }  
  113.         pemp++;  
  114.     }  
  115.     //如果不存在这个人的刷卡记录,包括没有任何记录  
  116.     if(i == count)  
  117.     {  
  118.         //把结构数据集的指针指向要写入数据的位置  
  119.         struct emp_data emp_data2;  
  120.         pemp = &emp_data2;  
  121.         pemp->id = emp_id;  
  122.         bzero(pemp->name, 8);  
  123.         strncpy(pemp->name, cmdx+7, 7);//必需拷贝7个字符,最后一个字符置为'\0'  
  124.         pemp->type = PUNCH_ABNORMAL;  
  125.         strncpy(pemp->check_in, cmdx+15, 6);  
  126.         strcpy(pemp->check_out, "");  
  127.         pemp->work_time = 0;  
  128.         if(!(fptr = fopen(FILE_IN, "a")) )  
  129.         {  
  130.             printf("open file[%s] failed!\n", FILE_IN);  
  131.             return 1;  
  132.         }  
  133.         read_n=fwrite(pemp,1,sizeof(struct emp_data),fptr);  
  134.         fclose(fptr);  
  135.         printf("if i== count---write bytes :%d,count %d\n", read_n, count);  
  136.     }  
  137.     return 0;  
  138. }  
  139.   
  140.   
  141. //检查早退迟到等,并可以计算工时,工时通过outlen指针输出  
  142. int type_check(char* check_in, char *check_out, int* outlen)  
  143. {  
  144.     int in_hh, in_mm;  
  145.     int out_hh, out_mm;  
  146.     int hh = 0, mm = 0;  
  147.     int flaglate = 0, flagearly = 0;  
  148.     int flagt =0;  
  149.   
  150.     printf("in type_check()\n");  
  151.     if((strlen(check_in)>1)&&(strlen(check_out)>1))  
  152.     {  
  153.         in_hh = atoi(check_in);  
  154.         in_mm = atoi(check_in+3);  
  155.         out_hh = atoi(check_out);  
  156.         out_mm = atoi(check_out+3);  
  157.         if((in_hh>8)||((in_hh==8)&&(in_mm>0)))  
  158.         {  
  159.             flaglate = 1;  
  160.             flagt = WORK_LATE;  
  161.         }  
  162.         if((out_hh<17)||((out_hh==17)&&(out_mm<30)))  
  163.         {  
  164.             flagearly = 1;  
  165.             flagt = LEAVE_EARLY;  
  166.         }  
  167.         if((in_hh>17)||((in_hh==17)&&(in_mm>=30))||  
  168.         (out_hh<8)||((out_hh==8)&&(out_mm==0)))  
  169.         {  
  170.             printf("----1----abs");  
  171.             flagt = ABSENT;  
  172.         }  
  173.         if(flaglate&&flagearly)  
  174.         {  
  175.             flagt =LATE_AND_LEARLY;  
  176.         }  
  177.     }  
  178.     else if((strlen(check_in)<1)&&(strlen(check_out)<1))  
  179.     {  
  180.         printf("----2----abs");  
  181.         flagt = ABSENT;  
  182.     }  
  183.     else  
  184.     {  
  185.         flagt = PUNCH_ABNORMAL;  
  186.     }  
  187.     //如果,参数outlen== -1 则不计算工时,否则计算  
  188.     if(*outlen == -1) goto ret;  
  189.     if((flagt == ABSENT)||(flagt == PUNCH_ABNORMAL)) //之前这里flagt == ABSENT少打了一个=号,害得结果又错了  
  190.     {  
  191.     *outlen = 0;  
  192.     }  
  193.     else  
  194.     {  
  195.         if(in_mm<=out_mm)  
  196.         {  
  197.         *outlen = (out_hh-in_hh)*100 + (out_mm-in_mm);  
  198.         }  
  199.         else  
  200.         {  
  201.         *outlen = (out_hh-in_hh-1)*100 + 60 + (out_mm-in_mm);  
  202.         }  
  203.     }  
  204.     ret: return flagt;  
  205. }  
  206.   
  207. char* ret_typestr(int typecode)  
  208. {  
  209.     switch(typecode)  
  210.     {  
  211.     case 0: return "NORMAL";  
  212.     case 1: return "ABSENT";  
  213.     case 2: return "WORK_LATE";  
  214.     case 3: return "LEAVE_EARLY";  
  215.     case 4: return "LATE_AND_LEARLY";  
  216.     case 5: return "PUNCH_ABNORMAL";  
  217.     defaultreturn "typecode not know!";  
  218.     }  
  219. }  
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设你已经有了一个 `Employee` 实体类和一个 `Attendance` 实体类,其中 `Attendance` 记录了员工上下班打卡记录,包括打卡日期、上班打卡时间和下班打卡时间等信息。你需要查询某个员工在指定日期的上下班打卡记录,可以按照以下步骤进行操作: 1. 创建一个 `DbContext` 类,用于管理实体类和数据库连接。 ```csharp public class MyDbContext : DbContext { public DbSet<Employee> Employees { get; set; } public DbSet<Attendance> Attendances { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { // 配置数据库连接字符串 optionsBuilder.UseSqlServer("Server=localhost;Database=mydb;User Id=myuser;Password=mypassword;"); } } ``` 2. 在 `Attendance` 实体类中定义一个 `Employee` 属性,用于关联员工实体。 ```csharp public class Attendance { public int Id { get; set; } public DateTime Date { get; set; } public DateTime? ClockIn { get; set; } public DateTime? ClockOut { get; set; } public int EmployeeId { get; set; } public Employee Employee { get; set; } } ``` 3. 在 `Employee` 实体类中定义一个 `Attendances` 属性,用于关联打卡记录实体集合。 ```csharp public class Employee { public int Id { get; set; } public string Name { get; set; } public ICollection<Attendance> Attendances { get; set; } } ``` 4. 编查询代码。可以使用 LINQ 表达式查询指定日期的员工打卡记录,示例代码如下: ```csharp using (var db = new MyDbContext()) { var employeeId = 1; // 员工 ID var date = DateTime.Parse("2022-01-01"); // 打卡日期 var query = from a in db.Attendances where a.EmployeeId == employeeId && a.Date == date select a; var results = query.ToList(); foreach (var result in results) { Console.WriteLine($"{result.ClockIn} - {result.ClockOut}"); } } ``` 上述代码中,首先创建了一个 `MyDbContext` 实例,然后使用 LINQ 表达式查询指定员工和日期的打卡记录,最后将结果输出到控制台。需要注意的是,查询结果是一个 `List<Attendance>` 集合,其中包含了员工在指定日期的所有打卡记录。如果某个打卡时间为空,对应的属性值将会是 `null`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值