本文最后更新于 708 天前,其中的信息可能已经有所发展或是发生改变。
由于作者被舍友求着代写课设,迫于无奈写的,在文件操作中一番挣扎最后写出来勉强运行的东西,有一种重复造轮子的美,直接上代码了
// // Created by Shanwer on 2023/5/26. // EMS is short for Employee Management System // #include <stdio.h> #include <string.h> #include <stdlib.h> enum sex{female,male}; typedef struct { int ID; char name[30]; enum sex s; char from[20]; char department[35]; char title[30]; char job[20]; struct{ int transferJob; int transferDepartment; int transferDuty; int retirement;//0 for not retired,1 for retired; }status; }employee; void printEmployee(employee e){ if(e.s == 0) printf("员工信息为:%d %s female %s %s %s %s\n",e.ID,e.name,e.from,e.department,e.title,e.job); else printf("员工信息为:%d %s male %s %s %s %s\n",e.ID,e.name,e.from,e.department,e.title,e.job); } char * getLastIndex(char * s,int whetherInsertSpace){ //get the last index of string(including the first \0) and decide whether insert a space while(*s != '\0'){ s++; } if(whetherInsertSpace) { *s = ' '; s++; } return s; } int registerNewEmployee(){ FILE *tmpP = NULL; tmpP = fopen("employeeInfo.txt", "r"); employee tmpE;//发现存储的话其实可以直接一个char *更方便点,但是没考虑到 char buff[sizeof(employee)]; if(tmpP == NULL){ printf("打开文件失败\n");//读到最后一行 return 1; }else { while(!feof(tmpP)) { fgets(buff,sizeof(employee),tmpP); } REGISTER: fclose(tmpP); FILE *fp = NULL; fp = fopen("employeeInfo.txt", "a"); char LastID[5];//最多员工人数100000人,故为5 sscanf(buff,"%[^ ]", LastID);//截取字符串直到第一个空格 tmpE.ID = atoi(LastID)+1;//stdlib的字符串转整型 printf("要添加的工号为:%d\n",tmpE.ID); printf("输入员工姓名:"); scanf("%30s", tmpE.name); printf("输入员工性别,0为女,1为男:"); scanf("%d",&tmpE.s); printf("输入员工籍贯:"); scanf("%20s",tmpE.from); printf("输入员工部门:"); scanf("%35s",tmpE.department); printf("输入员工职称:"); scanf("%30s",tmpE.title); printf("输入员工职务:"); scanf("%20s",tmpE.job); printEmployee(tmpE); printf("确认登记吗,按y确认,其他键取消:"); char confirm = 'y'; char tempClearC; while((tempClearC = getchar()) != '\n');//清空输入缓冲区 scanf("%c",&confirm); if(confirm == 'y'){ fputs("\n",fp);//windows换行符为\r\n,但是实际操作发现会换行两次 char tmpRow[sizeof(employee)]; itoa(tmpE.ID,tmpRow,10); char *tmpRowP = tmpRow; tmpRowP = getLastIndex(tmpRowP,1); strncpy(tmpRowP,tmpE.name,30); tmpRowP = getLastIndex(tmpRowP,1); itoa(tmpE.s,tmpRowP,10); tmpRowP = getLastIndex(tmpRowP,1); strncpy(tmpRowP,tmpE.from,20); tmpRowP = getLastIndex(tmpRowP,1); strncpy(tmpRowP,tmpE.department,35); tmpRowP = getLastIndex(tmpRowP,1); strncpy(tmpRowP,tmpE.title,30); tmpRowP = getLastIndex(tmpRowP,1); strncpy(tmpRowP,tmpE.job,20); fputs(tmpRow,fp); fclose(fp); return 0; }else memset(&tmpE, 0, sizeof(tmpE));//不确认的话就清空临时结构体 goto REGISTER; } } int editEmployee() { //修改和删除行非常麻烦,弃坑 int readID;char tmpBuff[sizeof(employee)];//tmpBuff is written to but never read employee tmpE; printf("输入要修改的员工工号:"); scanf("%d", &tmpE.ID); FILE *fp = NULL; fp = fopen("employeeInfo.txt", "r+"); for (int i = 0; i < tmpE.ID; i++) { fgets(tmpBuff, sizeof(employee), fp);//读取到需求行的上一行,建立在数据文件结构正常的情况下,工号顺序递增,因此顺序读取 } fscanf(fp,"%d",&readID);//读取需求行的工号,以空格截断 if (tmpE.ID == readID) { EDIT: printf("输入员工姓名:"); scanf("%30s", tmpE.name); printf("输入员工性别,0为女,1为男:"); scanf("%d", &tmpE.s); printf("输入员工籍贯:"); scanf("%20s", tmpE.from); printf("输入员工部门:"); scanf("%35s", tmpE.department); printf("输入员工职称:"); scanf("%30s", tmpE.title); printf("输入员工职务:"); scanf("%20s", tmpE.job); printEmployee(tmpE); printf("确认操作吗,按y确认,其他键取消:"); char confirm = 'y'; char tempClearC; while ((tempClearC = getchar()) != '\n');//清空输入缓冲区 confirm = getchar(); if (confirm == 'y') { char tmpRow[sizeof(employee)]; char *tmpRowP = tmpRow; fgets(tmpBuff, sizeof(employee), fp);//读取到末尾 fseek(fp,-strlen(tmpBuff)+1,SEEK_CUR);//偏移当前行的长度,由于已经取掉了+1防止吞空格,如果超出文件范围则指针不会移动 strncpy(tmpRowP, tmpE.name, 30); tmpRowP = getLastIndex(tmpRowP, 1); itoa(tmpE.s, tmpRowP, 10); tmpRowP = getLastIndex(tmpRowP, 1); strncpy(tmpRowP, tmpE.from, 20); tmpRowP = getLastIndex(tmpRowP, 1); strncpy(tmpRowP, tmpE.department, 35); tmpRowP = getLastIndex(tmpRowP, 1); strncpy(tmpRowP, tmpE.title, 30); tmpRowP = getLastIndex(tmpRowP, 1); strncpy(tmpRowP, tmpE.job, 20); fputs(tmpRow, fp);//如果新的字符串比原来的字符串短的话就出问题了 fclose(fp); return 0; } else { memset(&tmpE, 0, sizeof(tmpE));//不确认的话就清空临时结构体 goto EDIT; } }else { printf("未查找到指定的员工!"); return 1; } } int findEmployee() { char tmpBuff[sizeof(employee)]; int ID;int readID; printf("输入要查找的员工工号:"); scanf("%d", &ID); FILE *fp = NULL; fp = fopen("employeeInfo.txt", "r"); for (int i = 0; i < ID; i++) { fgets(tmpBuff, sizeof(employee), fp);//读取到需求行的这一行,建立在数据文件结构正常的情况下,工号顺序递增,因此顺序读取 } fscanf(fp,"%d",&readID); fgetc(fp); if(readID == ID){ fgets(tmpBuff, sizeof(employee),fp); puts(tmpBuff); return 0; }else { printf("未查找到指定的员工!"); return 1; } } int printStatus(){ findEmployee(); return 0; } int main() { //为了逻辑正确,工号不可输入,而是由系统设置,从0递增 //最多员工人数100000人 //文件的第一行占用做默认值避免逻辑错误 //一个功能一个函数 int input; printf("欢迎使用企业人事管理系统\n" "1.登记新员工信息\n" "2.修改员工信息\n" "3.删除员工信息\n" "4.查找员工信息\n" "5.按工号,部门输出员工职称\n" "6.查询员工工作单位变化\n" "输入功能前的序号数字来选择功能:"); scanf("%d", &input); while (input < 1 || input > 6) { printf("错误的输入,输入功能前的序号数字来选择功能\n"); printf("输入功能前的序号数字来选择功能:"); scanf("%d", &input); } switch (input) { case 1: if(!registerNewEmployee()) { printf("创建成功!"); break; } else break; case 2: if(!editEmployee()){ printf("修改成功!"); break; } else break; case 3: //删除的思路是令一个二维字符数组来存储当前文件的所有行,再删除指定的一行,这得上链表,然后再存到临时文件,删除原来文件,复制过去才可以,过于复杂了 break; case 4: if(!findEmployee()){ printf("查找成功"); break; }else break; case 5: findEmployee();//不理解按工号,部门输出员工职称是什么意思 break; case 6: printStatus();//查询员工工作单位变化,原理上是输出结构体中嵌套的结构体,由于没有操作,未被初始化,因而不做更多操作 break; default: break; } }