职工管理系统(c语言版)

一、系统简介

此系统是一个简易的职工管理系统,其所实现的功能是由c语言进行编写的,这里所运用的编译器是一款基础的编译软件dev-c(其它编译软件也能运行),所使用的流程图软件为亿图图示。如果有一定的c语言编程基础可能对此系统理解起来更加容易。具体是通过链表、结构体、文件等的形式呈现了一个职工管理系统。通过定义多种函数以达到实现退出、增加、显示、删除、查找、修改、保存、清空等多种功能的操作。同时此系统能用来记录职工的编号、姓名、性别、年龄、职位等并进行上述的一系列操作。

二、系统介绍

接下来从系统的头文件引入开始,逐一对代码进行详细的解析。

2.1、头文件

当我们在进行c语言程序的编写时,需要引入一定的头文件,否则无法进行后续代码的编写。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

这里代表引入c语言的头文件,单一的<stdio,h>并不能满足系统的需求。<stdlib.h>头文件中的malloc函数便于我们在使用链表时进行空间的申请;<string.h>头文件中的strcmp函数便于我们进行字符串的比对,以及其他用到的函数,这里不再赘述。

2.2、结构体

我们接下来所使用到的链表包含指针域和数据域,定义一个结构体正好能满足此需求。

struct employee {
	char Id[20];//职工编号
	char Name[20];//职工名字
	char sex[10];//职工性别
	int age;//职工年龄
	char work[10];//职工职位
	struct employee *next;
};
typedef struct employee EMP;
EMP *h;

这里是创建一个结构体并进行重命名,同时创建了一个链表的头指针 *h。结构体内部主要包含了职工的编号、姓名、性别、年龄以及职工的职位,如果想添加其他特征,如家庭地址、电话号码、薪资待遇等等都可以在此处进行对应的定义,同时在后续读取数据与输出数据时加上即可。

2.3、主函数

c语言程序首先都要包含main函数,然后才能进行其他函数的定义以及使用。下面是main内部的代码及解析。

2.3.1、函数代码

int main() {
	h = (EMP *)malloc(sizeof(EMP));//创建链表的头结点
	h->next = NULL;//初始化链表头节点中下一节点指针为NULL
	Read();//首先读取文件数据到链表中
	while (true) {
		Show_Menu();
		printf("请输入您的选择:\n");
		int choice;
		scanf("%d", &choice); //储存用户做出的选择
		switch (choice) {
			case 0:
				ExitSystem();//退出系统
				break;
			case 1:
				Add_Emp();//增加职工信息
				printf("添加成功!\n");
				system("pause");
				system("cls");
				break;
			case 2:
				Show_File();//显示职工信息
				break;
			case 3:
				Del_Emp();//删除职工信息
				break;
			case 4:
				Change_Emp();//修改职工信息
				break;
			case 5:
				Find_Emp();//查找职工信息
				break;

			case 6:
				Save();//保存数据到文件中
				break;
			case 7:
				Clean_File();//清空职工信息
				break;
		}
	}
	system("pause");
}

2.3.2、流程图

主函数流程图

2.3.3、函数解析

主函数这里很好理解,首先创建一个空链表,然后调用Read函数(具体步骤详见2.4.2Read函数)将文件中的数据读取到链表中去。然后进入一个while循环,循环内首先调用Show_Menu函数(具体步骤详见2.4.1Show_Menu函数)向用户展示一下可以做出的操作。然后用一个变量接收用户所做出的选择,并调用switch函数进行判断,根据不同的选择调用不同的函数,当用户所选的操作运行完成后,通过break退出switch函数,然后返回while内部进行下一轮的循环。

2.4、分函数

由于此系统主要功能都是在分函数内进行实现的,所以这一部分内容较多,同时也是此系统的主体部分,初学者理解起来可能有一定的压力,可以通过 ”代码块内部的注释+代码块下方的解析“ 的形式进行理解。

2.4.1、Show_Menu函数

当用户运行代码后,给用户提供一个可供选择的主菜单,每次操作结束后也会返回到此菜单。

2.4.1.1、函数代码
void Show_Menu() {
	printf("******************************\n");
	printf("*****欢迎使用职工管理系统*****\n");
	printf("********0.退出管理系统********\n");
	printf("********1.增加职工信息********\n");
	printf("********2.显示职工信息********\n");
	printf("********3.删除离职职工********\n");
	printf("********4.修改职工信息********\n");
	printf("********5.查找职工信息********\n");
	printf("********6.保存职工信息********\n");
	printf("********7.清空所有文档********\n");
	printf("******************************\n");
}
2.4.1.2、函数解析

显而易见,这一函数是通过一系列简单的printf语句,输出一个较为美观的主菜单供用户进行选择,并通过用户的选择进行一系列的操作,如果不喜欢代码中所展现的格式,也可以更换其他形式的主菜单。

2.4.2、Read函数

当用户开始使用后,首先需要看用户是否已有待处理的数据,有的话需要先读取到链表中去。

