C语言课程设计项目——职工信息管理系统

名人说:一花独放不是春,百花齐放花满园。——《增广贤文》
作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)

目录

      • 一、整体框架
        • 1、整体模块
        • 2、系统说明
        • 3、数据类型说明
      • 二、主要功能函数分析
        • 1、注册登录
        • 2、录入职工信息
        • 3、显示职工信息
        • 4、修改职工信息
        • 5、删除职工信息
        • 6、保存职工信息
      • 三、完整代码及注释
      • 四、运行页面展示
      • 五、总结与收获

以下代码个人分享出来,仅供学习交流,且仅在CSDN平台发布,未经授权禁止二次转发。

一、整体框架

1、整体模块

在这里插入图片描述

2、系统说明

《职工信息管理系统》用链表,文件设计方法,各部分利用链表运行,结构清晰,较好地利用了链表等数据类型,主要语句加了上适当的注释,将难以理解的过程,变得更加简洁易懂。

该系统能够实现对职工信息的输入、显示、保存、删除、修改,特别还有管理员的注册与登录等操作。在设计的过程中,建立了清晰的结构体,能进行简单的界面设计,C语言中的基本语句、函数、数组、结构体、文件等。

本程序开发环境为Dev c++ MinGW GCC10.3。

3、数据类型说明

在这里插入图片描述

二、主要功能函数分析

1、注册登录

1️⃣代码

//注册账号
void add_user(void)				
{  
//    FILE *fp;   char str[101];  system("cls");  printf("\n");printf("\t\t\t请输入账号:\n\n\t\t\t   ");  scanf("%s",str);while(strlen(str)>16 || check_exist(str)) //使用循环而不是递归,并且增加一个检查账号是否存在的函数{if(strlen(str)>16)printf("\t\t账号长度大于16位,请重新输入\n");elseprintf("\t\t该账号已被注册,请重新注册\n");system("PAUSE");  system("cls");  printf("\n");  printf("\t\t\t请输入账号:\n\n\t\t\t   ");  scanf("%s",str);}	strcpy(user[user_count].ID,str); //使用user_count而不是iprintf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);while(strlen(str)>16){system("cls");printf("\n");printf("\t\t密码长度大于16位,请重新输入\n\n");printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);	} strcpy(user[user_count].password,str); //使用user_count而不是iprintf("\t\t\t请再次输入密码:\n\n\t\t\t   ");  scanf("%s",str);  while(strcmp(user[user_count].password,str)!=0) //使用循环而不是递归{  printf("\t\t两次密码不一致,请重新输入\n\n"); printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);while(strlen(str)>16){system("cls");printf("\n");printf("\t\t密码长度大于16位,请重新输入\n\n");printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);	} strcpy(user[user_count].password,str); //使用user_count而不是iprintf("\t\t\t请再次输入密码:\n\n\t\t\t   ");  scanf("%s",str);   }save_user();//将账号写入磁盘 printf("\t\t\t账号申请成功\n\n\t\t\t");  user_count++;if(user_count>=1010) //检查是否超出数组范围{printf("\t\t已达到最大账号数量,无法再添加新账号\n\n");}system("PAUSE");user_menu();   
}//检查账号是否存在
bool check_exist(char* str) //增加一个检查账号是否存在的函数,返回true或false
{int i;for(i=0;i<user_count;i++)if(strcmp(user[i].ID,str)==0)return true;return false;
}//登录账号
void login_user(void)			
{int i,flag=0;char str[20];system("cls");  printf("\n");printf("\t\t\t请输入账号:\n\n\t\t\t   ");scanf("%s",str);for(i=0;i<user_count;i++)if(strcmp(user[i].ID,str)==0){flag=1;break;}if(flag==0){int n;printf("\t\t\t该账号不存在!\n\t\t\t请输入你的选择\n");printf("\t\t\t<---------------->\n"); printf("\t\t\t |0.返回上层菜单 |\n");printf("\t\t\t<---------------->\n");printf("\t\t\t |1.退出系统     |\n");printf("\t\t\t<---------------->\n");  printf("\t\t\t请输入你的选择:\n");printf("\t\t\t");scanf("%d",&n);switch(n){case 0:user_menu();break;case 1:exit(0);break;}system("cls");  printf("\n");login_user(); return;}printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);while(strcmp(user[i].password,str)!=0){system("cls");  printf("\n");printf("\t\t\t密码错误,请重新输入\n\n\t\t\t\t");scanf("%s",str);	}printf("\t\t\t登录成功\n\n\t\t\t");system("PAUSE");choose_menu();
} 

2️⃣函数实现过程

  • 第一个函数是add_user,其功能是注册账号。首先清空屏幕,然后提示用户输入账号,并用一个字符串str存储。之后用一个循环检查账号的长度是否超过16位,以及账号是否已经存在(调用了第二个函数check_exist)。如果有问题,就让用户重新输入。如果没有问题,就把账号复制到user[user_count].ID中,其中user是一个结构体数组,user_count是一个全局变量,表示当前的账号数量。接下来,提示用户输入密码,并用同样的字符串str存储。然后它用另一个循环检查密码的长度是否超过16位,如果是,就让用户重新输入。如果不是,就把密码复制到user[user_count].password中。然后它提示用户再次输入密码,并用同样的字符串str存储。然后它用第三个循环检查两次输入的密码是否一致,如果不一致,就让用户重新输入。如果一致,就调用第三个函数save_user,把账号信息写入磁盘。然后它打印出账号申请成功的信息,并把user_count加一。最后,它检查是否达到了最大账号数量(1010),如果是,就打印出无法再添加新账号的信息。然后它暂停程序,并返回用户菜单(调用了另一个函数user_menu)。

  • 第二个函数是check_exist,它的功能是检查账号是否存在。首先接受一个字符串参数str,表示要检查的账号。之后用一个循环遍历所有已经注册的账号(存储在结构体数组user中),并用字符串比较函数strcmp判断是否有相同的账号。如果有,就返回真值(true)。如果没有,就返回假值(false)。

  • 第三个函数是login_user,其功能是登录账号。首先清空屏幕,然后提示用户输入账号,并用一个字符串str存储。接着用一个循环遍历所有已经注册的账号(存储在结构体数组user中),并用字符串比较函数strcmp判断是否有相同的账号。如果有,就把一个标志变量flag设为1,并跳出循环。如果没有,就打印出该账号不存在的信息,并让用户选择返回上层菜单(调用了另一个函数user_menu)或退出系统(调用了系统函数 exit)。然后它清空屏幕,并递归地调用自己(这里可以改成循环)。如果找到了相同的账号,就提示用户输入密码,并用同样的字符串 str 存储。然后它用一个循环检查密码是否正确(和对应的 user[i].password 比较),如果不正确,就让用户重新输入。如果正确,就打印出登录成功的信息,并暂停程序。然后它进入选择菜单(调用了另一个函数 choose_menu)。

2、录入职工信息

1️⃣代码

