目录
1.功能:
可以通过此系统得到所有食谱信息,插入食谱信息,删除某一个的信息,通过id或卡路里数查找某一个食谱,修改某个食谱的信息,销毁所有食谱信息,对所有食谱信息写入和读出
2.main.c文件
#include"./hash.h"
void menu(void)
{
printf("\\~~~~~1~~~~~添加\n");
printf("\\~~~~~2~~~~~查找id\n");
printf("\\~~~~~3~~~~~查找卡路里\n");
printf("\\~~~~~4~~~~~删除\n");
printf("\\~~~~~5~~~~~显示\n");
printf("\\~~~~~6~~~~~销毁\n");
printf("\\~~~~~7~~~~~修改\n");
printf("\\~~~~~8~~~~~写入\n");
printf("\\~~~~~9~~~~~读出\n");
printf("\\~~~~~-1~~~~退出\n");
}
int main(void)
{
Hash *pHash = NULL;
int reti=createHash(&pHash);
if(reti <0)
{
return MALLOCERROR;
}
int op=0;
data_type item;
data_type newitem;
data_type pdata;
data_type ppdata;
int ret=0;
while(1)
{
menu();
printf("请输入你的选项:\n");
scanf("%d",&op);
if(-1 == op)
{
break;
}
switch(op)
{
case 1: //插入
printf("输入你想要插入的数据:\n");
printf("id号 卡路里数 用餐时间 主食名称\n");
scanf("%d%d%s%s",&item.id,&item.cal,item.date,item.foodname);
ret=InsertHash(pHash,item);
if(ret == OK)
{
printf("插入成功\n");
}
else
{
printf("插入失败\n");
}
break;
case 2: //依据id号查找
printf("请输入要查找数据的id\n");
scanf("%d",&item.id);
findHash(pHash,item);
break;
case 3: //依据卡路里数查找
printf("请输入要查找数据的卡路里数\n");
scanf("%d",&item.cal);
findHash(pHash,item);
break;
case 4: //删除
printf("请输入要删除数据的id号:\n");
scanf("%d",&(item.id));
DeleteHash(pHash,item,&pdata);
printf("删除的数据id为%d\n",pdata.id);
printf("删除的数据卡路里数为%d\n",pdata.cal);
printf("删除的数据用餐时间为%s\n",pdata.date);
printf("删除的数据主食名称为%s\n",pdata.foodname);
break;
case 5: //显示
printf("显示所有食谱信息\n");
ShowHash(pHash);
break;
case 6: //销毁所有数据
printf("销毁所有数据\n");
DestroyHash(pHash);
break;
case 7: //修改食谱数据
printf("请输入要修改数据的id:\n");
scanf("%d",&(item.id));
printf("请输入要修改后新的数据\n");
printf("id号 卡路里数 用餐时间 主食名称\n");
scanf("%d%d%s%s",&newitem.id,&newitem.cal,newitem.date,newitem.foodname);
ChangeHash(pHash,item,newitem);
break;
case 8: //将数据备份到文件中
filewriteHash(pHash);
//printf("备份成功\n");
break;
case 9: //将数据读出
filereadHash(pHash);
//printf("读出成功\n");
break;
}
}
return 0;
}
3.hash.h文件
#ifndef _HASH_H_
#define _HASH_H_
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//定义参考食谱20种
#define SIZE 20
//食谱管理系统
typedef struct food
{
int id;//id号 主key
int cal;//卡路里
char date[20];//早中晚
char foodname[20];//主食名称
}data_type;
//创建一个食谱信息的结构
typedef struct node
{
data_type data;
struct node *next;
}Node;
//定义一个hash表
typedef struct hash
{
Node *HashArr[SIZE];//指向哈希表
int count; //食谱的种数
//int Lastid;//最后一个食谱的id
}Hash;
enum opt
{
ERROR =-4,
EXIST,
NOEXIST,
MALLOCERROR,
OK
};
//创建一个食谱系统
//创建hash表
//参数:hash表的大小
//返回值:hash表的首地址
int createHash(Hash **ppHash);
//哈希映射函数
//参数1:data_type item:数据项的主key
//参数2:质数取余 不大于count的最大质数
//返回值:pos 存储结点的下标
int HashFun(data_type item,int p);
//添加一个食谱信息
//参数1:hash表首地址
//参数2:要插入的数据
//返回值:成功ok
int InsertHash(Hash *pHash,data_type item);
//删除某一个食谱信息
//参数1:hash表首地址
//参数2:要删除的数据存入**pdata中
//返回值:成功OK
int DeleteHash(Hash *pHash,data_type item,data_type *pdata);
//显示所有食谱信息
//参数:hash表首地址
//返回值:成功返回OK
int ShowHash(Hash *pHash);
//修改食谱数据
//参数1:hash表首地址
//参数2:要修改的数据
//参数3:新的数据
//返回值:成功返回OK
int ChangeHash(Hash *pHash,data_type item,data_type newitem);
//hash查找(依据id查找,依据date查找)
//参数1:Hash表的首地址
//参数2:依据item值需要找到pos位置,返回当前数据所在首地址
Node *findHash(Hash *pHash,data_type item);
//销毁所有数据
//参数1:hash表首地址
//参数2:将数据备份到**pdata中
//返回值:成功返回OK
int DestroyHash(Hash *pHash);
//写文件操作,下载信息
//参数:hash表首地址
//返回值:
int filewriteHash(Hash *pHash);
//读文件,
//参数:hash表首地址
//返回值:
int filereadHash(Hash *pHash);
#endif
4.hash.c
4.1 哈希表的创建
#include "./hash.h"
//hash表的创建
int createHash(Hash **ppHash)
{
//1.入参判断
if(ppHash == NULL)
{
return MALLOCERROR;
}
*ppHash =(Hash *)malloc(sizeof(Hash));
if(NULL == *ppHash)
{
perror("malloc error\n");
return MALLOCERROR;
}
//2.初始化哈希表表头
memset(*ppHash,0,sizeof(Hash));
return OK;
}
4.2 哈希映射函数
//哈希函数
int HashFun(data_type item,int p)
{
int pos;
//质数取余
pos=item.id%p;//data.ID
return pos;
}
4.3 查找元素
//数据的查找
Node *findHash(Hash *pHash,data_type item)
{
//1.依据item的值在hash表中的下标位置
int pos =HashFun(item,23);
//2.定义变量,初始化为哈希表当前pos位置对应的结点地址;Node *
Node *pFirst =NULL;
pFirst= pHash->HashArr[pos];
while(pFirst != NULL)
{
//依据id号查找
if(pFirst->data.id == item.id)
{
printf("id为:%d\n",pFirst->data.id);
printf("卡路里数为:%d\n",pFirst->data.cal);
printf("用餐时间为:%s\n",pFirst->data.date);
printf("主食名称为:%s\n",pFirst->data.foodname);
break;
}
//依据卡路里数查找
if(pFirst->data.cal == item.cal)
{
printf("id为:%d\n",pFirst->data.id);
printf("卡路里数为:%d\n",pFirst->data.cal);
printf("用餐时间为:%s\n",pFirst->data.date);
printf("主食名称为:%s\n",pFirst->data.foodname);
break;
}
pFirst = pFirst->next;
}
return NULL;
}
4.4 元素插入
//数据的插入
int InsertHash(Hash *pHash,data_type item)
{
if(pHash == NULL)
{
return NOEXIST;
}
//判断这个数据之前是否已经插入
if(findHash(pHash,item) !=NULL )
{
printf("该数据已经在hash表中\n");
return EXIST;
}
//创建一个新结点
Node *pNew=NULL;
pNew =(Node *)malloc(sizeof(Node));
if(pNew == NULL)
{
perror("malloc error\n");
return MALLOCERROR;
}
memset(pNew,0,sizeof(Node));
pNew->data = item;
//找位置
int pos =HashFun(item,23);
//头插
//先将原本在哈希表此位置的首结点与新结点连接
pNew->next=pHash->HashArr[pos];
//再将新结点放入到此位置的首结点的位置
pHash->HashArr[pos]=pNew;
//pHash->Lastid++;
pHash->count++;
//printf("最后一个id是%d个",pHash->Lastid);
printf("有%d个有效数据\n",pHash->count);
return OK;
}
4.5 元素删除
//数据的删除
int DeleteHash(Hash *pHash,data_type item,data_type *pdata)
{
if(NULL == pHash)
{
return MALLOCERROR;
}
//先找到要删除数据的位置
int pos=HashFun(item,23);
//定义两个游标,pDel指向要删除的结点
Node *pDel=NULL;
Node *pTmp=NULL;
//先让pTmp指向要删除结点位置的首结点
pTmp=pHash->HashArr[pos];
//在这个位置只有一个结点
if(pTmp->next==NULL)
{
pDel=pTmp;
pHash->HashArr[pos]=pDel->next;
*pdata=pDel->data;
free(pDel);
pDel=NULL;
//pHash->Lastid--;
}
else
{
//在要删除的结点后边还有结点
while(pDel->next!=NULL)
{
if(pDel->data.id==item.id)
{
pTmp->next=pDel->next;
*pdata=pDel->data;
free(pDel);
pDel=NULL;
//pHash->Lastid--;
break;
}
pDel=pDel->next;
}
//删除的结点后边没有结点
while(pDel->next==NULL)
{
*pdata=pDel->data;
free(pDel);
pDel=NULL;
//pHash->Lastid--;
}
}
pHash->count--;
return OK;
}
4.6 修改元素数据
//修改食谱数据
//参数1:哈希表首地址
//参数2:要修改的数据
//参数3:新的数据
//返回值:成功返回OK
int ChangeHash(Hash *pHash,data_type item,data_type newitem)
{
if(pHash == NULL)
{
return MALLOCERROR;
}
for(int i=0;i<20;i++)
{
Node *pLink=pHash->HashArr[i];
while(pLink!=NULL)
{
if(pLink->data.id!=item.id)
{
if(pLink->next==NULL)
{
break;
}
pLink=pLink->next;
}
if(pLink->data.id==item.id)
{
pLink->data=newitem;
break;
}
}
}
printf("修改成功\n");
return OK;
}
4.7 显示所有元素数据
//显示所有食谱信息
int ShowHash(Hash *pHash)
{
if(pHash == NULL)
{
return MALLOCERROR;
}
int i;
for(i=0;i<20;i++)
{
Node *pShow=pHash->HashArr[i];
while(pShow != NULL)
{
printf("*****食谱信息*****\n");
printf("ID号:%d\n",pShow->data.id);
printf("卡路里为:%d\n",pShow->data.cal);
printf("用餐时间:%s\n",pShow->data.date);
printf("主食名称:%s\n",pShow->data.foodname);
printf("******************\n");
pShow=pShow->next;
}
}
printf("显示完毕\n");
return OK;
}
4.8 销毁
//销毁所有数据
int DestroyHash(Hash *pHash)
{
if(pHash == NULL)
{
return MALLOCERROR;
}
int i;
Node *pDel=NULL;
for(i=0;i<20;i++)
{
pDel=(pHash)->HashArr[i];
while(pDel !=NULL)
{
(pHash)->HashArr[i]=pDel->next;
free(pDel);
pDel=(pHash)->HashArr[i];
//printf("i=%d",i);
}
//printf("i=%d",i);
}
free(pHash);
pHash=NULL;
printf("销毁成功\n");
return OK;
}
4.9 写入读出文件
//写文件操作
int filewriteHash(Hash *pHash)
{
//打开文件
FILE *fw=NULL;
fw=fopen("hash.txt","w");
if(fw == NULL)
{
return ERROR;
}
//操作文件
for(int i=0;i<20;i++)
{
Node *pLink=pHash->HashArr[i];
if(pLink !=NULL)
{
fwrite(&pLink->data,1,sizeof(data_type),fw);
pLink=pLink->next;
}
}
//关闭文件
fclose(fw);
printf("写入成功\n");
return OK;
}
//读文件操作
int filereadHash(Hash *pHash)
{
//打开文件
FILE *fr=NULL;
fr=fopen("hash.txt","r");
if(fr == NULL)
{
return ERROR;
}
//操作文件
data_type tmp;
while(fread(&tmp,1,sizeof(data_type),fr))
{
InsertHash(pHash,tmp);
}
//关闭文件
fclose(fr);
printf("读出成功\n");
return OK;
}
5.打印