2.4.2.1、函数代码
	void Read() { //读文件数据,并创建链表
	FILE *fp;
	fp = fopen("File.txt", "r");//以读的形式打开文件

	if (fp == NULL) { //文件不存在或数据为空,令标志为真
		FileIsEmpty = true;
		return ;
	}  else  { //当文件存在且数据不为空,调用Add函数创建链表
		while (!feof(fp)) {
			EMP *node = (EMP *)malloc(sizeof(EMP));//申请空间
			node->next = NULL;//令下一节点为空
			fscanf(fp, "%s%s%s%d%s\n", node->Id, node->Name, node->sex, &node->age, node->work);//读取文件数据
			Add(node);//调用增加职工信息函数
		}
	}
	fclose(fp);//关闭文件
}

2.4.2.2、流程图

读取操作流程图

2.4.2.3、函数解析

这里主要是通过“r”的形式打开文件,首先进行判断文件是否为空,如果文件为空就将全局变量FileIsEmpty值变为True;如果文件不为空,则进入了while循环,循环内首先申请一个结点空间,并让下一节点为空,通过fscanf函数的形式将文件内容保存到结点的数据域,然后调用Add函数(具体步骤见2.4.3增加职工信息函数)将结点数据添加到链表内,然后便完成了文件数据的处理。

2.4.3、增加职工信息函数

这一部分是通过用户的输入将内容添加到我们所创建的链表中。

2.4.3.1、函数代码

由于直接添加不太好操作,所以这里我们所创建的增加职工信息函数一共有两个,一个是准备操作,另一个是具体操作,以下称准备函数和具体函数。

2.4.3.1.1、准备函数
void Add_Emp() {
	EMP *node;
	node = (EMP *)malloc(sizeof(EMP));//申请空间
	node->next = NULL;//令下一节点为空
	printf("请输入添加的员工编号: \n");
	scanf("%s", node->Id);
	printf("请输入添加员工的姓名: \n");
	scanf("%s", node->Name);
	printf("请输入添加的员工性别(f/m): \n");
	scanf("%s", node->sex);
	printf("请输入添加的员工年龄: \n");
	scanf("%d", &node->age);
	printf("请输入添加的员工工作(boss/manager/employee): \n");
	scanf("%s", node->work);
	Add(node);//调用添加函数
}
2.4.3.1.2、具体函数
void Add(EMP *p) {
	EMP *q;//首先定义一个新指针q
	q = h->next;  //将q指针指向链表中第一个职工结点

	if (q == NULL) { //首先判断当前链表是否为空,如果q指针为NULL,则表示当前链表为空
		h->next = p; //将p指针指向链表中第一个结点

		p->next = NULL;//现在p指针指向的是最后一个结点,因此将该节点的next指针设为NULL

	} else {//不为空时先找到链表最后一个节点,然后用p替换掉
		while (q->next != NULL) { //通过while循环找到链表中最后一个节点

			q = q ->next;
		}
		q->next = p;    //将p指针找到的这个最后一个节点
		p->next = NULL; //现在p指针指向的是最后一个结点,因此将该节点的next指针设为NULL
	}
}
2.4.3.2、流程图

增加函数流程图

2.4.3.3、函数解析

首先对于准备函数,新创建一个结点并申请空间,然后通过输出一系列提示将用户的输入储存在结点的数据域,然后调用具体函数进行添加处理;对于具体函数,首先定义一个新指针并指向链表的头结点,然后进行判断,如果链表为空,直接将我们在准备函数中创建的结点赋值给头结点,并使下一结点置空;如果链表不为空,那么进入while循环找到链表的最后一个元素,然后将我们在准备函数中创建的结点赋值给最后一个结点,同时将下一结点置空,最后输出 “添加成功” 的字样告诉用户并摁任意键清屏。

2.4.4、显示职工信息函数

当我们进行完我们所选择的操作后,如果不确定是否操作成功,那么我们可以调用这个函数来查看是否操作成功或者是否时我们想要的结果。

2.4.4.1、函数代码
void Show_File() {
	if (FileIsEmpty) {
		printf("文件不存在或文件为空\n");
	} else {
		EMP *node;
		node = h->next;
		while (node != NULL) {
			printf("职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄:%d\n职工工作:%s\n", node->Id, node->Name, node->sex,
			       node->age, node->work);
			printf("\n");
			node = node->next;
		}
	}
	system("pause");
	system("cls");
}
2.4.4.2、流程图

显示职工信息函数流程图

2.4.4.3、函数解析

这一部分是对文件内容的显示操作,更确切地来说是对此时链表中的数据进行显示。首先判断文件是否为空,为空则退出循环;不为空则新建一个指针,使其指向链表的头部,然后进入while循环,通过fprintf函数将链表中的元素对应输出。当运行到最后一个链表元素时退出循环,然后摁任意键清屏。

2.4.5、查找职工信息函数