//录入信息函数
void Add(List L)     			     
{Position TmpCell;int number;char n[20];printf("\n请输入所要创建的职工号:  ");                         //提示输入职工号scanf("%d",&number);                                if(!IsLast(FindNumPrevious(number,L),L))             //连续调用 职工号前驱指针查找函数 判断链尾函数,判断该职工号是否已存在{printf("\n职工号 %d 已存在!!!\n\n",number);TurnBack();                                      //调用返回上一菜单函数return;                                          //退出并返回上一级菜单}printf("\n请输入该职工的姓名:  ");                       //保存职工姓名scanf("%s",n);                           if(!IsLast(FindNamePrevious(n,L),L))     //连续调用 职工姓名前驱指针查找函数 判断链尾函数,判断该职工姓名是否已存在{printf("\n职工姓名 %s 已存在!!!\n\n",n);TurnBack();                                      //调用返回上一菜单函数return;                                          //退出并返回上一级菜单}TmpCell=(Position)malloc(sizeof(struct Employee));   //创建新结点if(TmpCell==NULL){printf("\n添加失败,内存不足!!!\n\n");                  //添加失败,提示内存不足system("pause");                                 //暂停屏幕显示return;                                          //返回上一级菜单}TmpCell->num=number;                                 //保存职工号strcpy(TmpCell->name,n);                             //保存姓名printf("\n请输入该职工的工作部门:  ");                   //保存工作部门scanf("%s",TmpCell->department);printf("\n请输入该职工的职称:  ");                       //保存职称scanf("%s",TmpCell->Title);  printf("\n请输入该职工的入厂时间(格式为:年/月/日):  ");  //保存入厂时间scanf("%s",TmpCell->time);                         printf("\n请输入该职工的工资(单位:元):  ");              //保存工资scanf("%d",&TmpCell->money);   TmpCell->Next=L->Next;                               //将结点TmpCell插入到链表中L->Next=TmpCell;                                     printf("\n职工 %s 的信息创建成功!!!\n",TmpCell->name);   //提示创建成功Save(L);                                             //调用 信息保存函数TurnBack();                                          //调用 返回上一菜单函数return;                                              //退出并返回上一级菜单
}

2️⃣函数实现过程

  • 这个函数是Add,它的功能是录入一个新员工的信息,并把它插入到链表中。其中接受一个参数L,表示一个员工链表。首先定义了一个指针变量TmpCell用来创建新结点,一个整型变量number用来存储职工号,一个字符数组变量n用来存储姓名。然后它打印出提示信息,让用户输入要创建的职工号,并用整型变量number存储。接着它调用了两个函数:FindNumPreviousIsLast,传入职工号和链表,判断该职工号是否已经存在于链表中。如果存在,就打印出错误信息,并调用另一个函数TurnBack返回上一菜单,并退出函数。如果不存在,就继续打印出提示信息,让用户输入该员工的姓名,并用字符数组变量n存储。之后它调用了两个函数:FindNamePreviousIsLast,传入姓名和链表,判断该姓名是否已经存在于链表中。如果存在,就也打印出错误信息,并调用另一个函数 TurnBack 返回上一菜单,并退出函数。如果不存在,就为新结点分配内存空间(调用了系统函数 malloc),并检查是否分配成功(即 TmpCell 是否为空)。如果不成功,就打印出内存不足的信息,并暂停程序(调用了系统函数 pause),并退出函数。如果成功,就把职工号和姓名分别复制到新结点的相应字段中(使用了字符串复制函数 strcpy)。接着它继续打印出提示信息,让用户输入该员工的其他信息,包括工作部门、职称、入厂时间和工资,并分别复制到新结点的相应字段中。然后它把新结点插入到链表的头部(即头结点的下一个位置),并打印出创建成功的信息。紧接着它调用了另一个函数 Save ,把链表中的员工信息保存到磁盘中。最后,调用了另一个函数 TurnBack 返回上一菜单,并退出函数。
3、显示职工信息

1️⃣代码

//职工信息打印函数
void PrintEmployee(Position P)      
{printf("\n该职工信息如下:\n");printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");printf("  职工号    姓名     工作部门      职称         入厂时间      工资      \n"); printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");printf("   %-d         %-s        %-s             %-s            %-s             %-d\n",P->num,P->name,P->department,P->Title,P->time,P->money);printf("\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
}//职工号显示函数
void ViewNum(List L)           	 
{ Position P;int number;printf("\n请输入所要查询的职工号:  ");scanf("%d",&number);P=FindNumPrevious(number,L);	 //调用职工号前驱指针查找函数,获得所需显示结点的前一结点if(IsLast(P,L)==1)               //判断是否存在该员工printf("\n无职工号为 %d 的员工!!!\n\n",number);elsePrintEmployee(P->Next);      //调用职工信息打印函数TurnBack();                      //调用返回上一菜单函数return;                          //返回上一菜单
}//部门信息显示函数
void ViewDepartment(List L)      
{Position P;PtrToTitle P1,L1;char c[20];int num,money;L1=NULL;L1=MakeEmptyTitle(L1);                   //调用职称链表创建函数num=money=0;printf("请输入所要查询的部门名称:  ");scanf("%s",c);P=L->Next;while(P!=NULL&&strcmp(c,P->department)!=0)P=P->Next;if(P==NULL){printf("\n无名称为 %s 的部门\n\n",c);TurnBack();                          //调用返回上一菜单函数return;}printf("\n该部门职工信息如下:\n");printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");printf("   职工号   姓名    工作部门      职称     入厂时间    工资\t\n"); printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");P=L->Next;while(P!=NULL){if(strcmp(c,P->department)==0){printf("   %-d         %-s       %-s             %-s         %-s          %-d\n",P->num,P->name,P->department,P->Title,P->time,P->money);L1=InsertTitle(P->Title,L1);num++;money+=P->money;}P=P->Next;}printf("\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - -\n");printf("该部门的统计情况如下:\n 总人数为: %d 人\n 平均工资为: %.2f 元\n",num,(float)money/num);P1=L1->Next;while(P1!=NULL){printf(" 职称为 %s 的共:  %d 人\n",P1->title,P1->num);P1=P1->Next;}putchar('\n');TurnBack();                               //调用返回上一菜单函数return;                                   //退出并返回上一级菜单
}  

