C++链表实现职工管理系统

简述

这个学期的《数据结构》这门课有要制作课程设计的要求,刚好我的题目是使用链表的数据结构写一个简单的职工管理系统。以下是学校的要求
在这里插入图片描述
现在开始码代码。

对了,代码中有大量的注释,非常适合初次制作的兄弟姐妹门理解,互相学习互相借鉴啦,哈哈哈。而且功能模块封装合理,我就直接上全部代码啦,您慢用!

#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string.h>
#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <io.h>



//定义 员工 链表
struct Employee {
	char name[15]; // 姓名
	char gender[8]; // 性别
	char birth[20]; // 出生
	char gzny[20]; // 工作年月
	char xueli[15]; // 学历
	char posit[15]; // 职务
	char tele[16]; // 电话
	char location[25]; // 住址
	struct Employee* next;//链式存储
};
Employee* employeeList;//定义全局 员工 指针  即常用的L
int employeeCount = 0;//员工 个数记录

int compare(int a, int b);
int compare(const char* a, const char* b);//此处什么意思

//员工 读入文件
void readEmployee();
//员工 写入文件
void writeEmployee();
//员工 添加记录
void addEmployee();
void addOneEmployee(Employee* employee);
//员工 删除记录
void delEmployee();
//员工 根据下标删除
int delEmployeeByIndex(int index);
//员工 修改记录
void modEmployee();
//员工 查找记录
void findEmployee(int all);
//员工 排序
void sortEmployee();
//交换
void exchangeEmployee(int i, int j);
//存在判断函数

//菜单
void menu();

// 主函数
int main() {
	//读取数据
	readEmployee();//读取员工
	while (1) {
		int choice;
		menu();
		scanf("%d", &choice);
		switch (choice) {
		case 1:
			addEmployee();//添加员工
			break;
		case 2:
			findEmployee(1);//查找员工
			delEmployee();//删除员工
			break;
		case 3:
			findEmployee(1);//查找员工
			modEmployee();//修改员工
			break;
		case 4:
			findEmployee(0);//查找员工
			break;
		case 5:
			sortEmployee();//排序员工
			break;
		case 0:
			printf("\n\n\n\t\t\t感谢使用\n\n\n");
			exit(0);//C ++exit函数终止进程,退出程序
		default:
			getchar();
			printf("\n\n\n\t提示:没有这个选项!请重新输入!\n\n\n\n");
			system("pause");
			break;
		}
	}
	return 0;
}