这一部分是通过用户的输入在我们所创建的链表中进行查找,如果找到则正常输出职工信息,如果没找到则返回主菜单。

2.4.5.1、函数代码

为了丰富用户的体验,在这里设置了两种查询方式,一种是按照职工姓名进行查找,另一种是按照职工编号进行查找,如果说自己添加的有其他特征也可以对函数进行改写或者新建一种查询方式,这里不再赘述。

2.4.5.1.1、准备函数
void Find_Emp() {
	int choice;

	printf("请输入要查找的方式: \n1:职工编号\n2:职工姓名\n");

	scanf("%d", &choice);

	if (choice == 1) {
		IdFind();
	} else if (choice == 2) {
		NameFind();
	}
	system("pause");
	system("cls");
}
2.4.5.1.2、按姓名查找函数
int NameFind() {
	int flag = 1;
	EMP *node, *p;
	p = h->next;
	node = (EMP *)malloc(sizeof(EMP));
	node->next = NULL;
	printf("请输入职工姓名: \n");
	scanf("%s", node->Name);
	for (; p != NULL; p = p->next) {
		if (strcmp(p->Name, node->Name) == 0) {
			printf("找到该职工!\n\n");
			printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
			       p->sex,
			       p->age, p->work);
			break;
		}
	}
	if (p == NULL) {
		printf("没有找到该职工!\n");
		flag = -1;
	}
	return flag;//返回标志
}
2.4.5.1.3、按编号查找函数
int IdFind() {
	int flag = 1;
	EMP *node, *p;
	p = h->next;
	node = (EMP *)malloc(sizeof(EMP));
	node->next = NULL;
	printf("请输入职工编号: \n");
	scanf("%s", node->Id);
	for (; p != NULL; p = p->next) {
		if (strcmp(node->Id, p->Id) == 0) {
			printf("找到该职工\n\n");
			printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
			       p->sex,
			       p->age, p->work);
			break;
		}
	}
	if (p == NULL) {
		printf("没有找到该职工\n");
		flag = -1;
	}
	return  flag;
}
2.4.5.2、流程图

查找职工函数

2.4.5.3、函数解析

在查找职工信息这里,我们设置了三个函数,一个是准备函数,两个具体操作函数:一个是按照编号,另一个是按照姓名,但由于两者逻辑与思路一致,这里不再分开解析。在准备函数,我们通过提示告诉用户做出选择,然后根据选择进行调用两个函数。具体操作:我们首先定义了一个flag标志,并进行返回,这代表最终是否在链表内查找成功;又定义了一个结点并申请了空间,使其指向链表头结点;然后进入for循环,结束条件是链表为空(即最后一个结点),同时在循环内部,调用strcmp函数进行比对,如果某一结点的编号或者姓名和用户输入的相等,则代表成功找到,然后将此员工的所有信息依次输出,输出完成后通过break语句退出循环,如果遍历结束仍未找到,则输出 “没有找到该职工” 的字样提示用户。

2.4.6、删除职工信息函数

这里是对职工信息进行删除操作的函数,同时内部调用了查找函数进行查找,如果在链表中就正常删除,如果不在就直接返回主菜单。

2.4.6.1、函数代码

与查找类似,这里也定义了两种方式,一种是按姓名进行删除,另一种是按编号进行删除,如果说自己添加的有其他特征也可以对函数进行修改或者新建一种删除方式,这里不再赘述。

2.4.6.1.1、准备函数
void Del_Emp() {
	int choice;//储存用户的选择
	printf("请选择要删除的信息:\n1、职工编号\n2、职工姓名\n");
	scanf("%d", &choice);
	if (choice == 1) {//进行判断并调用对应函数
		IdDel();
	} else if (choice == 2) {
		NameDel();
	} else {
		system("pause");
		system("cls");
	}
}
2.4.6.1.2、按姓名删除函数
void NameDel() {
	int choice;//储存用户选择
	char delate[20];//储存用户输入的姓名
	if (NameFind() == 1) { //首先进行查找,找到则进行删除,否则退出
		printf("您确定要删除该职工吗?\n1、确定删除\n0、取消删除\n");
		scanf("%d", &choice);
		if (choice == 1) {
			EMP  *p, *q;
			p = h->next;//使p指向链表中第一个节点
			q = p->next;//使p指向链表中第一个节点
			printf("请再次确认职工姓名:\n");//存放用户最终的选择
			scanf("%s", delate);
			if (strcmp(delate, p->Id) == 0) {//首先判断第一个节点是否为需要删除的结点
				h->next = p->next;//如果是,将下一结点提前
				free(p);//删除q
				printf("删除职工姓名为%s的职工成功!\n\n", delate);
			}
			while (q != NULL) { //当未遍历完链表时
				if (strcmp(delate, q->Id) == 0) { //找到需要删除的结点
					p->next = q->next; // p下一结点指向q下一结点
					free(q);//删除q
					printf("删除职工姓名为%s的职工成功!\n\n", delate);
				}
				p = q; // p指向q
				q = q->next; //q指向下一q的下一节点

			}

		} else {
			printf("取消删除成功!\n");
		}
	} else
		printf("无法进行删除操作!\n") ;
	system("pause");
	system("cls");
}