2️⃣函数实现过程

  • 这个函数是PrintEmployee,其功能是打印出一个员工结点的信息。接受一个参数P,表示一个员工结点。接着先打印出提示信息,表示要显示的员工信息。然后它打印出一个表格的表头,包括职工号、姓名、工作部门、职称、入厂时间和工资等字段。之后它打印出指针变量P所指向的结点的相应字段的值,按照一定的格式对齐。最后,它打印出一个表格的表尾,表示结束。

  • 第一个函数是ViewNum,该函数的功能是显示某个职工号对应的员工信息。接受一个参数L,表示一个员工链表。它首先打印出提示信息,让用户输入要查询的职工号,并用一个整型变量number存储。然后它调用了另一个函数FindNumPrevious,传入职工号和链表,返回该职工号对应的结点的前一个结点,用一个指针变量P存储。然后它调用了另一个函数IsLast,传入指针和链表,判断该指针是否指向链表的最后一个结点(即空结点)。如果是,就说明没有找到该职工号对应的员工,就打印出错误信息。如果不是,就说明找到了该职工号对应的员工,就调用另一个函数PrintEmployee,传入指针的下一个结点(即目标结点),打印出该员工的信息。最后,它调用了另一个函数TurnBack,返回上一菜单,并退出函数。

  • 第二个函数是ViewDepartment,其功能是显示某个部门的员工信息和统计情况。接受一个参数L,表示一个员工链表。接着定义了几个变量:一个指针变量P用来遍历链表,一个指向职称结构体的指针变量P1和一个指向职称链表的指针变量L1用来统计不同职称的人数,一个字符数组变量c用来存储要查询的部门名称,两个整型变量nummoney用来统计部门的总人数和总工资。然后它把职称链表初始化为空(调用了另一个函数 MakeEmptyTitle),并把总人数和总工资设为0。之后它打印出提示信息,让用户输入要查询的部门名称,并用字符数组变量 c 存储。然后它把指针 P 指向链表的第一个结点(即头结点的下一个结点),并用一个循环找到第一个属于该部门的员工结点。如果没有找到(即 P 为空),就打印出错误信息,并调用另一个函数 TurnBack 返回上一菜单,并退出函数。如果找到了(即 P 不为空),就打印出该部门员工信息的表头,并把指针 P 重新指向链表的第一个结点(即头结点的下一个结点)。然后它用另一个循环遍历整个链表,如果某个结点属于该部门(即部门名称和字符数组变量 c 相同),就打印出该员工的信息,并把该员工的职称插入到职称链表中(调用了另一个函数 InsertTitle),并把总人数加一,总工资加上该员工的工资。循环结束后,它打印出该部门的统计情况,包括总人数、平均工资和不同职称的人数(遍历职称链表)。最后,它调用另一个函数 TurnBack 返回上一菜单,并退出函数。

4、修改职工信息

1️⃣代码

