数据结构:通过hash表方法创建母猪信息录入系统

本文介绍了一个利用数据结构和哈希算法创建的母猪信息录入系统的实现过程,包括创建主MakeFile,子MakeFile的编写,头文件、主函数和子函数的实现,以及最终的运行结果展示。
摘要由CSDN通过智能技术生成

一.创建主MakeFile

1.先在主目录分别创建四个文件夹,分别是:src  .   include  .  obj  .   bin  ,然后在主目录创建makefile文件。

     

 

OBJS:=main.o pig.o
MyApp:=MyPig
CC:=gcc
CFLAGS:=-c -g -Wall

export OBJS MyApp CC CFLAGS  //将变量传给各目录下的子makefile

ALL:
    make -C ./src/  // 先执行src下的makefile
    make -C ./obj/  //再执行obj下的makefile
.PHONY:clean
clean:
    $(RM) ./obj/*.o
    $(RM) ./bin/*

二.创建子MakeFile

2.进入到src 以及 obj 文件夹下分别再创建makefile文件,makefile如下图:

  src:

ALL:$(OBJS)
	mv $^ ../obj/
main.o:main.c
	$(CC) $(CFLAGS) $< -o $@
pig.o:pig.c
	$(CC) $(CFLAGS) $< -o $@

makefile目的是为了把*.c文件转换为.c文件,并且把.o文件移动到obj文件夹中。

   obj:

ALL:$(MyApp)
	mv $^ ../bin/
$(MyApp):$(OBJS)
	$(CC) $^ -o $@

 makefile目的是为了把所有的.o文件合并转换为可执行文件,并且再把可执行文件移动到bin目录下。

三.编写头文件(.h文件)

#ifndef _PIG_H
#define _PIG_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define SIZE 100
//猪的数据类型的定义
typedef struct pig
{
	char color[20];
	int age;
	char state[20];
	int weight;
	int NUM;
}data_type;
//hash表的节点的定义:一个数据段一个指针段
typedef struct hashnode
{
	data_type data;
	struct hashnode *pNext;
}HashNode;
//hash表的定义
typedef struct hash 
{
	HashNode *HashArr[SIZE];
	int count;
	int LastNum;
}Hash;
//定义一个枚举来列出错误的类型
enum value
{
	NO_EXIST = -7,
	EMPTY_ERROR,
	NUM_ERROR,
	MALLOC_ERROR,
	CREAT_ERROR,
	NULL_ERROR,
	ERROR,
	OK
};

int HashCreat(Hash **ppHash);
int AddBuyPigMessageToHash(Hash *pHash, data_type NewPigData);
int SellPigFromHash(Hash *pHash ,int NUM , data_type *pSellData);
int AlterPigMessage(Hash *pHash, data_type PigData);
int SearchPigMessage(Hash *pHash, int NUM, data_type *pData);
int DestroyHash(Hash **ppHash);
int ShowAllPigMessage(Hash *pHash);

#endif

四.编写主函数 

#include "../include/pig.h"

int main(int argc, const char *argv[])
{
	//创建哈西表
	Hash *pHash = NULL;
	if(HashCreat(&pHash) < 0)
	{
		return ERROR;
	}
	printf("创建哈西表成功\n");

	//导入文件中的内容至哈西表中
	int fr = open("pig.txt",O_RDONLY);
	if(fr < 0)
	{
		perror("open_read error");
	}
	else
	{
		printf("打开存储猪信息的文件成功\n");
		//读取 定义一个可以存储每只猪信息的变量
		data_type AllData;
		while(1)
		{
			int MyRead = read(fr, &AllData, sizeof(AllData));
			if(MyRead < 0)
			{
				perror("读取猪信息失败");
				close(fr);
				DestroyHash(&pHash);
				return ERROR;
			}
			else if(0 == MyRead)
			{
				printf("导入猪的信息完毕\n");
				break;
			}
			else
			{
				//存储读取的信息
				if(AddBuyPigMessageToHash(pHash,AllData) < 0)
				{
					DestroyHash(&pHash);
					close(fr);
					return ERROR;
				}
				printf("已经导入一只猪的信息\n");
				pHash->LastNum = AllData.NUM;
			}
		}
	}

	//定义变量保存新买入母猪的数据
	data_type Data;
	//定义保存猪编号的变量
	int NUM;
	char op[20];
	//定义保存卖出母猪信息的变量
	data_type SellData;

	while(1)
	{
		printf("请输入需要进行的操作:buy,sell,alter,search...\n");
		scanf("%s",op);
		if(0 == strcmp("quit",op))
		{
			printf("退出\n");
			break;
		}
		if(0 == strcmp("buy",op))
		{
			 // 买入
			 printf("请输入新猪的颜色:\n");
			 scanf("%s",Data.color);
			 //自动生成编号
			 Data.NUM = pHash->LastNum + 1;
			 printf("请输入新猪的年龄:\n");
			 scanf("%d",&Data.age);
			 printf("请输入新猪的受孕状态:\n");
			 scanf("%s",Data.state);
			 printf("请输入新猪的重量:\n");
			 scanf("%d",&Data.weight);

			 //调用买入
			 if(AddBuyPigMessageToHash(pHash,Data) < 0)
			 {
			 	DestroyHash(&pHash);
				return ERROR;
			 }
			 printf("%d编号小猪猪买入完毕\n",Data.NUM);
			 //更新最后一头猪的编号
			 pHash->LastNum = Data.NUM;
		}

		else if(0 == strcmp(op,"search"))
		{
			//查找所有的猪或者指定猪的信息
			printf("请输入需要查找的猪的编号:\n");
			scanf("%d",&NUM);
			//0->查看所有猪的信息 非0->查看指定编号猪的信息
			if(SearchPigMessage(pHash, NUM, NULL) < 0)
			{
				DestroyHash(&pHash);
				return ERROR;
			}
			printf("查找成功\n");
		}
		else if(0 == strcmp(op, "sell"))
		{
			//卖猪喽
			printf("正在和买家讨价还价....\n");
			printf("请输入要卖的猪的编号:\n");
			scanf("%d",&NUM);

			//调用卖猪函数
			if(SellPigFromHash(pHash, NUM, &SellData) < 0)
			{
				DestroyHash(&pHash);
				return ERROR;
			}
			printf("%d编号的猪猪售卖完毕",NUM);
			printf("被卖掉的猪的信息如下:\n");
			
			printf("-------------\n");
			printf("颜色:%s\n",SellData.color);
			printf("编号:%d\n",SellData.NUM);
			printf("年龄:%d\n",SellData.age);
			printf("状态:%s\n",SellData.state);
			printf("重量:%d\n",SellData.weight);
			printf("-------------\n");
		}
		else if(0 == strcmp(op,"alter"))
		{
			//修改猪的信息
			printf("请输入要修改信息的猪的编号:\n");
			scanf("%d",&NUM);
			printf("%d编号的猪的信息修改中....\n",NUM);
			data_type PigData;
			if(SearchPigMessage(pHash, NUM, &PigData) < 0)
			{
				DestroyHash(&pHash);
				return ERROR;
			}
			printf("需要修改的猪的信息已找到\n");
			printf("请重新输入猪的年龄:\n");
			scanf("%d",&PigData.age);
			printf("请确认这只猪是否怀孕\n");
			scanf("%s",PigData.state);
			printf("这小子是不是又胖了,请重新输入体重:\n");
			scanf("%d",&PigData.weight);
			//调用修改函数
			if(AlterPigMessage(pHash,PigData) < 0)
			{
				DestroyHash(&pHash);
				return ERROR;
			}
			printf("修改后的猪的信息如下:\n");
			SearchPigMessage(pHash, NUM, NULL);
		}
	}

	//自动保存猪的信息
	int fw = open("pig.txt", O_WRONLY | O_CREAT | O_TRUNC ,0664);
	if(fw < 0)
	{
		perror("open_write error");
		close(fr);
		DestroyHash(&pHash);
		return ERROR;
	}
	printf("打开保存信息文件成功,即将保存所有猪的信息\n");
	int i;
	for(i = 0; i < pHash->LastNum; i++)
	{
		HashNode *pTemp = pHash->HashArr[i];
		while(NULL != pTemp)
		{
			//写入文件
			int MyWrite = write(fw, &pTemp->data, sizeof(pTemp->data));
			if(MyWrite < 0)
			{
				perror("write error");
				close(fr);
				close(fw);
				DestroyHash(&pHash);
				return ERROR;
			}
			else if(0 == MyWrite)
			{
				printf("没有猪的信息\n");
				close(fr);
				close(fw);
				DestroyHash(&pHash);
				return ERROR;
			}
			else
			{
				printf("写入一个猪的信息成功\n");
			}
			//更新pTemp的指向
			pTemp = pTemp->pNext;
		}
	}

	//销毁哈西表
	if(DestroyHash(&pHash) < 0)
	{
		printf("销毁哈西表失bai\n");
		return ERROR;
	}
	printf("销毁哈西表成功\n");
	close(fr);
	close(fw);

	return 0;
}

五.编写子函数

#include "../include/pig.h"

//创建哈西表子函数
//参数:哈西表的首地址
//成功返回ok
int HashCreat(Hash **ppHash)
{
	if(NULL == ppHash)
	{
		return NULL_ERROR;
	}
	*ppHash = (Hash *)malloc(sizeof(Hash));
	if(NULL == *ppHash)
	{
		return MALLOC_ERROR;
	}
	memset(*ppHash, '\0', sizeof(Hash));
	return OK;
}

//买入新猪子函数
//参数1:哈西表的地址
//参数2:即将买入新猪的数据
//成功返回ok
int AddBuyPigMessageToHash(Hash *pHash, data_type NewPigData)
{
	if(NULL == pHash)
	{
		return CREAT_ERROR;
	}
	//根据哈西函数获得NUM和存储地址之间的关系
	//根据算出来的地址存储制定的新猪数据
	//将NewPigData的节点地址保存在HashArr[Index]
	//哈西函数->H(NUM) = NUM-1
	int Index = NewPigData.NUM-1;

	HashNode *pNew = (HashNode *)malloc(sizeof(HashNode));
	if(NULL == pNew)
	{
		return MALLOC_ERROR;
	}
	memset(pNew, 0 ,sizeof(HashNode));

	//赋值
	pNew->data = NewPigData;
	//头插
	pNew->pNext = pHash->HashArr[Index];
	//将pNew重新赋值给hasharr[Index]
	pHash->HashArr[Index] = pNew;
	//更新猪的数量
	pHash->count++;
	return OK;
}
//查找猪猪子函数
//参数1:哈西表的地址
//参数2:查找的猪的编号
//参数3:找到指定的猪的信息
//成功返回ok
int SearchPigMessage(Hash *pHash, int NUM, data_type *pData)
{
	if(NULL == pHash)
	{
		return CREAT_ERROR;
	}
	if(NUM < 0 || NUM >SIZE)
	{
		return NUM_ERROR;
	}

	//根据传入的编号进行不同的操作
	if(0 == NUM)
	{
		//查看所有猪的信息
		ShowAllPigMessage(pHash);
	}
	else
	{
		int Index = NUM-1;
		HashNode *pShow = pHash->HashArr[Index];
		//遍历
		while(NULL != pShow)
		{
			if(NUM == pShow->data.NUM)
			{
				//判断第三个参数是否为NULL决定进行的操作
				if(NULL == pData)
				{
					//只想查看某只猪的信息
					printf("-------------\n");
					printf("颜色:%s\n",pShow->data.color);
					printf("编号:%d\n",pShow->data.NUM);
					printf("年龄:%d\n",pShow->data.age);
					printf("状态:%s\n",pShow->data.state);
					printf("重量:%d\n",pShow->data.weight);
					printf("-------------\n");
				}
				else
				{
					*pData = pShow->data;
				}
				break;
			}
			//更新pShow的指向
			pShow = pShow->pNext;
		}
		//判断引起循环终止的条件
		if(NULL == pShow)
		{
			printf("需要查找的%d编号的小猪猪还没买",NUM);
			return NO_EXIST;
		}
	}
	return OK;
}
//显示所有的猪猪信息的子函数
//参数:哈西表的地址
//成功返回ok
int ShowAllPigMessage(Hash *pHash)
{
	if(NULL ==pHash)
	{
		return CREAT_ERROR;
	}
	//遍历哈西表
	int i;
	HashNode *pTemp = NULL;
	printf("目前猪圈的猪猪个数为:%d个,具体的猪猪信息如下:\n",pHash->count);
	for(i = 0; i < pHash->LastNum; i++)
	{
		pTemp = pHash->HashArr[i];
		while(NULL != pTemp)
		{
			printf("-------------\n");
			printf("颜色:%s\n",pTemp->data.color);
			printf("编号:%d\n",pTemp->data.NUM);
			printf("年龄:%d\n",pTemp->data.age);
			printf("状态:%s\n",pTemp->data.state);
			printf("重量:%d\n",pTemp->data.weight);
			printf("-------------\n");

			//更新指针指向
			pTemp = pTemp->pNext;
		}
	}
	return OK;
}
//卖猪函数
//参数1:哈系表的地址
//参数2:即将被卖掉的猪的编号
//参数3:即将卖掉的猪的信息
//成功返回ok
int SellPigFromHash(Hash *pHash, int NUM, data_type *pSellData)
{
	if(NULL == pHash)
	{
		return CREAT_ERROR;
	}
	if(NUM <= 0 || NUM > SIZE)
	{
		printf("猪的编号不对\n");
		return NUM_ERROR;
	}
	if(NULL == pSellData)
	{
		return NULL_ERROR;
	}
	//通过编号找猪
	//先保存被卖的猪的信息
	//释放被卖的猪的节点空间
	//置空
	
	int Index = NUM-1;
	HashNode *pTemp = pHash->HashArr[Index];
	if(NULL == pTemp)
	{
		printf("该位置没有猪的信息\n");
		return EMPTY_ERROR;
	}
	else
	{
		if(NUM == pTemp->data.NUM)
		{
			//保存被卖的猪的信息
			*pSellData = pTemp->data;
			//保存pTemp->pNext到pHash->HashArr[Index]
			pHash->HashArr[Index] = pTemp->pNext;
			free(pTemp);
			pTemp = NULL;
			//猪的个数减少
			pHash->count--;
		}
		else
		{
			//pTemp指向节点里的num不是我们要找的猪
			HashNode *pPre = pTemp;
			HashNode *pSell = pPre->pNext;
			while(NULL != pSell)
			{
				//pTemp后面有节点
				if(NUM == pSell->data.NUM)
				{
					*pSellData = pSell->data;
					//保存后续地址
					pPre->pNext = pSell->pNext;
					free(pSell);
					pSell = NULL;
					pHash->count--;
				}
				else
				{
					//还是没有找到
					pPre = pSell;
					pSell = pSell->pNext;
				}
			}
		}
	}
	return OK;
}
//修改猪的信息(赚钱)函数
//参数1:哈系表的地址
//参数2:修改猪的信息
//成功返回ok
int AlterPigMessage(Hash *pHash, data_type PigData)
{
	if(NULL == pHash)
	{
		return CREAT_ERROR;
	}
	
	int Index = PigData.NUM-1;
	HashNode *pTemp = pHash->HashArr[Index];
	while(NULL != pTemp)
	{
		if(PigData.NUM == pTemp->data.NUM)
		{
			pTemp->data = PigData;
			break;
		}
		pTemp = pTemp->pNext;
	}
	if(NULL == pTemp)
	{
		printf("没有这个编号的猪\n");
	}
	return OK;
}

//销毁函数
//参数1:哈西表的首地址
//成功返回ok
int DestroyHash(Hash **ppHash)
{
	if(NULL == ppHash)
	{
		return NULL_ERROR;
	}
	if(NULL == *ppHash)
	{
		return CREAT_ERROR;
	}
	//先释放每一个指针数组元素中有可能存储的单链表
	//再释放哈西表
	int i;
	HashNode *pNode = NULL;
	for(i = 0; i < (*ppHash)->LastNum; i++)
	{
		pNode = (*ppHash)->HashArr[i];
		//头删法删除单链表
		while(NULL != pNode)
		{
			(*ppHash)->HashArr[i] = pNode->pNext;
			free(pNode);
			pNode = (*ppHash)->HashArr[i];
		}

	}
	//删除哈西表
	free(*ppHash);
	*ppHash = NULL;
	return OK;
}

六.运行结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值