//员工 读入文件
void readEmployee() {
	FILE* fp;
	fp = fopen("EmployeeData.data", "r");    //	FILE* =fopen("EmployeeData.data", "r");将文件读入fp这个文件结构体,
	//读取文件为空                                               以文本格式读取EmployeeData.data文件
	if (fp == NULL)return;
	//读取个数
	fread(&employeeCount, sizeof(int), 1, fp);//将文件数据个数放进employeeCount  ,1指元素个数
	employeeList = NULL;
	Employee* tail = employeeList;   //这个tail没用
	//写入到链表
	for (int i = 0; i < employeeCount; i++) {
		Employee* p = (Employee*)malloc(sizeof(Employee));//分配一段Employee结构体大小的地址空间
		fread(p, sizeof(Employee), 1, fp);   //以Employee对象返回给p这个指针    这种动态内存分配空间节约内存,而且外部需要调用函数内部指针对应空间
		p->next = NULL;
		//指针为空则赋值。
		if (employeeList == NULL) {
			employeeList = p;
			tail = p;
		}
		else {     //这个tail指针并没有用到
			tail->next = p;
			tail = p;
		}
	}
	fclose(fp);//关闭文件函数
}
//员工 写入文件
void writeEmployee() {
	//保存到本地信息库
	FILE* fp;
	fp = fopen("EmployeeData.data", "wb");   //写入二进制内容
	Employee* p = employeeList;
	//先保存个数
	fwrite(&employeeCount, sizeof(employeeCount), 1, fp);
	//挨个保存
	while (p) {     //将p写入,将整个链表写入本地文件
		Employee* temp = (Employee*)malloc(sizeof(Employee));
		temp->next = NULL;
		strcpy(temp->name, p->name);
		strcpy(temp->gender, p->gender);
		strcpy(temp->birth, p->birth);
		strcpy(temp->gzny, p->gzny);
		strcpy(temp->xueli, p->xueli);
		strcpy(temp->posit, p->posit);
		strcpy(temp->tele, p->tele);
		strcpy(temp->location, p->location);
		fwrite(temp, sizeof(Employee), 1, fp);
		p = p->next;
	}
	fclose(fp);
}
//员工 添加记录
void addEmployee() {
	char selectYNFlag = 'y';
	while (selectYNFlag == 'y' || selectYNFlag == 'Y') {
		printf("\n");
		Employee* tempValue = (Employee*)malloc(sizeof(Employee)); //必须重新分配地址空间。
		printf("请输入姓名 :");
		char name[15];
		scanf("%s", name);
		strcpy(tempValue->name, name); 
		printf("请输入性别 :");
		char gender[8];
		scanf("%s", gender);
		strcpy(tempValue->gender, gender);
		printf("请输入出生 :");
		char birth[20];
		scanf("%s", birth);
		strcpy(tempValue->birth, birth);
		printf("请输入工作年月 :");
		char gzny[20];
		scanf("%s", gzny);
		strcpy(tempValue->gzny, gzny);
		printf("请输入学历 :");
		char xueli[15];
		scanf("%s", xueli);
		strcpy(tempValue->xueli, xueli);
		printf("请输入职务 :");
		char posit[15];
		scanf("%s", posit);
		strcpy(tempValue->posit, posit);
		printf("请输入电话 :");
		char tele[16];
		scanf("%s", tele);
		strcpy(tempValue->tele, tele);
		printf("请输入住址 :");
		char location[25];
		scanf("%s", location);
		strcpy(tempValue->location, location);
		tempValue->next = NULL;
		addOneEmployee(tempValue);     //将新形成的链表结点加入链表   形成新的employeeList(头结点),即下方头插法函数
		printf("\n是否继续录入?(y/n)");
		getchar();//I/O流输入字符,直到回车
		scanf("%c", &selectYNFlag);
	}
	writeEmployee();
	printf("\n*****************************\n");
	printf("录入完成\n");
	printf("*****************************\n");
}
void addOneEmployee(Employee* temp) {
	//采用头插法
	if (employeeList == NULL) {
		employeeList = temp;
	}
	else {
		temp->next = employeeList;
		employeeList = temp;
	}
	employeeCount++;
}
//员工 删除
void delEmployee() {
	printf("请输入您要删除的 员工 序号(输入-1退出):");
	int index;
	scanf("%d", &index);

	if (index >= 0) {
		int res = delEmployeeByIndex(index);
		if (res) {
			printf("删除成功!\n\n");
			writeEmployee();
		}
		else {
			printf("删除失败!请正确输入现有员工序号!!\n\n");
		}
	}
}
//员工 根据下标删除
int delEmployeeByIndex(int index) {
	if (index > employeeCount || index < 1) {
		return 0;//删除失败 ,数量没那么多
	}
	//开始删除!
	Employee* p = (Employee*)malloc(sizeof(Employee));
	Employee* q = employeeList;
	p->next = employeeList;
	if (index == 1) {
		employeeList = employeeList->next;  //通过将当前链表结点next指针指向下一个结点
	}
	else {
		for (int i = 0; i < index - 1; i++) {  ///初始时q指向employeeList即链表第一个结点,删除第几个需要移动index-1次
			p = p->next;                                 //循环后p为所要删除结点的前驱
			q = q->next;                                     //将前驱结点的后继指针指向应删除结点的下一个结点就实现了删除
		}
		p->next = q->next;
	}
	employeeCount = employeeCount - 1;    //员工信息计数减一
	return 1;              //删除成功后返回布尔值为1
}
//员工 修改
void modEmployee() {
	printf("请输入您要修改的员工 序号(输入-1退出):");
	int indexOfMod = -1;
	scanf("%d", &indexOfMod);
	if (indexOfMod > 0 && indexOfMod <= employeeCount) {
		//开始修改
		Employee* temp = employeeList;
		for (int i = 0; i < indexOfMod - 1; i++) {   //将temp指向需要修改的链表结点,即修改该结点所在员工信息
			temp = temp->next;
		}
		printf("请输入姓名 :");
		char name[15];
		scanf("%s", name);

		printf("请输入性别 :");
		char gender[8];
		scanf("%s", gender);

		printf("请输入出生 :");
		char birth[20];
		scanf("%s", birth);

		printf("请输入工作年月 :");
		char gzny[20];
		scanf("%s", gzny);

		printf("请输入学历 :");
		char xueli[15];
		scanf("%s", xueli);

		printf("请输入职务 :");
		char posit[15];
		scanf("%s", posit);

		printf("请输入电话 :");
		char tele[16];
		scanf("%s", tele);

		printf("请输入住址 :");
		char location[25];
		scanf("%s", location);

		//输入完毕,赋值
		strcpy(temp->name, name);
		strcpy(temp->gender, gender);
		strcpy(temp->birth, birth);
		strcpy(temp->gzny, gzny);
		strcpy(temp->xueli, xueli);
		strcpy(temp->posit, posit);
		strcpy(temp->tele, tele);
		strcpy(temp->location, location);
		printf("修改成功!\n");
		writeEmployee();    //为什么没有将temp赋值给p
	}
	else {
		printf("输入错误!\n");
	}
}
//员工 查找 如果all=1:查询全部 否则按条件查询
void findEmployee(int all) {
	int select = 0;
	char conCharArr[40];
	double conNum1, conNum2;
	while (1) {//重复循环,主要是为了选择姓名等筛选条件后继续进行重新筛选后的信息输出
		printf("\n%-5s%-8s%-8s%-12s%-12s%-10s%-20s%-12s%-20s \n\n", "序号", "姓名", "性别", "出生", "工作年月", "学历", "职务", "电话", "住址");
		int i = 1, count = 0;     //%-5s%-15s%-8s%-20s%-20s%-15s%-15s%-16s%-25s
		if (employeeList) {
			//用于统计信息所用
			Employee* t = employeeList;
			while (t) {    //对于筛选后的链表结点进行遍历输出,不符合筛选条件进行过滤不再输出
				int delFlag = 0;
				if (select == 0
					|| select == 1 && strcmp(conCharArr, t->name) == 0   //该函数值等于0则表示字符串相等,即此处出入文字进行选择也行
					|| select == 2 && strcmp(conCharArr, t->gender) == 0
					) {
					printf("%-5d%-8s%-8s%-12s%-12s%-10s%-20s%-12s%-20s \n\n", i
						, t->name
						, t->gender
						, t->birth
						, t->gzny
						, t->xueli
						, t->posit
						, t->tele
						, t->location
					);
					//用于统计信息所用
					count++;
				}
				else {
					delFlag = 1;//删掉
				}
				t = t->next;   //再输出下一个员工信息(下一个链表结点)
				if (delFlag) {
					delEmployeeByIndex(i--);
				}
				i++;
			}
			printf("共%d条结果\n", count);
			printf("-----------------------------------------------------------------------------------------------------\n");
			printf("\n");
		}
		//如果参数all为1,则表示列出所有就退出
		if (all == 1)break;
		//进入过滤。
		printf("【筛选器:你可以在以上结果的基础上,进行以下条件筛选:】\n");
		printf("0:退出\n");
		printf("1:按 姓名 筛选\n");
		printf("2:按 性别 筛选\n");
		printf("请输入选择:");
		scanf("%d", &select);
		if (select > 0) {
			if (0 || select == 1 || select == 2) {
				printf("请输入筛选条件:");
				scanf("%s", conCharArr);//装姓名或性别
			}
			else if (0) {
				printf("请输入筛选范围m,n,用空格隔开(m ≤X ≤n):");
				scanf("%lf", &conNum1);
				scanf("%lf", &conNum2);
			}
		}
		else {
			break;
		}
	}
	readEmployee();//从新读取数据。
}
//员工 排序
void sortEmployee() {
	int select, i, j;
	printf("1:按 姓名 排序\n");
	printf("2:按 性别 排序\n");
	printf("3:按 出生 排序\n");
	printf("4:按 工作年月 排序\n");
	printf("5:按 学历 排序\n");
	printf("6:按 职务 排序\n");
	printf("7:按 电话 排序\n");
	printf("8:按 住址 排序\n");
	printf("请输入选择:");
	scanf("%d", &select);
	Employee* list[100];      //将现有读取的链表数据写进用于排序的临时链表当中
	for (i = 0; i < employeeCount; i++) {
		list[i] = employeeList;
		employeeList = employeeList->next;
	}
	for (i = employeeCount - 1; i > 0; i--) {//通过嵌套两次for循环进行比较,比较字符串使用strcmp函数,比较数字直接相减     冒泡排序
		for (j = 0; j < i; j++) {
			if (0        //0||的表达式,表示逻辑真值不为0则为1
				|| select == 1 && compare(list[j]->name, list[j + 1]->name) > 0   //前后两个节点数据进行顺序比较
				|| select == 2 && compare(list[j]->gender, list[j + 1]->gender) > 0
				|| select == 3 && compare(list[j]->birth, list[j + 1]->birth) > 0
				|| select == 4 && compare(list[j]->gzny, list[j + 1]->gzny) > 0
				|| select == 5 && compare(list[j]->xueli, list[j + 1]->xueli) > 0
				|| select == 6 && compare(list[j]->posit, list[j + 1]->posit) > 0
				|| select == 7 && compare(list[j]->tele, list[j + 1]->tele) > 0
				|| select == 8 && compare(list[j]->location, list[j + 1]->location) > 0
				) {
				Employee* temp = (Employee*)malloc(sizeof(Employee));
				temp = list[j]; //交换位置   前者字母排序大于后者则进行位置调换,即按照字母从前往后排序
				list[j] = list[j + 1];
				list[j + 1] = temp;
			}

		}
	}
	for (i = 0; i < employeeCount - 1; i++) {      //将链表指针进行绑定,将链表结点连接
		list[i]->next = list[i + 1];
	}
	list[employeeCount - 1]->next = NULL;//释放临时链表,减少内存占用
	employeeList = list[0];
	findEmployee(1);
	writeEmployee();
}

void menu() {
	//菜单
	printf("*------------------主菜单---------------------*\n");
	printf("*-------------1 :添加员工\n");
	printf("*-------------2 :删除员工\n");
	printf("*-------------3 :修改员工\n");
	printf("*-------------4 :查找员工\n");
	printf("*-------------5 :排序员工\n");
	printf("*-------------0:退出\n");
	printf("*---------------------------------------------*\n");
	printf("请输入选择:");
}

//对比函数
int compare(int a, int b) {
	return a - b;
}
int compare(const char* a, const char* b) {
	return strcmp(a, b);
}

下载地址:
https://download.csdn.net/download/qq_51481160/66345000

  • 8
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值