2.4.6.1.2、按编号删除函数
void IdDel() {
	int choice;//储存用户选择
	char delate[20];//储存用户输入的编号
	if (IdFind() == 1) { //首先进行查找,找到则进行删除,否则退出
		printf("您确定要删除该职工吗?\n1、确定删除\n0、取消删除\n");
		scanf("%d", &choice);
		if (choice == 1) {
			EMP  *p, *q;
			p = h->next;//使p指向链表中第一个节点
			q = p->next;//使q指向链表中第二个节点
			printf("请再次确认职工编号:\n");
			scanf("%s", delate);//存放用户最终的选择
			if (strcmp(delate, p->Id) == 0) {//首先判断第一个节点是否为需要删除的结点
				h->next = p->next;//如果是,将下一结点提前
				free(p);//删除p
				printf("删除职工编号为%s的职工成功!\n\n", delate);
			}
			while (q != NULL) { //当未遍历完链表时
				if (strcmp(delate, q->Id) == 0) { //找到需要删除的结点
					p->next = q->next; // p下一结点指向q下一结点
					free(q);//删除q
					printf("删除职工编号为%s的职工成功!\n\n", delate);
					break;
				}
				p = q; // p指向q
				q = q->next; //q指向下一q的下一节点
			}
		} else {
			printf("取消删除成功!\n");
		}
	} else
		printf("无法进行删除操作!\n") ;
	system("pause");
	system("cls");
}
2.4.6.2、流程图

删除职工流程图

2.4.6.3、函数解析

在删除职工信息这里,我们设置了三个函数,一个是准备函数,两个具体操作函数:一个是按照编号,另一个是按照姓名,但由于两者逻辑与思路一致,这里不再分开解析。在准备函数,我们让用户做出选择,并根据相应选择调用对应函数;具体操作:首先让用户确认是否真的进行删除操作,如果确定进行删除,则定义两个指针p,q,p指向链表的头结点,q指向p的下一结点;然后进行判断,首先判断p是否为要删除的结点,如果是,将q赋值给头结点并释放p即可;如果不是则进入while循环,然后调用strcmp函数与链表元素进行比对,找到以后将q的下一结点赋值给p的下一结点并释放q然后break语句退出即可。整体来说也不是很复杂,在具体删除部分,如果看不懂具体怎么操作,可以根据代码内容画出链表与指针相应的操作图可能会更容易理解。

2.4.7、修改职工信息函数

这一部分是对职工某一信息进行修改,首先现在链表中找到这个职工,然后再进行对应的修改,如果未找到则返回主菜单。