//信息修改函数
void Mod(List L)          		 		
{while(1){char a;Position P;system("cls");                    //实现清屏ModMeun();                        //调用修改菜单fflush(stdin);                    //清除键盘缓冲区a=Test1(getchar(),'1','3');       //调用菜单输入检测函数switch(a){case '1':                         //职工号修改{int number;system("cls");  printf("\n请输入所要修改的职工信息的职工号:  ");scanf("%d",&number);P=FindNumPrevious(number,L);	 //调用职工号前驱指针查找函数,获得所需显示结点的前一结点if(IsLast(P,L)==1)               //判断是否存在该员工{printf("\n无职工号为 %d 的员工!!!\n\n",number);TurnBack();                      //调用返回上一菜单函数}elseMod1(P->Next,L);     //调用修改的部分函数break;                   //返回上一菜单}case '2':	return;}}
}//修改的部分函数  
void Mod1(Position P,List L)        	  
{while(1){char a;PrintEmployee(P);		          //调用职工信息打印函数     ModMeun1();                       //调用修改菜单fflush(stdin);                    //清除键盘缓冲区a=Test1(getchar(),'1','7');       //调用菜单输入检测函数switch(a){case '1': system("cls");  ModNum(P,L);         break;  //职工号修改case '2': system("cls");  ModName(P,L);        break;  //职工姓名修改case '3': return;}}
}//职工号修改函数
void ModNum(Position P,List L)			
{int b;       printf("\n请输入新的职工号:  ");    scanf("%d",&b);  if(!IsLast(FindNumPrevious(b,L),L))     //连续调用 职工号前驱指针查找函数 判断链尾函数,判断该职工号是否已存在printf("\n职工号 %d 已存在!!!\n\n",b);else{P->num=b;           Save(L);         //调用信息保存函数}TurnBack();          //调用返回上一菜单函数return;              //返回上一级菜单并退出
}//职工姓名修改函数
void ModName(Position P,List L)       	
{char c[20]; printf("\n请输入新的职工姓名:  ");  scanf("%s",c);   if(!IsLast(FindNamePrevious(c,L),L))     //连续调用 职工姓名前驱指针查找函数 判断链尾函数,判断该职工姓名是否已存在printf("\n职工姓名 %s 已存在!!!\n\n",c);else{strcpy(P->name,c);           Save(L);         //调用信息保存函数}TurnBack();          //调用返回上一菜单函数return;              //返回上一级菜单并退出
}

2️⃣函数实现过程

  • 第一个函数是Mod,其功能是修改员工信息。接受一个参数L,表示一个员工链表。它用一个无限循环实现菜单的重复显示和选择。之后它首先清空屏幕(调用了系统函数 system),然后调用了另一个函数 ModMeun ,显示修改菜单的选项。然后它清除键盘缓冲区(调用了系统函数 fflush),并让用户输入一个字符,并用另一个函数 Test1 检测该字符是否在 '1''3'之间。如果是,就根据字符的值执行相应的操作。如果是 '1',就表示要修改职工号,就进入第二个函数 Mod1 的调用。如果是 '2',就表示要返回上一菜单,就退出循环和函数。

  • 第二个函数是Mod1,该函数的功能是修改某个员工结点的信息。接受两个参数:一个指针变量 P 表示要修改的员工结点,一个指针变量 L 表示员工链表。它用了一个无限循环实现菜单的重复显示和选择。接着先调用了另一个函数 PrintEmployee ,传入指针变量 P ,打印出该员工的信息。然后它调用了另一个函数 ModMeun1 ,显示修改菜单的选项。然后它清除键盘缓冲区(调用了系统函数 fflush),并让用户输入一个字符,并用另一个函数 Test1 检测该字符是否在 '1''7'之间。如果是,就根据字符的值执行相应的操作。如果是 '1',就表示要修改职工号,就清空屏幕(调用了系统函数 system),并进入第三个函数 ModNum 的调用。如果是 '2',就表示要修改姓名,就清空屏幕(调用了系统函数 system),并进入第四个函数 ModName 的调用。如果是 '3',就表示要返回上一菜单,就退出循环和函数。

  • 第三个函数是ModNum,其功能是修改某个员工结点的职工号。接受两个参数:一个指针变量 P 表示要修改的员工结点,一个指针变量 L 表示员工链表。它首先定义了一个整型变量 b用来存储新的职工号,并打印出提示信息让用户输入新的职工号,并用整型变量 b存储。然后它调用了两个函数:FindNumPreviousIsLast,传入新的职工号和链表,判断该职工号是否已经存在于链表中。如果存在,就打印出错误信息。如果不存在,就把新的职工号复制到指针变量 P 所指向的结点的相应字段中,并调用另一个函数 Save 把链表中的员工信息保存到磁盘中。最后,它调用了另一个函数 TurnBack 返回上一菜单,并退出函数。

  • 第四个函数是ModName,该函数功能是修改某个员工结点的姓名。接受两个参数:一个指针变量 P 表示要修改的员工结点,一个指针变量 L 表示员工链表。该函数首先定义了一个字符数组变量 c用来存储新的姓名,并打印出提示信息让用户输入新的姓名,并用字符数组变量 c存储。然后它调用了两个函数:FindNamePreviousIsLast,传入新的姓名和链表,判断该姓名是否已经存在于链表中。如果存在,就打印出错误信息。如果不存在,就把新的姓名复制到指针变量 P 所指向的结点的相应字段中(使用了字符串复制函数 strcpy),并调用另一个函数 Save 把链表中的员工信息保存到磁盘中。最后,它调用了另一个函数 TurnBack 返回上一菜单,并退出函数。

5、删除职工信息

1️⃣代码

//职工号删除函数
void DeleteNum(List L) 			
{Position P,TmpCell;int number;printf("\n请输入所要删除的职工信息的职工号:  ");scanf("%d",&number);P=FindNumPrevious(number,L);	 //调用职工号前驱指针查找函数,获得所需显示结点的前一结点if(IsLast(P,L)==1)               //判断是否存在该员工printf("\n无职工号为 %d 的员工!!!\n\n删除失败!!!\n\n",number);else{PrintEmployee(P->Next);      //调用职工信息打印函数fflush(stdin);                   //清除键盘缓冲区printf("\n是否确认要删除?回复'Y'/'N'\n");if(getchar()=='Y'){TmpCell=P->Next;P->Next=TmpCell->Next;  free(TmpCell);printf("\n删除成功!!!\n\n");Save(L);                     //调用信息保存函数}}TurnBack();                      //调用返回上一菜单函数return;                          //退出并返回上一级菜单
}

2️⃣函数实现过程

  • 这个函数是DeleteNum,它的功能是删除某个职工号对应的员工信息。接受一个参数L,表示一个员工链表。它首先定义了两个指针变量:一个指针变量 P 用来存储要删除的员工结点的前一个结点,一个指针变量 TmpCell 用来存储要删除的员工结点。其还定义了一个整型变量 number 用来存储要删除的职工号,并打印出提示信息让用户输入要删除的职工号,并用整型变量 number 存储。然后它调用了另一个函数 FindNumPrevious,传入职工号和链表,返回该职工号对应的结点的前一个结点,用指针变量 P 存储。然后它调用了另一个函数 IsLast,传入指针和链表,判断该指针是否指向链表的最后一个结点(即空结点)。如果是,就说明没有找到该职工号对应的员工,就打印出错误信息。如果不是,就说明找到了该职工号对应的员工,就调用另一个函数 PrintEmployee,传入指针的下一个结点(即目标结点),打印出该员工的信息。然后它清除键盘缓冲区(调用了系统函数 fflush),并打印出确认信息,让用户输入 'Y''N'表示是否要删除该员工。如果用户输入 'Y',就把指针变量 TmpCell 指向要删除的员工结点(即指针变量 P 的下一个结点),然后把指针变量 P 的下一个结点改为指针变量 TmpCell 的下一个结点(即跳过要删除的结点),然后释放指针变量 TmpCell 所指向的内存空间(调用了系统函数 free),并打印出删除成功的信息。然后它调用了另一个函数 Save,把链表中的员工信息保存到磁盘中。最后,它调用了另一个函数 TurnBack,返回上一菜单,并退出函数。
6、保存职工信息

1️⃣代码

//信息保存函数 
void Save(List L)        
{FILE *fp;                                           //文件指针Position P;L=Sort(L);                                            //调用链表冒泡排序函数P=L;if((fp=fopen("职工信息.txt","w+"))==NULL)           //打开"职工信息.txt"文本文件{printf("无法打开文件!!!\n");system("pause");                                //暂停屏幕显示return;}fp=fopen("职工信息.txt","w+");                      //以读写的方式打开"职工信息.txt"文本文件while(P->Next!=NULL)                                //将内存中的数据输出到磁盘中{P=P->Next;                                      //信息从第一个有效结点开始保存,循环指向下一个有效结点if(fprintf(fp,"%d %s %s %s %s %d\n",P->num,P->name,P->department,P->Title,P->time,P->money)<0) break;  //向文件写入信息}printf("\n职工信息保存成功!!!\n\n");fclose(fp);return;
}

2️⃣函数实现过程

  • 这个函数是Save,其功能是把链表中的员工信息保存到磁盘中。其中接受一个参数L,表示一个员工链表。首先它定义了一个文件指针变量fp用来操作文件,和一个指针变量P用来遍历链表。然后它调用了另一个函数Sort,传入链表,对链表中的员工信息进行冒泡排序。接着它把指针变量P指向链表的头结点,并尝试以读写的方式打开一个名为"职工信息.txt"的文本文件,并用文件指针变量fp存储。如果打开失败(即fp为空),就打印出错误信息,并暂停程序(调用了系统函数 system),并退出函数。如果打开成功(即 fp 不为空),就再次以读写的方式打开该文件(这里可以省略)。然后它用一个循环遍历链表中的所有结点(从第一个有效结点开始),并用文件写入函数 fprintf 把每个结点的员工信息按照一定的格式写入到文件中。如果写入失败(即返回值小于0),就跳出循环。循环结束后,它打印出保存成功的信息,并关闭文件(调用了系统函数 fclose),并退出函数。

三、完整代码及注释

//创作者:Code_流苏(CSDN)
//未经允许,禁止转载发布,可自己学习使用
//头文件声明 
#include               
#include				
#include				
#include 			
#include				//结构体声明、职工工资结构体 
struct Employee;                         			//职工工资结构体声明
typedef struct Employee *PtrToNode;      			//结构体指针定义                
typedef PtrToNode List;                  			//链表头指针定义
typedef PtrToNode Position;              			//链表结点指针定义 //职称结构体
struct Title;                            			//职称结构体声明
typedef struct Title *PtrToTitle;        			//结构体指针定义                //链表函数声明、空链表创建函数 
int IsEmpty(List L);                            	//判断空链表函数
int IsLast(Position P,List L);                  	//判断链尾函数Position FindNumPrevious(int number,List L);    	//职工号前驱指针查找函数 
Position FindNamePrevious(char name[],List L);  	//职工姓名前驱指针查找函数 
List Sort(List L);                              	//链表冒泡排序函数
PtrToTitle MakeEmptyTitle(PtrToTitle L1);           //空职称链表创建函数
PtrToTitle InsertTitle(char t[20],PtrToTitle L1);   //职称插入函数//文件函数声明
List Init(List L);                 		//初始化函数
void Save(List L);                 		//信息保存函数//菜单函数声明
void MainMeun(void);                    //主菜单
void ViewMeun();                   		//显示菜单
void ModMeun();                   		//修改菜单
void ModMeun1();                   		//修改的部分菜单//职工管理函数声明
void Add(List L);                  		//信息录入函数
void View(List L);                 		//信息显示函数
void ViewNum(List L);              		//职工号显示函数
void ViewDepartment(List L);       		//部门信息显示函数//登录 
void user_menu(void);					//账号菜单
void add_user(void);					//注册账号 
void login_user(void);					//登录账号
void reset_password(void);				//修改密码
void save_user(void);					//将账号写入磁盘
void choose_menu(void);					//选择菜单bool check_exist(char* str);//修改 void Mod(List L);                       //信息修改函数
void Mod1(Position P,List L);           //修改的部分函数
void ModNum(Position P,List L);         //职工号修改函数
void ModName(Position P,List L);       	//职工姓名修改函数//删除 
void DeleteList(List L);                //链表删除函数
void DeleteNum(List L);            		//职工号删除函数void PrintEmployee(Position P);    		//职工工资打印函数
void TurnBack();                   		//返回上一菜单函数
char Test1(char a,char b,char c);  		//菜单输入检测函数int user_count=0;
//定义职工工资结构体
struct Employee           
{int num;               //职工号char name[20];         //姓名char department[20];   //工作部门char Title[20];        //职称char time[10];         //入厂时间  年/月/日  2018/6/29   int money;             //工资Position Next;         //Next指针 (指向下一结构体)
};
//职称结构体
struct Title
{char title[20];       //职称名称int num;              //部门职称人数struct Title* Next;   //Next指针
};
struct asccount{  char ID[20];  char password[20]; 
}user[1010];
//主函数int main()
{user_menu();List L=NULL;char a;L=Init(L);printf("\n\t\t输入回车键继续"); getchar();while(1){system("color be");system("cls");                      //实现清屏MainMeun();                         //调用 主菜单显示函数fflush(stdin);                      //清除键盘缓冲区a=Test1(getchar(),'0','7');         //菜单输入检测函数switch(a){case '0':  system("cls");  choose_menu();    break;case '1':  system("cls");  Add(L);           break;                    //调用 信息录入函数case '2':  system("cls");  View(L);          break;                    //调用 信息显示函数   case '3':  system("cls");  Mod(L);           break;                    //调用 信息修改函数case '4':  system("cls");  DeleteNum(L);     break;                    //调用 信息删除函数case '5':  system("cls");  Save(L);          system("pause");  break;  //调用 信息保存函数case '6':  return 0;                                                   //退出系统}}return 0;
}//链表函数
//空链表创建函数
List MakeEmpty(List L)                         
{if(L)                                      //相当于 if(L!=NULL) ,即指针L指向的空间不为空DeleteList(L);                       //删除原先链表L=(List)malloc(sizeof(struct Employee));   //创建新的空链表if(!L)                                     //相当于 if(L==NULL) ,即指针L指向的空间为空{printf("创建失败,内存不足!!!");        //创建失败,提示内存不足system("pause");                       //暂停屏幕显示return NULL;                           //返回上一级菜单}L->Next=NULL;                              //Next指针指向空return L;                                  //返回链表头
}//空职称链表创建函数
struct Title *MakeEmptyTitle(struct Title *L1)                         
{if(L1)                                      //相当于 if(L!=NULL) ,即指针L指向的空间不为空{struct Title *P;P=L1->Next;           //取链表头后的所有结点L1->Next=NULL;        //链表头指向空结点while(P!=NULL)       //依次释放链表头后所有结点的空间{free(P);P=P->Next;}}L1=(struct Title *)malloc(sizeof(struct Title));   //创建新的空链表if(!L1)                                     //相当于 if(L==NULL) ,即指针L指向的空间为空{printf("创建失败,内存不足!!!");        //创建失败,提示内存不足system("pause");                       //暂停屏幕显示return NULL;                           //返回上一级菜单}L1->Next=NULL;                              //Next指针指向空return L1;                                  //返回链表头
}//职称插入函数
PtrToTitle InsertTitle(char t[20],PtrToTitle L1)
{PtrToTitle P,TmpCell;if(L1->Next==NULL)                         //如果职称链表为空,则直接创建结点{TmpCell=(PtrToTitle)malloc(sizeof(struct Title));if(TmpCell==NULL)printf("\n超出空间!!!\n\n");else                                   //将新建结点插入链表{strcpy(TmpCell->title,t);TmpCell->Next=L1->Next;L1->Next=TmpCell;TmpCell->num=1;}}else{P=L1->Next;while(P!=NULL&&strcmp(P->title,t)!=0)P=P->Next;if(P==NULL){TmpCell=(PtrToTitle)malloc(sizeof(struct Title));if(TmpCell==NULL)printf("\n超出空间!!!\n\n");else                                   //将新建结点插入链表{strcpy(TmpCell->title,t);TmpCell->Next=L1->Next;L1->Next=TmpCell;TmpCell->num=1;}}elseP->num++;}return L1;
}//判断空链表函数
int IsEmpty(List L)             
{return L->Next==NULL;       //头结点的Next指针为空,则链表为空,返回值为1
}//判断链尾函数
int IsLast(Position P,List L)   
{return P->Next==NULL;       //结点P的Next指针为空,则P为最后一个结点,返回值为1
}//链表删除函数
void DeleteList(List L)   
{Position P;P=L->Next;           //取链表头后的所有结点L->Next=NULL;        //链表头指向空结点while(P!=NULL)       //依次释放链表头后所有结点的空间{free(P);P=P->Next;}
}//职工号前驱指针查找函数 
Position FindNumPrevious(int number,List L)       
{Position P;P=L;while(P->Next!=NULL&&P->Next->num!=number)  //判断P的Next指针是否为空,且P的下一个结点的职工号是否为查找的职工号P=P->Next;                              //查找下一个return P;                                   //返回该职工号的前驱指针
}//职工姓名前驱指针查找函数 
Position FindNamePrevious(char name[],List L)       
{Position P;P=L;while(P->Next!=NULL&&strcmp(name,P->Next->name)!=0)  //判断P的Next指针是否为空,且P的下一个结点的职工姓名是否为查找的职工姓名P=P->Next;                                       //查找下一个return P;                                            //返回该职工号的前驱指针
}//链表选择排序函数
List Sort(List L)
{Position P,Tmp1,Tmp2,Min;int i,j,num=0;P=L->Next;while(P!=NULL)   //获取总人数{num++;P=P->Next;}for(j=0;j<num-1;j++)  //通过总人数控制循环{P=L;for(i=0;i<j;i++)  //找到已排序部分的末尾{P=P->Next;}Tmp1=P->Next;  //未排序部分的第一个元素Tmp2=Tmp1->Next;  //未排序部分的第二个元素Min=Tmp1;  //假设最小元素为第一个元素while(Tmp2!=NULL)  //遍历未排序部分{if(Tmp2->num<Min->num)   //升序{Min=Tmp2;  //更新最小元素}Tmp2=Tmp2->Next;  //指向下一个元素}if(Min!=Tmp1)  //如果最小元素不是第一个元素,就交换它们的位置{Tmp2=Min->Next;  //保存最小元素的后继节点P->Next=Min;  //将最小元素放到已排序部分的末尾Min->Next=Tmp1;  //将原来的第一个元素放到最小元素的后面while(Tmp1->Next!=Min)  //找到原来第一个元素的前驱节点{Tmp1=Tmp1->Next;}Tmp1->Next=Tmp2;  //将原来第一个元素的前驱节点指向最小元素的后继节点}}return L;  }//注册登录菜单函数 
void user_menu(void)			 
{int choose;system("color be");system("cls");printf("\n\n\t\t*****************************************");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t 欢迎来到职工工资管理系统\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t      登录账号请按1\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t      注册账号请按2\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t      修改密码请按3\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t      退出系统请按0\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*****************************************");printf("\n\t\t\t\t");printf("\n\t\t\t       请输入选项:\n\t\t\t\t   ");scanf("%d",&choose);switch(choose){case 1:login_user(); break;case 2:add_user(); break;case 3:reset_password(); break;case 0:exit(0); default :printf("\n\t\t\t   输入错误,请重新输入\n\n\t\t\t    "); system("PAUSE");  system("cls"); user_menu(); }
}//注册账号
void add_user(void)				
{  
//    FILE *fp;   char str[101];  system("cls");  printf("\n");printf("\t\t\t请输入账号:\n\n\t\t\t   ");  scanf("%s",str);while(strlen(str)>16 || check_exist(str)) //使用循环而不是递归,并且增加一个检查账号是否存在的函数{if(strlen(str)>16)printf("\t\t账号长度大于16位,请重新输入\n");elseprintf("\t\t该账号已被注册,请重新注册\n");system("PAUSE");  system("cls");  printf("\n");  printf("\t\t\t请输入账号:\n\n\t\t\t   ");  scanf("%s",str);}	strcpy(user[user_count].ID,str); //使用user_count而不是iprintf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);while(strlen(str)>16){system("cls");printf("\n");printf("\t\t密码长度大于16位,请重新输入\n\n");printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);	} strcpy(user[user_count].password,str); //使用user_count而不是iprintf("\t\t\t请再次输入密码:\n\n\t\t\t   ");  scanf("%s",str);  while(strcmp(user[user_count].password,str)!=0) //使用循环而不是递归{  printf("\t\t两次密码不一致,请重新输入\n\n"); printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);while(strlen(str)>16){system("cls");printf("\n");printf("\t\t密码长度大于16位,请重新输入\n\n");printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);	} strcpy(user[user_count].password,str); //使用user_count而不是iprintf("\t\t\t请再次输入密码:\n\n\t\t\t   ");  scanf("%s",str);   }save_user();//将账号写入磁盘 printf("\t\t\t账号申请成功\n\n\t\t\t");  user_count++;if(user_count>=1010) //检查是否超出数组范围{printf("\t\t已达到最大账号数量,无法再添加新账号\n\n");}system("PAUSE");user_menu();   
}//检查账号是否存在
bool check_exist(char* str) //增加一个检查账号是否存在的函数,返回true或false
{int i;for(i=0;i<user_count;i++)if(strcmp(user[i].ID,str)==0)return true;return false;
}//将账号读入内存
void load_user(void)			
{  FILE *fp;fp=fopen("账号.txt","r"); while(fscanf(fp,"%s",user[user_count].ID)!=EOF){  fscanf(fp,"%s",user[user_count].password); user_count++;if(user_count>=1010) //检查是否超出数组范围{printf("\t\t已达到最大账号数量,无法再读取更多账号\n\n");break;}}fclose(fp);
}//将账号写入磁盘
void save_user(void)			
{int i;FILE *fp;  fp=fopen("账号.txt","w");for(i=0;i<user_count;i++) //使用{fprintf(fp,"%s\n",user[i].ID);  fprintf(fp,"%s\n",user[i].password); }  fclose(fp);  
}//登录账号
void login_user(void)			
{int i,flag=0;char str[20];system("cls");  printf("\n");printf("\t\t\t请输入账号:\n\n\t\t\t   ");scanf("%s",str);for(i=0;i<user_count;i++)if(strcmp(user[i].ID,str)==0){flag=1;break;}if(flag==0){int n;printf("\t\t\t该账号不存在!\n\t\t\t请输入你的选择\n");printf("\t\t\t<---------------->\n"); printf("\t\t\t |0.返回上层菜单 |\n");printf("\t\t\t<---------------->\n");printf("\t\t\t |1.退出系统     |\n");printf("\t\t\t<---------------->\n");  printf("\t\t\t请输入你的选择:\n");printf("\t\t\t");scanf("%d",&n);switch(n){case 0:user_menu();break;case 1:exit(0);break;}system("cls");  printf("\n");login_user(); return;}printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);while(strcmp(user[i].password,str)!=0){system("cls");  printf("\n");printf("\t\t\t密码错误,请重新输入\n\n\t\t\t\t");scanf("%s",str);	}printf("\t\t\t登录成功\n\n\t\t\t");system("PAUSE");choose_menu();
} 
//修改密码
void reset_password(void)		
{int i,flag=0;char str[20];system("cls");  printf("\n");printf("\t\t\t请输入账号:\n\n\t\t\t   ");scanf("%s",str);for(i=0;i<user_count;i++)if(strcmp(user[i].ID,str)==0){flag=1;break;}if(flag==0){printf("\t\t该账号不存在,请重新登录\n\n\t\t\t");system("PAUSE");system("cls");  printf("\n");reset_password(); return;}printf("\t\t\t请输入密码:\n\n\t\t\t   ");scanf("%s",str);while(strcmp(user[i].password,str)!=0){system("cls");  printf("\n");printf("\t\t\t密码错误,请重新输入\n\n\t\t\t\t");scanf("%s",str);	}printf("\t\t\t请输入新密码\n\n\t\t\t   "); scanf("%s",str);while(strlen(str)>16){printf("\t\t密码长度大于16位,请重新输入\n");system("PAUSE");  system("cls");  printf("\n");  scanf("%s",str);} strcpy(user[i].password,str);  printf("\t\t\t请再次输入密码:\n\n\t\t\t   ");  scanf("%s",str);  while(strcmp(user[i].password,str)!=0){  printf("\t\t两次密码不一致,请重新申请\n\n\t\t\t");  system("PAUSE");  system("cls");  printf("\n");  scanf("%s",str);} save_user();printf("\t\t\t修改成功\n\n\t\t\t"); system("PAUSE");user_menu();
}//登录后页面显示选择菜单
void choose_menu(void)			
{int choose;while(1){system("cls");printf("\n\n\t\t*****************************************");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t     欢迎来到选择菜单管理\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t      职工工资管理请按1\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*\t      返回到上一层请按0\t\t*");printf("\n\t\t*\t\t\t\t\t*");printf("\n\t\t*****************************************");printf("\n\t\t\t\t");printf("\n\t\t\t       请输入选项:\n\t\t\t\t   ");scanf("%d",&choose); switch(choose){case 0:system("cls");user_menu(); return;case 1:system("cls");MainMeun(); return;default:printf("\n\t\t\t   输入错误,请重新输入\n\n\t\t\t    "); system("PAUSE"); system("cls");}	 }		
} //调用菜单函数 显示主菜单
void MainMeun(void)  			 //主菜单 
{printf("\n\t\t                主菜单");printf("\n\t\t*******************************************");printf("\n\t\t*             1、录入信息                 *");printf("\n\t\t*             2、显示信息                 *");printf("\n\t\t*             3、修改信息                 *");printf("\n\t\t*             4、删除信息                 *");printf("\n\t\t*             5、保存信息                 *");printf("\n\t\t*             6、退出系统                 *");printf("\n\t\t*             0、返回上一层菜单           *");printf("\n\t\t*******************************************");printf("\n\n\t\t\t请输入您的选择:");
}//录入信息函数
void Add(List L)     			     
{Position TmpCell;int number;char n[20];printf("\n请输入所要创建的职工号:  ");                         //提示输入职工号scanf("%d",&number);                                if(!IsLast(FindNumPrevious(number,L),L))             //连续调用 职工号前驱指针查找函数 判断链尾函数,判断该职工号是否已存在{printf("\n职工号 %d 已存在!!!\n\n",number);TurnBack();                                      //调用返回上一菜单函数return;                                          //退出并返回上一级菜单}printf("\n请输入该职工的姓名:  ");                       //保存职工姓名scanf("%s",n);                           if(!IsLast(FindNamePrevious(n,L),L))     //连续调用 职工姓名前驱指针查找函数 判断链尾函数,判断该职工姓名是否已存在{printf("\n职工姓名 %s 已存在!!!\n\n",n);TurnBack();                                      //调用返回上一菜单函数return;                                          //退出并返回上一级菜单}TmpCell=(Position)malloc(sizeof(struct Employee));   //创建新结点if(TmpCell==NULL){printf("\n添加失败,内存不足!!!\n\n");                  //添加失败,提示内存不足system("pause");                                 //暂停屏幕显示return;                                          //返回上一级菜单}TmpCell->num=number;                                 //保存职工号strcpy(TmpCell->name,n);                             //保存姓名printf("\n请输入该职工的工作部门:  ");                   //保存工作部门scanf("%s",TmpCell->department);printf("\n请输入该职工的职称:  ");                       //保存职称scanf("%s",TmpCell->Title);  printf("\n请输入该职工的入厂时间(格式为:年/月/日):  ");  //保存入厂时间scanf("%s",TmpCell->time);                         printf("\n请输入该职工的工资(单位:元):  ");              //保存工资scanf("%d",&TmpCell->money);   TmpCell->Next=L->Next;                               //将结点TmpCell插入到链表中L->Next=TmpCell;                                     printf("\n职工 %s 的信息创建成功!!!\n",TmpCell->name);   //提示创建成功Save(L);                                             //调用 信息保存函数TurnBack();                                          //调用 返回上一菜单函数return;                                              //退出并返回上一级菜单
}//显示菜单
void ViewMeun()  				 
{printf("\n\t\t                显示信息菜单");printf("\n\t\t********************************************");printf("\n\t\t*            1、显示职工信息               *");printf("\n\t\t*            2、显示部门信息              *");printf("\n\t\t*            3、返回到主菜单               *");printf("\n\t\t********************************************");printf("\n\n\t\t\t请输入您的选择:");
}//信息显示函数
void View(List L)          		 
{while(1){char a;system("cls");                   //实现清屏ViewMeun();                      //调用显示菜单fflush(stdin);                   //清除键盘缓冲区a=Test1(getchar(),'1','4');      //调用菜单输入检测函数switch(a){case '1':	system("cls");  ViewNum(L);   break; 		 //显示职工信息case '2':	system("cls");  ViewDepartment(L); break;    //显示部门信息case '3':	return;}}
}//职工号显示函数
void ViewNum(List L)           	 
{ Position P;int number;printf("\n请输入所要查询的职工号:  ");scanf("%d",&number);P=FindNumPrevious(number,L);	 //调用职工号前驱指针查找函数,获得所需显示结点的前一结点if(IsLast(P,L)==1)               //判断是否存在该员工printf("\n无职工号为 %d 的员工!!!\n\n",number);elsePrintEmployee(P->Next);      //调用职工信息打印函数TurnBack();                      //调用返回上一菜单函数return;                          //返回上一菜单
}//部门信息显示函数
void ViewDepartment(List L)      
{Position P;PtrToTitle P1,L1;char c[20];int num,money;L1=NULL;L1=MakeEmptyTitle(L1);                   //调用职称链表创建函数num=money=0;printf("请输入所要查询的部门名称:  ");scanf("%s",c);P=L->Next;while(P!=NULL&&strcmp(c,P->department)!=0)P=P->Next;if(P==NULL){printf("\n无名称为 %s 的部门\n\n",c);TurnBack();                          //调用返回上一菜单函数return;}printf("\n该部门职工信息如下:\n");printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");printf("   职工号   姓名    工作部门      职称     入厂时间    工资\t\n"); printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");P=L->Next;while(P!=NULL){if(strcmp(c,P->department)==0){printf("   %-d         %-s       %-s             %-s         %-s          %-d\n",P->num,P->name,P->department,P->Title,P->time,P->money);L1=InsertTitle(P->Title,L1);num++;money+=P->money;}P=P->Next;}printf("\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - -\n");printf("该部门的统计情况如下:\n 总人数为: %d 人\n 平均工资为: %.2f 元\n",num,(float)money/num);P1=L1->Next;while(P1!=NULL){printf(" 职称为 %s 的共:  %d 人\n",P1->title,P1->num);P1=P1->Next;}putchar('\n');TurnBack();                               //调用返回上一菜单函数return;                                   //退出并返回上一级菜单
} //文件函数
//初始化函数
List Init(List L)            
{FILE *fp;                                               //文件指针Position TmpCell;int num=0;if((fp=fopen("职工信息.txt","r+"))==NULL)                //打开"职工信息.txt"文本文件{printf("\n\t\t无法打开文件或文件不存在\n");         //提示错误printf("\n\t\t正在尝试创建新文件....\n");fp=fopen("职工信息.txt","w");                       //创建"职工信息.txt"文本文件if((fp=fopen("职工信息.txt","r+"))==NULL)           //再次打开判断是否成功{printf("\t\t文件创建失败!!!\n");system("pause");                                //暂停屏幕显示return NULL;}}fp=fopen("职工信息.txt","r+");                           //以只读的方式打开"职工信息.txt"文本文件L=MakeEmpty(L);                                         //创建链表,以便存储文本文件中的信息while(1)                                                //将磁盘中的信息输出到内存中{TmpCell=(Position)malloc(sizeof(struct Employee));  //创建新结点if(TmpCell==NULL){printf("文件信息读取失败,系统内存不足!!!\n");   //添加失败,提示内存不足system("pause");                                //暂停屏幕显示return NULL;                                    //返回上一级菜单}if(fscanf(fp,"%d %s %s %s %s %d",&TmpCell->num,TmpCell->name,TmpCell->department,TmpCell->Title,TmpCell->time,&TmpCell->money)<0) break;  //将文件信息写入内存TmpCell->Next=L->Next;                              //将结点TmpCell插入到链表中L->Next=TmpCell;                                     num++;} printf("\n\t\t职工信息读取完成!!!\n");printf("\n\t\t目前共有 %d 名职工信息\n",num);fclose(fp);                                             //关闭文件return L;
}//信息保存函数 
void Save(List L)        
{FILE *fp;                                           //文件指针Position P;L=Sort(L);                                            //调用链表冒泡排序函数P=L;if((fp=fopen("职工信息.txt","w+"))==NULL)           //打开"职工信息.txt"文本文件{printf("无法打开文件!!!\n");system("pause");                                //暂停屏幕显示return;}fp=fopen("职工信息.txt","w+");                      //以读写的方式打开"职工信息.txt"文本文件while(P->Next!=NULL)                                //将内存中的数据输出到磁盘中{P=P->Next;                                      //信息从第一个有效结点开始保存,循环指向下一个有效结点if(fprintf(fp,"%d %s %s %s %s %d\n",P->num,P->name,P->department,P->Title,P->time,P->money)<0) break;  //向文件写入信息}printf("\n职工信息保存成功!!!\n\n");fclose(fp);return;
}//修改菜单函数
void ModMeun()  				 		
{printf("\n\t\t                 职工修改菜单");printf("\n\t\t********************************************");printf("\n\t\t*            1、根据查询职工号修改         *");printf("\n\t\t*            2、返回到主菜单               *");printf("\n\t\t********************************************");printf("\n\n\t\t\t请输入您的选择:");
}//信息修改函数
void Mod(List L)          		 		
{while(1){char a;Position P;system("cls");                    //实现清屏ModMeun();                        //调用修改菜单fflush(stdin);                    //清除键盘缓冲区a=Test1(getchar(),'1','3');       //调用菜单输入检测函数switch(a){case '1':                         //职工号修改{int number;system("cls");  printf("\n请输入所要修改的职工信息的职工号:  ");scanf("%d",&number);P=FindNumPrevious(number,L);	 //调用职工号前驱指针查找函数,获得所需显示结点的前一结点if(IsLast(P,L)==1)               //判断是否存在该员工{printf("\n无职工号为 %d 的员工!!!\n\n",number);TurnBack();                      //调用返回上一菜单函数}elseMod1(P->Next,L);     //调用修改的部分函数break;                   //返回上一菜单}case '2':	return;}}
}//修改的部分菜单
void ModMeun1()  			 			
{printf("\n\t\t             所要修改的部分");printf("\n\t\t********************************************");printf("\n\t\t*            1、职工号                     *");printf("\n\t\t*            2、职工姓名                   *");printf("\n\t\t*            3、返回上一菜单               *");printf("\n\t\t********************************************");printf("\n\n\t\t\t请输入您的选择:");
}//修改的部分函数  
void Mod1(Position P,List L)        	  
{while(1){char a;PrintEmployee(P);		          //调用职工信息打印函数     ModMeun1();                       //调用修改菜单fflush(stdin);                    //清除键盘缓冲区a=Test1(getchar(),'1','7');       //调用菜单输入检测函数switch(a){case '1': system("cls");  ModNum(P,L);         break;  //职工号修改case '2': system("cls");  ModName(P,L);        break;  //职工姓名修改case '3': return;}}
}//职工号修改函数
void ModNum(Position P,List L)			
{int b;       printf("\n请输入新的职工号:  ");    scanf("%d",&b);  if(!IsLast(FindNumPrevious(b,L),L))     //连续调用 职工号前驱指针查找函数 判断链尾函数,判断该职工号是否已存在printf("\n职工号 %d 已存在!!!\n\n",b);else{P->num=b;           Save(L);         //调用信息保存函数}TurnBack();          //调用返回上一菜单函数return;              //返回上一级菜单并退出
}//职工姓名修改函数
void ModName(Position P,List L)       	
{char c[20]; printf("\n请输入新的职工姓名:  ");  scanf("%s",c);   if(!IsLast(FindNamePrevious(c,L),L))     //连续调用 职工姓名前驱指针查找函数 判断链尾函数,判断该职工姓名是否已存在printf("\n职工姓名 %s 已存在!!!\n\n",c);else{strcpy(P->name,c);           Save(L);         //调用信息保存函数}TurnBack();          //调用返回上一菜单函数return;              //返回上一级菜单并退出
}//职工号删除函数
void DeleteNum(List L) 			
{Position P,TmpCell;int number;printf("\n请输入所要删除的职工信息的职工号:  ");scanf("%d",&number);P=FindNumPrevious(number,L);	 //调用职工号前驱指针查找函数,获得所需显示结点的前一结点if(IsLast(P,L)==1)               //判断是否存在该员工printf("\n无职工号为 %d 的员工!!!\n\n删除失败!!!\n\n",number);else{PrintEmployee(P->Next);      //调用职工信息打印函数fflush(stdin);                   //清除键盘缓冲区printf("\n是否确认要删除?回复'Y'/'N'\n");if(getchar()=='Y'){TmpCell=P->Next;P->Next=TmpCell->Next;  free(TmpCell);printf("\n删除成功!!!\n\n");Save(L);                     //调用信息保存函数}}TurnBack();                      //调用返回上一菜单函数return;                          //退出并返回上一级菜单
}//职工信息打印函数
void PrintEmployee(Position P)      
{printf("\n该职工信息如下:\n");printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");printf("  职工号    姓名     工作部门      职称         入厂时间      工资      \n"); printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");printf("   %-d         %-s        %-s             %-s            %-s             %-d\n",P->num,P->name,P->department,P->Title,P->time,P->money);printf("\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
}//菜单输入检测函数
char Test1(char a,char b,char c)    
{while(a<b||a>c){printf("\n\t\t\t输入错误,请重新输入: ");fflush(stdin);                           //清除键盘缓冲区a=getchar();}return a;
}//返回上一菜单函数
void TurnBack()       				
{printf("按回车键返回上一菜单...");fflush(stdin);                                       //清除键盘缓冲区getchar();                                           //读取任意按键值system("cls");                                       //实现清屏
}

四、运行页面展示

1、注册登录界面
在这里插入图片描述

2、选择菜单页面

在这里插入图片描述

3、功能菜单界面
在这里插入图片描述

五、总结与收获

在本次项目中,我用C语言编写了一个职工信息管理系统,实现了注册登录、增删改查操作、以及显示信息功能。通过这个项目,我收获了以下几点:

  • 一是掌握了C语言的基本语法和数据结构,如变量、常量、运算符、表达式、控制流、函数、数组、指针、结构体等。我学会了如何定义和使用这些元素,以及如何解决一些常见的编程问题和错误。
  • 二是熟悉了文件操作的方法和技巧,如打开、关闭、读写、追加等。我学会了如何用文件存储和读取职工信息,以及如何用二进制和文本格式进行文件转换。
  • 三是理解了模块化编程的思想和好处,如封装、抽象、复用等。我学会了如何将程序分为多个模块,每个模块负责一个功能,然后通过接口进行通信和协作。这样可以提高程序的可读性、可维护性和可扩展性。
  • 四是探索了一些高级的编程技巧和特性,如动态内存分配、链表、排序算法等。我学会了如何用这些技巧和特性优化程序的性能和功能,以及如何避免一些潜在的内存泄漏和逻辑错误。
  • 五是体验了软件开发的完整过程,从需求分析、设计、编码、测试、到部署和使用。我学会了如何根据用户需求设计程序的功能和界面,如何编写规范和清晰的代码,如何进行有效的调试和测试,以及如何给用户提供友好和方便的操作指南。

总之,通过这个项目,我不仅锻炼了我的编程能力和逻辑思维,也拓展了我的知识面和视野。我感受到了C语言的强大和灵活,也感受到了编程的乐趣和挑战。我相信这个项目对我的学习和成长有很大的帮助,也为我今后的编程之路打下了坚实的基础。

最后我要说的是,本次课设能够成功完成,不仅仅是因为自己的努力,还有同学以及老师的帮助。本次课设收获的不仅是代码实现系统的能力,还有多方面的能力与经验,是一次受益匪浅的学习过程。

以"穷途总是非末路,沧海绝境见青山。"共勉。

Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)
如果对大家有帮助的话,希望大家能多多点赞+关注!这样我动力会更足哦! ღ( ´・ᴗ・` )比心


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部