本文最后更新于 542 天前,其中的信息可能已经有所发展或是发生改变。
由于作者被舍友求着代写课设,迫于无奈写的,在文件操作中一番挣扎最后写出来勉强运行的东西,有一种重复造轮子的美,直接上代码了
//
// 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;
}
}