2.4.7.1、函数代码
void Change_Emp() {
	int choice;
	printf("请输入要修改的职工:\n1、职工编号\n2、职工姓名\n");
	scanf("%d", &choice);
	if (choice == 1) {
		EMP *node, *p;
		p = h->next;
		node = (EMP *)malloc(sizeof(EMP));
		node->next = NULL;
		printf("请输入职工编号: \n");
		scanf("%s", node->Id);
		for (; p != NULL; p = p->next) {
			if (strcmp(p->Id, node->Id) == 0) {
				printf("找到该职工!\n\n");
				printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				break;
			}
		}
		if (p == NULL) {
			printf("没有找到该职工!\n");
			system("pause");
			system("cls");
			return ;
		}
		printf("请输入要修改的信息:\n1、职工编号\n2、职工姓名\n3、职工性别\n4、职工年龄\n5、职工职位\n");
		int change;
		scanf("%d", &change);
		switch (change) {
			case 1:
				printf("请输入修改后的职工编号:\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 2:
				printf("请输入修改后的职工姓名:\n");
				scanf("%s", p->Name);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 3:
				printf("请输入修改后的职工性别:\n");
				scanf("%s", p->sex);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 4:
				printf("请输入修改后的职工年龄:\n");
				scanf("%s", p->age);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 5:
				printf("请输入修改后的职工工作(boss/manager/employee):\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			default :
				break;

		}
	} else if (choice == 2) {
		EMP *node, *p;
		p = h->next;
		node = (EMP *)malloc(sizeof(EMP));
		node->next = NULL;
		printf("请输入职工姓名: \n");
		scanf("%s", node->Name);
		for (; p != NULL; p = p->next) {
			if (strcmp(p->Name, node->Name) == 0) {
				printf("找到该职工!\n\n");
				printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				break;
			}
		}
		if (p == NULL) {
			printf("没有找到该职工!\n");
			system("pause");
			system("cls");
			return ;
		}
		printf("请输入要修改的信息:\n1、职工编号\n2、职工姓名\n3、职工性别\n4、职工年龄\n5、职工职位\n");
		int change;
		scanf("%d", &change);
		switch (change) {
			case 1:
				printf("请输入修改后的职工编号:\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 2:
				printf("请输入修改后的职工姓名:\n");
				scanf("%s", p->Name);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 3:
				printf("请输入修改后的职工性别:\n");
				scanf("%s", p->sex);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 4:
				printf("请输入修改后的职工年龄:\n");
				scanf("%s", p->age);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 5:
				printf("请输入修改后的职工工作(boss/manager/employee):\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			default :
				break;
		}
	} else {
		system("pause");
		system("cls");
		return;
	}
}
2.4.7.2、流程图

修改职工函数

2.4.7.3、函数解析

这一部分代码可能较为冗杂,我们一点一点的来剖析。首先如果我们想修改职工的信息,首先我们要先在链表中进行查找,所以我们在函数内部追加一步查找(具体详见2.4.5)也可以尝试直接调用,如果没有找到该职工则直接返回主菜单;如果找到该职工,则进行下一步的修改,让用户选择想要修改的数据,并用switch函数进行判断,分别修改相应的数据域,即对对应的数据域赋值,并把修改后的结果输出,然后告诉用户修改成功。整体来说并不是很复杂,只不过为了丰富用户的体验多追加了一遍查找,而且对对应的数据进行修改时由于需要进行switch函数的判断,所以导致了代码过于繁杂。

2.4.8、保存职工信息函数

由于我们并不是直接把链表信息追加到文件中的,所以相对应的我们需要进行保存职工信息到文件中去,这就要使用到我们自定义的另一个函数:保存职工信息函数。

2.4.8.1、函数代码
void Save() {
	FILE *fp;

	EMP *node;

	fp = fopen("File.txt", "w"); //以写的方式打开文件

	node = h->next;//node指针指向链表第一个结点

	while (node != NULL) {//进行while循环写入文件
		fprintf(fp, "%s %s %s %d %s\n", node->Id, node->Name, node->sex, node->age, node->work);
		node = node->next;
	}
	fclose(fp);//关闭文件
	printf("保存成功!\n");
	system("pause");
	system("cls");
}
2.4.8.2、流程图

保存职工信息函数流程图

2.4.8.3、函数解析

因为药保存链表数据到文件中,所以我们首先需要以写的形式打开文件,然后定义一个指针,使其指向我们所创建的链表的头结点,然后进行判断是否为链表的最后一个结点,如果是就直接关闭文件,并输出 “保存成功” 的字样告诉用户保存成功;如果不是就通过fprintf函数将链表内容写入到文件中去,然后指向链表的下一位接着进行循环。

2.4.9、清空职工信息函数

当我们想要把文件中内容全部清除时,如果数据过多那么单一的删除可能需要用很长时间,所以这就需要用到另一个我们创建的自定义函数:清空职工信息函数。

2.4.9.1、函数代码
void Clean_File() {
	FILE *fp;
	fp = fopen("File.txt", "w");
	fprintf(fp, "1 kxy f 20 boss");
	fclose(fp);
	printf("清空文件成功!\n\n但此操作后文件会默认存在一名boss!!!\n\n");
	system("pause");
	system("cls");
}
2.4.9.2、流程图

清空函数流程图

2.4.9.3、函数解析

由于我们使用 “w” 模式打开文件,所以如果文件存在,那么会自动清空并重新创建一个File文件;如果文件不存在,那么就会自动创建一个File文件,这时就只需要我们对文件进行初始化即可。所以通过文件独有的打开模式 “w” 模式就实现了我们对整体文件的清空处理。最后两行system命令代表摁任意键清屏。

三、总结

到这一步整个系统就算是差不多完善好了,但同时如果仅仅是以上代码是不足以让整个程序跑起来的,需要我们手动进行一定的操作,具体详见3.2.2说明。

3.1、总结

编写代码中可能出现语句不规范、不简洁或者算法不是最优解的情况,如果发现的话,可以在评论区指正出来,大家共同学习、共同进步!

3.2、补充

这一部分是对此系统的补充完善以及说明。

3.2.1、退出函数

在我们进行完所有的操作以后,我们需要正常退出这个系统,这就需要用到我们自定义的另一个函数:退出函数。

3.2.1.1、函数代码
void ExitSystem() {
	printf("欢迎下次使用!\n");
	system("pause");//摁任意键清屏
	exit(0);
}
3.2.1.2、流程图

退出函数流程图

3.2.1.3、函数解析

因为我们要退出系统,所以我们药告诉用户是否成功退出,这里输出的 “欢迎下次使用!” 代表我们退出成功,同时第三行代码代表 ”摁任意键清屏“ 这一命令,最后的exit(0)表示关闭所有的文件,终止正在执行的进程。

3.2.2、说明

由于此系统篇幅包含了文件的读和写,并未进行文件的创建处理,所以可能需要手动进行文件的初始化;同时当我们操作完成后需要手动进行保存。

3.2.2.1、创建文件

在使用此系统时,请在此文件的同级目录下创建一个名为 “File.txt” 的文本文档(编码格式采用utf-8),并按照结构体中对应的定义,这里是职工编号、职工姓名、职工性别、职工年龄以及职工职位进行初始化(例:1,kxy,f,20,boss),否则可能出现后续数据添加不上或无法得到想要的结果的情况。

3.2.2.2、保存文件

由于此系统有单独的保存函数,所以在进行完各项操作时并不会自动保存到我们所创建的文本文档中。如果直接退出系统,我们所做出的操作仅仅是对链表进行的修改,只有通过Save函数(具体步骤详见2.4.8保存职工信息函数)才会保存到文件中。所以我们需要在运行完我们的操作后,追加一步将链表内容通过保存职工信息的操作,保存到我们所创建的文本文档中。

四、系统总代码

上述便是此系统的全部内容,而下面便是此系统的整体代码。如果有想做毕业设计或者c语言期末大作业而不知如何下手的,可以在评论区留下你的联系方式,后续可以提供免费指导或者提供免费代做服务。如果仅仅是对此系统感兴趣,那么在粘贴复制本代码的同时一定要注意查看3.2.2的说明,否则可能无法正常运行。与此同时文章创作不易,如果觉得可以的话点赞关注支持一下!!!

//使用时请先注意文章中的3.2.2说明,否则可能无法正常运行
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct employee {
	char Id[20];//职工编号
	char Name[20];//职工名字
	char sex[10];//职工性别
	int age;//职工年龄
	char work[10];//职工职位
	struct employee *next;
};
typedef struct employee EMP;
EMP *h;
void Read(); //读文件数据,并创建链表
void Show_Menu();//显示主菜单
void ExitSystem();//退出系统
void Add_Emp();//增加职工
void Add(EMP *p);//增加职工具体实现
void Show_File();
void Save();//保存数据到文件中
void Find_Emp();
int IdFind();
int NameFind();
void Del_Emp();//删除职工
void IdDel();//按编号删除职工
void NameDel();//按姓名删除职工
void Change_Emp();
void Clean_File();

int main() {
	h = (EMP *)malloc(sizeof(EMP));//创建链表的头结点
	h->next = NULL;//初始化链表头节点中下一节点指针为NULL
	Read();//首先读取文件数据到链表中
	while (true) {
		Show_Menu();
		printf("请输入您的选择:\n");
		int choice;
		scanf("%d", &choice); //储存用户做出的选择
		switch (choice) {
			case 0:
				ExitSystem();//退出系统
				break;
			case 1:
				Add_Emp();//增加职工
				printf("添加成功!\n");
				system("pause");
				system("cls");
				break;
			case 2:
				Show_File();
				break;
			case 3:
				Del_Emp();//删除职工信息
				break;
			case 4:
				Change_Emp();
				break;
			case 5:
				Find_Emp();
				break;

			case 6:
				Save();//保存数据到文件中
				break;
			case 7:
				Clean_File();
				break;
		}
	}
	system("pause");
}
//定义一个布尔类型变量使其作为判断文件是否为空的标志
bool FileIsEmpty = false;

//读取文件数据
void Read() { //读文件数据,并创建链表
	FILE *fp;
	fp = fopen("File.txt", "r");//以读的形式打开文件

	if (fp == NULL) { //文件不存在或数据为空,令标志为真
		FileIsEmpty = true;
		return ;
	}  else  { //当文件存在且数据不为空,调用Add函数创建链表
		while (!feof(fp)) {
			EMP *node = (EMP *)malloc(sizeof(EMP));//申请空间
			node->next = NULL;//令下一节点为空
			fscanf(fp, "%s%s%s%d%s\n", node->Id, node->Name, node->sex, &node->age, node->work);
			Add(node);
		}
	}
	fclose(fp);
}

//显示菜单
void Show_Menu() {
	printf("******************************\n");
	printf("*****欢迎使用职工管理系统*****\n");
	printf("********0.退出管理系统********\n");
	printf("********1.增加职工信息********\n");
	printf("********2.显示职工信息********\n");
	printf("********3.删除离职职工********\n");
	printf("********4.修改职工信息********\n");
	printf("********5.查找职工信息********\n");
	printf("********6.保存职工信息********\n");
	printf("********7.清空所有文档********\n");
	printf("******************************\n");
}

//退出系统
void ExitSystem() {
	printf("欢迎下次使用!\n");
	system("pause");//摁任意键清屏
	exit(0);
}

//增加职工
void Add_Emp() {
	EMP *node;
	node = (EMP *)malloc(sizeof(EMP));//申请空间
	node->next = NULL;//令下一节点为空
	printf("请输入添加的员工编号: \n");
	scanf("%s", node->Id);
	printf("请输入添加员工的姓名: \n");
	scanf("%s", node->Name);
	printf("请输入添加的员工性别(f/m): \n");
	scanf("%s", node->sex);
	printf("请输入添加的员工年龄: \n");
	scanf("%d", &node->age);
	printf("请输入添加的员工工作(boss/manager/employee): \n");
	scanf("%s", node->work);
	Add(node);//调用添加函数
}

//增加职工具体实现
void Add(EMP *p) {
	EMP *q;//首先定义一个新指针q
	q = h->next;  //将q指针指向链表中第一个职工结点

	if (q == NULL) { //首先判断当前链表是否为空,如果q指针为NULL,则表示当前链表为空
		h->next = p; //将p指针指向链表中第一个结点

		p->next = NULL;//现在p指针指向的是最后一个结点,因此将该节点的next指针设为NULL

	} else {//不为空时先找到链表最后一个节点,然后用p替换掉
		while (q->next != NULL) { //通过while循环找到链表中最后一个节点

			q = q ->next;
		}
		q->next = p;    //将p指针找到的这个最后一个节点
		p->next = NULL; //现在p指针指向的是最后一个结点,因此将该节点的next指针设为NULL
	}
}

void Show_File() {
	if (FileIsEmpty) {
		printf("文件不存在或文件为空\n");
	} else {
		EMP *node;
		node = h->next;
		while (node != NULL) {
			printf("职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄:%d\n职工工作:%s\n", node->Id, node->Name, node->sex,
			       node->age, node->work);
			printf("\n");
			node = node->next;
		}
	}
	system("pause");
	system("cls");
}

//保存链表信息到文件中
void Save() {
	FILE *fp;

	EMP *node;

	fp = fopen("File.txt", "w"); //以写的方式打开文件

	node = h->next;//node指针指向链表第一个结点

	while (node != NULL) {//进行while循环写入文件
		fprintf(fp, "%s %s %s %d %s\n", node->Id, node->Name, node->sex, node->age, node->work);
		node = node->next;
	}
	fclose(fp);//关闭文件
	printf("保存成功!\n");
	system("pause");
	system("cls");
}


void Find_Emp() {
	int choice;

	printf("请输入要查找的方式: \n1:职工编号\n2:职工姓名\n");

	scanf("%d", &choice);

	if (choice == 1) {
		IdFind();
	} else if (choice == 2) {
		NameFind();
	}
	system("pause");
	system("cls");
}


int IdFind() {
	int flag = 1;
	EMP *node, *p;
	p = h->next;
	node = (EMP *)malloc(sizeof(EMP));
	node->next = NULL;
	printf("请输入职工编号: \n");
	scanf("%s", node->Id);
	for (; p != NULL; p = p->next) {
		if (strcmp(node->Id, p->Id) == 0) {
			printf("找到该职工\n\n");
			printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
			       p->sex,
			       p->age, p->work);
			break;
		}
	}
	if (p == NULL) {
		printf("没有找到该职工\n");
		flag = -1;
	}
	return  flag;
}


int NameFind() {
	int flag = 1;
	EMP *node, *p;
	p = h->next;
	node = (EMP *)malloc(sizeof(EMP));
	node->next = NULL;
	printf("请输入职工姓名: \n");
	scanf("%s", node->Name);
	for (; p != NULL; p = p->next) {
		if (strcmp(p->Name, node->Name) == 0) {
			printf("找到该职工!\n\n");
			printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
			       p->sex,
			       p->age, p->work);
			break;
		}
	}
	if (p == NULL) {
		printf("没有找到该职工!\n");
		flag = -1;
	}
	return flag;//返回标志
}

//删除职工信息
void Del_Emp() {
	int choice;//储存用户的选择
	printf("请选择要删除的信息:\n1、职工编号\n2、职工姓名\n");
	scanf("%d", &choice);
	if (choice == 1) {//进行判断并调用对应函数
		IdDel();
	} else if (choice == 2) {
		NameDel();
	} else {
		system("pause");
		system("cls");
	}
}

// 按编号进行删除
void IdDel() {
	int choice;//储存用户选择
	char delate[20];//储存用户输入的编号
	if (IdFind() == 1) { //首先进行查找,找到则进行删除,否则退出
		printf("您确定要删除该职工吗?\n1、确定删除\n0、取消删除\n");
		scanf("%d", &choice);
		if (choice == 1) {
			EMP  *p, *q;
			p = h->next;//使p指向链表中第一个节点
			q = p->next;//使q指向链表中第二个节点
			printf("请再次确认职工编号:\n");
			scanf("%s", delate);//存放用户最终的选择
			if (strcmp(delate, p->Id) == 0) {//首先判断第一个节点是否为需要删除的结点
				h->next = p->next;//如果是,将下一结点提前
				free(p);//删除p
				printf("删除职工编号为%s的职工成功!\n\n", delate);
			}
			while (q != NULL) { //当未遍历完链表时
				if (strcmp(delate, q->Id) == 0) { //找到需要删除的结点
					p->next = q->next; // p下一结点指向q下一结点
					free(q);//删除q
					printf("删除职工编号为%s的职工成功!\n\n", delate);
					break;
				}
				p = q; // p指向q
				q = q->next; //q指向下一q的下一节点
			}
		} else {
			printf("取消删除成功!\n");
		}
	} else
		printf("无法进行删除操作!\n") ;
	system("pause");
	system("cls");
}

//按姓名进行删除
void NameDel() {
	int choice;//储存用户选择
	char delate[20];//储存用户输入的姓名
	if (NameFind() == 1) { //首先进行查找,找到则进行删除,否则退出
		printf("您确定要删除该职工吗?\n1、确定删除\n0、取消删除\n");
		scanf("%d", &choice);
		if (choice == 1) {
			EMP  *p, *q;
			p = h->next;//使p指向链表中第一个节点
			q = p->next;//使p指向链表中第一个节点
			printf("请再次确认职工姓名:\n");//存放用户最终的选择
			scanf("%s", delate);
			if (strcmp(delate, p->Id) == 0) {//首先判断第一个节点是否为需要删除的结点
				h->next = p->next;//如果是,将下一结点提前
				free(p);//删除q
				printf("删除职工姓名为%s的职工成功!\n\n", delate);
			}
			while (q != NULL) { //当未遍历完链表时
				if (strcmp(delate, q->Id) == 0) { //找到需要删除的结点
					p->next = q->next; // p下一结点指向q下一结点
					free(q);//删除q
					printf("删除职工姓名为%s的职工成功!\n\n", delate);
				}
				p = q; // p指向q
				q = q->next; //q指向下一q的下一节点

			}

		} else {
			printf("取消删除成功!\n");
		}
	} else
		printf("无法进行删除操作!\n") ;
	system("pause");
	system("cls");
}


void Change_Emp() {
	int choice;
	printf("请输入要修改的职工:\n1、职工编号\n2、职工姓名\n");
	scanf("%d", &choice);
	if (choice == 1) {
		EMP *node, *p;
		p = h->next;
		node = (EMP *)malloc(sizeof(EMP));
		node->next = NULL;
		printf("请输入职工编号: \n");
		scanf("%s", node->Id);
		for (; p != NULL; p = p->next) {
			if (strcmp(p->Id, node->Id) == 0) {
				printf("找到该职工!\n\n");
				printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				break;
			}
		}
		if (p == NULL) {
			printf("没有找到该职工!\n");
			system("pause");
			system("cls");
			return ;
		}
		printf("请输入要修改的信息:\n1、职工编号\n2、职工姓名\n3、职工性别\n4、职工年龄\n5、职工职位\n");
		int change;
		scanf("%d", &change);
		switch (change) {
			case 1:
				printf("请输入修改后的职工编号:\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 2:
				printf("请输入修改后的职工姓名:\n");
				scanf("%s", p->Name);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 3:
				printf("请输入修改后的职工性别:\n");
				scanf("%s", p->sex);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 4:
				printf("请输入修改后的职工年龄:\n");
				scanf("%s", p->age);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 5:
				printf("请输入修改后的职工工作(boss/manager/employee):\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			default :
				break;

		}
	} else if (choice == 2) {
		EMP *node, *p;
		p = h->next;
		node = (EMP *)malloc(sizeof(EMP));
		node->next = NULL;
		printf("请输入职工姓名: \n");
		scanf("%s", node->Name);
		for (; p != NULL; p = p->next) {
			if (strcmp(p->Name, node->Name) == 0) {
				printf("找到该职工!\n\n");
				printf("该职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				break;
			}
		}
		if (p == NULL) {
			printf("没有找到该职工!\n");
			system("pause");
			system("cls");
			return ;
		}
		printf("请输入要修改的信息:\n1、职工编号\n2、职工姓名\n3、职工性别\n4、职工年龄\n5、职工职位\n");
		int change;
		scanf("%d", &change);
		switch (change) {
			case 1:
				printf("请输入修改后的职工编号:\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 2:
				printf("请输入修改后的职工姓名:\n");
				scanf("%s", p->Name);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 3:
				printf("请输入修改后的职工性别:\n");
				scanf("%s", p->sex);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 4:
				printf("请输入修改后的职工年龄:\n");
				scanf("%s", p->age);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			case 5:
				printf("请输入修改后的职工工作(boss/manager/employee):\n");
				scanf("%s", p->Id);
				printf("修改成功!\n");
				printf("修改后的职工信息为:\n职工编号:%s\n职工姓名:%s\n职工性别:%s\n职工年龄: %d\n职工工作:%s\n\n", p->Id, p->Name,
				       p->sex,
				       p->age, p->work);
				system("pause");
				system("cls");
				break;
			default :
				break;
		}
	} else {
		system("pause");
		system("cls");
		return;
	}
}

void Clean_File() {
	FILE *fp;
	fp = fopen("File.txt", "w");
	fprintf(fp, "1 kxy f 20 boss");
	fclose(fp);
	printf("清空文件成功!\n\n但此操作后文件会默认存在一名boss!!!\n\n");
	system("pause");
	system("cls");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值