原本这个帖子,是由回复组成的,整个代码分布在各个回复里面,读者不好阅读,现在整个把它们放到正文,方便查看。
这是早期写的一个,仅仅是简单的考勤系统,大致功能是有的,但并未写的很牛叉,采用了文本来记录考勤数据,供小菜一览。
//头文件:emp_head.h
#ifndef EMP_HEAD_H
#define EMP_HEAD_H
#include<stdio.h>
#include<stdlib.h>
#define MAXNUM 1000
enum {
NORMAL = 0,
ABSENT = 1,
WORK_LATE = 2,
LEAVE_EARLY = 3,
LATE_AND_LEARLY = 4,
PUNCH_ABNORMAL = 5
};
enum {
ERR_TIME_INVALID = 1,
ERR_ID_INVALID = 2,
ERR_CMD_INVALID = 3,
ERR_EXIT_SYS = 9
};
struct emp_data
{
int id;
char name[8];
int type;
char check_in[16];//19:58 20110804
char check_out[16];
int work_time; //1208 --> 12H12M
} emp_data1;
int cmd_process(char* cmdx);
void p_err(int err);
int check_time(char *time);
int check_type(char *check_in, char *check_out);
void th_func(void);
void print_help(void);
int clean_data(char *fileaddr);
int request_data(char *fileaddr, char* cmdx);
int check_inout(char *fileaddr, char* cmdx);
int type_check(char* check_in, char *check_out, int* outlen);
char* ret_typestr(int typecode);
//char* analy_cmd(char* cmdx, int* n);
#endif //end EMP_HEAD_H
以下内容全部为一个c文件(主c文件),其实也就只有这个c文件。加上上面的头文件,整个可以编译通过生成我们的考勤系统。只是因为优快云的语法高亮做的不好,如果代码太长的话,整个网页加载起来很慢,所以就分开为几小段了。
另外关于输入检查这一块,之前没有写一个函数,结果这个程序只能固定多少个字符,来进行偏移,少了不行,多了也不行,全都是用指针偏移来操作的。后来写了个函数(请参考从符号分隔的命令行获取任意参数的函数(逗号分隔,空格分隔等都可以)(2011-12-29 01:04)) ,但是,由于太懒,所以没有改写这个考勤系统。留给读者改改吧。
/*
*主c文件
*author:duanxufang
*time:
*description:考勤系统
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include "../include/emp_head.h"
#define FILE_IN "emp_record.datafile"
struct emp_data record[MAXNUM] = {0};
int main()
{
pthread_t th_id;
printf("will create thread!\n");
if(pthread_create(&th_id, NULL, (void*)th_func, NULL))
{
printf("create thread error!\n");
exit(1);
}
if(pthread_join(th_id, NULL))
{
printf("thread quit error!");
exit(1);
}
return 0;
}
void p_err(int err)
{
switch(err)
{
case ERR_TIME_INVALID : printf("[ERR:TIME INVALID]\n"); break;
case ERR_ID_INVALID : printf("[ERR:ID INVALID]\n"); break;
case ERR_CMD_INVALID : printf("[ERR:COMMAND INVALID]\n"); break;
case 0 : break;
default: printf("ERR:Not Known!\n");
}
return ;
}
void th_func(void)
{
char input_cmd[256] = {0};
print_help();
while(printf("cmd here>"),gets(input_cmd))
{
int err_no = 0;
if((err_no = cmd_process(input_cmd)) == ERR_EXIT_SYS)
{
printf("EXIT SYSTEM\n");
break;
}
p_err(err_no);
printf("\nplease input next cmd:\n");
}
return ;
}
void print_help(void)
{
printf("--------cmd help:-----------\n\"0\":clean all the records \"1\":checktime input\n");
printf("\"2\":request records q/Q for quit system\n");
printf("h/H for help\n");
printf("cmd format is: 1,0001,duan001,18:56\n \
[id] like 0001 must be 4 chars\n \
[name] like duan001 must be 7 chars\n");
printf("--------cmd help end--------\n");
return ;
}
int cmd_process(char* cmdx)
{
printf("Your cmd: %s\n", cmdx);
int cmd_id = (int)(cmdx[0]-'0');
switch(cmd_id)
{
case 0: clean_data(FILE_IN); break;
case 1: check_inout(FILE_IN, cmdx); break;
case 2: request_data(FILE_IN, cmdx); break;
case 'h'-'0':
case 'H'-'0': print_help(); break;
case 'q'-'0':
case 'Q'-'0': return ERR_EXIT_SYS; //quik system;
default: return ERR_CMD_INVALID;
}
return 0;
}
int clean_data(char *fileaddr)
{
int count = 0;
char buf[60000];
int read_n = 0;
int i = 0;
struct emp_data *pemp = (struct emp_data *)buf;
FILE *fptr;
printf("clean_data()\n");//for debug
if(!(fptr = fopen(FILE_IN, "w")) )
{
printf("in clean _data open file[%s] failed!\n", FILE_IN);
return 1;
}
if(!(read_n = fread(buf, 1, 60000, fptr)))
{
printf("no record!");
return 1;
}
count =read_n/(sizeof(struct emp_data));
for(i =0; i < count; i++)
{
pemp[i].type = PUNCH_ABNORMAL;
strcpy(pemp[i].check_in, "");
strcpy(pemp[i].check_out, "");
pemp[i].work_time = 0;
}
fwrite(buf, 1, read_n, fptr);
read_n = fread(buf, 1, 60000, fptr);
for(i =0; i < count; i++)
{
printf("%d ", pemp[i].id);
printf("%s ", pemp[i].name);
printf("%s ", ret_typestr(pemp[i].type));
printf("%s ", pemp[i].check_in);
printf("%s ", pemp[i].check_out);
printf("%d\n", pemp[i].work_time);
}
fclose(fptr);
return 0;
}
//request_data
int request_data(char *fileaddr, char* cmdx)
{
int count = 0;
char buf[60000];
int read_n = 0;
int i = 0;
struct emp_data *pemp = (struct emp_data *)buf;
printf("in request_data()\n");
FILE *fptr;
if(!(fptr = fopen(FILE_IN, "r")) )
{
printf("in request_data open file[%s] failed!\n", FILE_IN);
return 1;
}
if(!(read_n = fread(buf, 1, 60000, fptr)))
{
printf("no record!");
return 1;
}
count =read_n/(sizeof(struct emp_data));
if(strlen(cmdx)==1)
{
for(i =0; i < count; i++)
{
printf("%4d ", pemp[i].id);
printf("%10s ", pemp[i].name);
printf("%-16s ", ret_typestr(pemp[i].type));
printf("%6s ", pemp[i].check_in);
printf("%6s ", pemp[i].check_out);
printf("%6d\n", pemp[i].work_time);
}
}
else
{
for(i =0; i < count; i++)
{
if(pemp[i].id==atoi(cmdx+2))
{
printf("%4d ", pemp[i].id);
printf("%10s ", pemp[i].name);
printf("%-16s ", ret_typestr(pemp[i].type));
printf("%6s ", pemp[i].check_in);
printf("%6s ", pemp[i].check_out);
printf("%6d\n", pemp[i].work_time);
}
}
}
fclose(fptr);
return 0;
}
//check_inout的前半部分
int check_inout(char *fileaddr, char* cmdx)
{
//取得数量
int count = 0, read_n = 0;
int worktime_len = 0;
int i = 0;
char buf[60000]={0};
int emp_id = atoi(cmdx+2);
struct emp_data *pemp = (struct emp_data *)buf;
printf("in check_inout() \n");
if(strlen(cmdx)<=2)
{
p_err(ERR_CMD_INVALID);
return 1;
}
if((atoi(cmdx+2)>1000)||(atoi(cmdx+2)<1))
{
p_err(ERR_ID_INVALID);
return 1;
}
//检查时间格式
if((cmdx[17]!=':')||(atoi(cmdx+15)>23)||(atoi(cmdx+15)<0)||
(atoi(cmdx+18)>59)||(atoi(cmdx+18)<0))
{
p_err(ERR_TIME_INVALID);
return 1;
}
FILE *fptr;
if(!(fptr = fopen(FILE_IN, "r+")) )
{
printf("open file[%s] failed!\n", FILE_IN);
return 1;
}
read_n = fread(buf, 1, 60000, fptr);
printf("read_n is: %d \n", read_n);
count =read_n/(sizeof(struct emp_data));
fclose(fptr);
check_inout的中间部分
for(i = 0; i < count; i++)
{
if( (pemp->id)== emp_id)
{
//更新刷卡记录
//strncpy 后面这个参数6害惨了我! 其实编译的时候会提示一个strncpy的警告!
strncpy(pemp->check_out, cmdx+15, 6); //!!!之前的值为5,最后必需写一个'\0',且这个'\0'包含在6中会发生段错误
//printf("-------typecheck----");
pemp->type = type_check(pemp->check_in, pemp->check_out, &worktime_len);
pemp->work_time = worktime_len;//worktime();
if(!(fptr = fopen(FILE_IN, "w")) )
{
printf("open file[%s] failed!\n", FILE_IN);
return 1;
}
read_n=fwrite(buf,1,count*(sizeof(struct emp_data)),fptr);
fclose(fptr);
printf("if [0 count]---write bytes :%d\n", read_n);
break;
}
pemp++;
}
//如果不存在这个人的刷卡记录,包括没有任何记录
if(i == count)
{
//把结构数据集的指针指向要写入数据的位置
struct emp_data emp_data2;
pemp = &emp_data2;
pemp->id = emp_id;
bzero(pemp->name, 8);
strncpy(pemp->name, cmdx+7, 7);//必需拷贝7个字符,最后一个字符置为'\0'
pemp->type = PUNCH_ABNORMAL;
strncpy(pemp->check_in, cmdx+15, 6);
strcpy(pemp->check_out, "");
pemp->work_time = 0;
if(!(fptr = fopen(FILE_IN, "a")) )
{
printf("open file[%s] failed!\n", FILE_IN);
return 1;
}
read_n=fwrite(pemp,1,sizeof(struct emp_data),fptr);
fclose(fptr);
printf("if i== count---write bytes :%d,count %d\n", read_n, count);
}
return 0;
}
//检查早退迟到等,并可以计算工时,工时通过outlen指针输出
int type_check(char* check_in, char *check_out, int* outlen)
{
int in_hh, in_mm;
int out_hh, out_mm;
int hh = 0, mm = 0;
int flaglate = 0, flagearly = 0;
int flagt =0;
printf("in type_check()\n");
if((strlen(check_in)>1)&&(strlen(check_out)>1))
{
in_hh = atoi(check_in);
in_mm = atoi(check_in+3);
out_hh = atoi(check_out);
out_mm = atoi(check_out+3);
if((in_hh>8)||((in_hh==8)&&(in_mm>0)))
{
flaglate = 1;
flagt = WORK_LATE;
}
if((out_hh<17)||((out_hh==17)&&(out_mm<30)))
{
flagearly = 1;
flagt = LEAVE_EARLY;
}
if((in_hh>17)||((in_hh==17)&&(in_mm>=30))||
(out_hh<8)||((out_hh==8)&&(out_mm==0)))
{
printf("----1----abs");
flagt = ABSENT;
}
if(flaglate&&flagearly)
{
flagt =LATE_AND_LEARLY;
}
}
else if((strlen(check_in)<1)&&(strlen(check_out)<1))
{
printf("----2----abs");
flagt = ABSENT;
}
else
{
flagt = PUNCH_ABNORMAL;
}
//如果,参数outlen== -1 则不计算工时,否则计算
if(*outlen == -1) goto ret;
if((flagt == ABSENT)||(flagt == PUNCH_ABNORMAL)) //之前这里flagt == ABSENT少打了一个=号,害得结果又错了
{
*outlen = 0;
}
else
{
if(in_mm<=out_mm)
{
*outlen = (out_hh-in_hh)*100 + (out_mm-in_mm);
}
else
{
*outlen = (out_hh-in_hh-1)*100 + 60 + (out_mm-in_mm);
}
}
ret: return flagt;
}
char* ret_typestr(int typecode)
{
switch(typecode)
{
case 0: return "NORMAL";
case 1: return "ABSENT";
case 2: return "WORK_LATE";
case 3: return "LEAVE_EARLY";
case 4: return "LATE_AND_LEARLY";
case 5: return "PUNCH_ABNORMAL";
default: return "typecode not know!";
}
}