利用动态数组(堆)方式实现员工信息管理

该文章介绍了一个基于C++的员工信息管理系统,利用动态数组(堆)存储和管理员工数据,包括增、删、改、查以及排序等操作。系统支持文件读写,能持久化存储数据,并提供了友好的用户交互界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用动态数组(堆)方式实现员工信息管理


头文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct _SInfo
{
	int nNumb;			//员工工号
	char sName[20];		//姓名
	float fSala;			//工资
}SInfo;
typedef SInfo DATA;// SInfo
//extern DATA* g_pData; //共享变量  哪里都可以改
					//私有变量   间接可以通过接口共享 访问权限 加上static私有
//extern DATA* g_pData;
//extern size_t g_nCount;
DATA* GetData();
size_t GetCount();
void Initialize(); 
void Add(DATA d);
void RemoveAt(int nIndex);
SInfo* FindNumb(int nNumb);
int SortMenu();
int FindMenu();
void Save();
void Print();
void Load();
void Print();
int Menu();

主函数

 #include "main.h"
int main()
{
	system("color 17"); 
	Initialize();
	Load();
	while (Menu())
		;
}

一、 动态数组(功能区)

#include "main.h"
static DATA* g_pData = NULL; //static 相当于private 不让你隔壁用 你用的话用接口 封装 不让你用核心数据
static size_t g_nSize = 4;  //可用资源数 大小  size_t longlong 64位 42亿*42亿
static size_t g_count = 0;	//已存入数量 记录位置	大小==位置	重新申请
DATA* GetData()
{
	return g_pData; //获取结构体对象内容
}
size_t GetCount()
{
	return g_count; //和获取有效数据个数
}

 
int GetFileSize(FILE* pf)  //读取文件大小 利用ftell 和fseek函数
{
	long m = ftell(pf);
	fseek(pf, 0, SEEK_END);
	long n = ftell(pf);
	fseek(pf, m, SEEK_SET);//恢复原位置
	return n;
}
void Initialize() //初始化空间大小
{
	int g_nSize = 4;  //大小
	int g_count = 0;
	g_pData = (DATA*)malloc(sizeof(DATA) * g_nSize);
}
void ReMalloc(size_t nSize) //重新申请空间大小
{
	if (nSize <= g_nSize) //判断一下是否满足申请空间要求
		return;
	DATA* p = (DATA*)malloc(sizeof(DATA) * nSize);  //自己写循环 nCount次 复制数据 或者直接memcpy
	if (!p)
		return;
	memcpy(p, g_pData, sizeof(DATA) * g_count); //将g_pData数据拷贝到新申请的空间中
	free(g_pData);
	g_pData = p; //重新赋值大小
	g_nSize = nSize;
}
void Save()
{
	FILE* pf = fopen("Worker.txt", "wb");
	if (!pf)
		return;
 
	fwrite(g_pData, sizeof(SInfo), g_count, pf);
	fclose(pf);
}
void Load()
{
	FILE* pf = fopen("Worker.txt", "rb");
	if (!pf)
		return;
	long n = GetFileSize(pf) / sizeof(DATA);  //读取文件块数
	if (n > 0)
	{
		ReMalloc(n * 2);
		g_count = fread(g_pData, sizeof(DATA), n, pf);  
		fclose(pf);
	}
}
void Add(DATA d)
{
	if (g_count >= g_nSize) //有效数据大于 给定空间
	{
		ReMalloc(g_count * 2);	//扩容
	}
	g_pData[g_count++] = d;
}
void RemoveAt(int nIndex)
{
	//作业 覆盖
	if (nIndex >= g_count)  //判断是否刪除有效数据
		return;
	if (nIndex < g_count - 1)  //什么时候需要搬运
	{	//g_pData 头部数据 第一个
		memcpy(g_pData + nIndex, g_pData + nIndex + 1, sizeof(DATA) * (g_count - nIndex - 1));
		//距离首地址3个 距离首地址4个 把它后面兄弟往前穿
	}
	g_count--;
}
SInfo* FindNumb(int nNumb)
{
	DATA* p = g_pData;
	while (p - g_pData < (long long)g_count) //p - g_pData 块之间相减判断是否在有效区间内
	{
		if (p->nNumb == nNumb)
			return p;
		++p;
	}
	return NULL;
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
 
//void Print()
//{
//	int i = -1;
//	while (++i < g_count)  //选择有效数据
//	{
//		printf("%g", g_pData[i]);
//	}
//	printf("总共有%d条数据\n", i);
//}
// 

二、业务区实现对人员的增删改查

#include "main.h"
//业务区
void Input()
{
	int nNumb = 0;
	printf("请输入新员工的工号:\n");
	scanf_s("%d",&nNumb);
	SInfo* p = FindNumb(nNumb);
	if (p)
	{
		printf("你输入的工号已经存在:%d\t%s\t%g\n", p->nNumb, p->sName, p->fSala);
		system("pause");
		return;
	}
	SInfo d = { nNumb };
	printf("请继续录入姓名和工资:\n");
	scanf_s("%s%f", d.sName, (int)sizeof(d.sName), &d.fSala);
	Add(d);
	Print();
	Save();

}
void Print()
{
	SInfo* pData = GetData(),
		* p = pData;
	size_t nCount = GetCount();
	printf("%-10s%-20s%s\n", "工号", "姓名", "工资");
	while (p - pData < (long long)nCount)
	{
			printf("%-10d%-20s%0.2f\n", p->nNumb, p->sName, p->fSala);
					++p;//28 跳
 
	}
	printf("总共有%lld条数据\n", nCount);
	system("pause");
	Save();
}
 
void Delete()
{

	int nNumb = 0;
	printf("请输入要删除的员工工号:\n");
	scanf_s("%d", &nNumb);
	SInfo* p = FindNumb(nNumb);
	if (!p)
	{
		printf("你输入的工号不存在 ");
		system("pause");
		return;
	}
	printf("%d\t%s\t%g\n你确定要删除这条记录吗?[Y/N]?", p->nNumb, p->sName, p->fSala);
	char c;
	scanf_s("\n%c", &c, (int)sizeof(c));
	if (c == 'Y' || c == 'y')
	{
		RemoveAt(p - GetData());  //选取头部地址
		Print();
		Save();
	}

	
}
void Modify()
{
	int nNumb = 0;
	printf("请输入要修改的员工工号:\n");
	scanf_s("%d", &nNumb);
	SInfo* p = FindNumb(nNumb);
	if (!p)
	{
		printf("你输入的工号不存在 ");
		system("pause");
		return;
	}
	printf("%d\t%s\t%g\n你确定要修改这条记录吗?[Y/N]?", p->nNumb, p->sName, p->fSala);
	char c;
	scanf_s("\n%c", &c, (int)sizeof(c));
	if (c != 'Y' && c != 'y')
		return; 
	printf("请录入新的姓名和工资!");
	scanf_s("%s%f", &p->sName, (int)sizeof(p->sName), &p->fSala);
	Print();
	Save();
}
 
int Menu()
{
	system("cls");
	puts("\n\n\t\t********************************");
	puts("\t\t*\t1、浏览所有信息        *");
	puts("\t\t*\t2、添加信息            *");
	puts("\t\t*\t3、删除信息            *");
	puts("\t\t*\t4、修改信息            *");
 	puts("\t\t*\t5、查找信息            *");
	puts("\t\t*\t6、排序信息            *");
	puts("\t\t*\t0、退出                *");
	puts("\t\t********************************");
	printf("\t\t请选择:");
	int i = 0;
	scanf_s("%d", &i);
	switch (i)
	{
	case 1:
		Print();
		break;
	case 2:
		Input();
		break;
	case 3:
		Delete();
		break;
	case 4:
		Modify();
		break;
	case 6:
		while (SortMenu())
			;
		break;
	case 5:
		while (FindMenu())
			;
		break;
	}
	return i;
}

2.查找模块

#include "main.h"


void FindbyNumb()
{
	int nNumb;
	printf("请输入你要查找的工号:");
	scanf_s("%d", &nNumb);
	SInfo* p = FindNumb(nNumb);
	if (p)
	{
		printf("%d\t%s\t%g\n", p->nNumb, p->sName, p->fSala);
	}
	else
	{
		puts("你输入的工号不存在!");
	}
	system("pause");

}
void FindbyName()
{
	char sName[20],str[20];
	printf("请输入要查找的员工姓名(允许部分):");
	scanf_s("%s", sName, (int)sizeof(sName));

	 
	int i = -1;
	SInfo* p = GetData();
	int n = GetCount();
	int sum = 0;
	_strlwr(sName);  //把录入的姓名转换成小写
	//不区分大小写
	// 调用strstr之前,把 大串和小串都改成小写或者大写
	//把原内容拿出来改成小写,再跟子串查找

	while (++i<n)  //小于每一个元素
	{
		strcpy(str, p[i].sName); //不改变源  
		_strlwr(str);	//这个在循环里面每变一下就重新转换成小写 		
		if (strstr(str,sName))
		{
			printf("%d\t%s\t%g\n", p[i].nNumb, p[i].sName, p[i].fSala), ++sum;
		}
	}
	printf("总共有%d条匹配的数据\n", sum);
	system("pause");
}
void FindbySalary()
{
	float fMin, fMax;
	printf("请输入一个工资段(2个浮点数):");
	scanf_s("%f%f", &fMin, &fMax);
	if (fMin > fMax)
	{
		float t = fMin;
		fMin = fMax;
		fMax = t;
	}

	int i = -1;
	SInfo* p = GetData();
	int n = GetCount();
	int sum = 0;

	while (++i < n)
	{
		if (p->fSala >= fMin && p->fSala <= fMax)
		{
			printf("%d\t%s\t%g\n", p->nNumb, p->sName, p->fSala);
			++sum;
		}
		++p;
	}
	printf("总共有%d条匹配的数据\n", sum);
	system("pause");
}
int FindMenu()
{
	system("cls");
	puts("\n\n\t\t********************************");
	puts("\t\t*\t1、按工号查找         *");
	puts("\t\t*\t2、按姓名查找         *");
	puts("\t\t*\t3、按工资查找         *");
	puts("\t\t*\t0、返回主菜单         *");
	puts("\t\t********************************");
	printf("\t\t请选择:");
	int i = 0;
	scanf_s("%d", &i);
	switch (i)
	{
	case 1:
		FindbyNumb();
		break;
	case 2:
		FindbyName();
		break;
	case 3:
		FindbySalary();
		break;
	default:
		break;
	}
	return i;
}

3.排序模块

 #include "main.h"
void SortbyNumb()
{
	int i = GetCount();  //5
	SInfo* p = GetData();
	while (--i>0)
	{ //4....1
		int j = 0;
		while (j<i) //j:0...4 j+1:1...5
		{
			if (p[j].nNumb > p[j+1].nNumb)
			{
				SInfo t = p[j];
				p[j] = p[j + 1];
				p[j + 1] = t;

			}
			++j;
		}
	}
	Print();
}
void  SortbyName()
{
	int i = GetCount();
	SInfo* p = GetData();
	while (--i > 0)
	{ //4....1
		int j = 0;
		while (j < i) //j:0...3 j+1:1...4
		{
			if (_stricmp(p[j].sName, p[j+1].sName) > 0) //内容比较strcmp 直接比较是地址之间比较
			{
				SInfo t = p[j];
				p[j] = p[j + 1];
				p[j + 1] = t;

			}
			++j;
		}
	}
	Print();
}
void SortbySalary()
{
	int i = GetCount();
	SInfo* p = GetData();
	while (--i > 0)
	{ //4....1
		int j = 0;
		while (j < i) //j:0...3 j+1:1...4
		{
			if (p[j].fSala > p[j+1].fSala)
			{
				SInfo t = p[j];
				p[j] = p[j + 1];
				p[j + 1] = t;

			}
			++j;
		}
	}
	Print();
}
int SortMenu()
{
	system("cls");
	puts("\n\n\t\t********************************");
	puts("\t\t*\t1、按工号排序         *");
	puts("\t\t*\t2、按姓名排序         *");
	puts("\t\t*\t3、按工资排序         *");
	puts("\t\t*\t0、返回主菜单         *");
	puts("\t\t********************************");
	printf("\t\t请选择:");
	int i = 0;
	scanf_s("%d", &i);
	switch (i)
	{
	case 1:
		SortbyNumb();
		break;
	case 2:
		SortbyName();
		break;
	case 3:
		SortbySalary();
		break;
	default:
		break;
	}
	return i;


}

总结

1、在查找模块要注意关于查找名字函数 这里不区分大小写转换的相应方法 后期会写一个函数来专门进行转换
2、在功能区 注意RemoveAt() ReMalloc()函数相应的判断条件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jcrry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值