数据结构 ——循环双链表的封装3-隐藏结构体
一、下面是基于变长结构体的循环双链表进行进一步封装,将结构体进行隐藏封装的实现,以项目工程的形式记录
//llist.h
#ifndef LLIST_H_
#define LLIST_H_
//将数据结构隐藏和封装,只暴露接口给用户使用
typedef void LLIST;
#define LLIST_FORWARD 1
#define LLIST_BACKWARD 2
typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);
LLIST *llist_create(int initsize);
int llist_insert(LLIST *,const void *,int mode);
void *llist_find(LLIST *,const void *,llist_cmp *);
int llist_delete(LLIST *,const void *key,llist_cmp *);
int llist_fetch(LLIST *,const void *key,llist_cmp *,void *data);
void llist_travel(LLIST *,llist_op *);
void llist_destroy(LLIST *);
#endif
//llist.c
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include "llist.h"
//将数据结构放到.c文件中
struct llist_node_st
{
struct llist_node_st *prev;
struct llist_node_st *next;
char data[0];//变长结构体,0字节开销,做占位符
};
/*
typedef struct
{
int size;
struct llist_node_st head;
}LLIST;
*/
struct llist_head_st
{
int size;
struct llist_node_st head;
};
LLIST *llist_create(int initsize)
{
struct llist_head_st *new;
new=malloc(sizeof(*new));
if(new==NULL)
return NULL;
new->size=initsize;
new->head.prev=&new->head;
new->head.next=&new->head;
return new;
}
int llist_insert(LLIST *p,const void *data,int mode)
{
struct llist_node_st *newnode;
struct llist_head_st *ptr=p;//将传过来的void*转化为结构体指针,进行使用
newnode=malloc(sizeof(*newnode)+ptr->size);
if(newnode==NULL)
return -1;
memcpy(newnode->data,data,ptr->size);
if(mode==LLIST_FORWARD)
{
newnode->prev=&ptr->head;
newnode->next=ptr->head.next;
}
else if(mode==LLIST_BACKWARD)
{
newnode->prev=ptr->head.prev;
newnode->next=&ptr->head;
}
else
{
return -3;
}
newnode->prev->next=newnode;
newnode->next->prev=newnode;
return 0;
}
static struct llist_node_st *find_(struct llist_head_st *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur!=&ptr->head;cur=cur->next)
{
if(cmp(key,cur->data)==0)
break;
}
return cur;
}
void *llist_find(LLIST *p,const void *key,llist_cmp *cmp)
{
struct llist_head_st *ptr=p;//将传过来的void*转化为结构体指针,进行使用
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
return NULL;
return node->data;
}
int llist_delete(LLIST *p,const void *key,llist_cmp *cmp)
{
struct llist_head_st *ptr=p;//将传过来的void*转化为结构体指针,进行使用
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
return -1;
node->prev->next=node->next;
node->next->prev=node->prev;
free(node);
return 0;
}
int llist_fetch(LLIST *p,const void *key,llist_cmp *cmp,void *data)
{
struct llist_head_st *ptr=p;//将传过来的void*转化为结构体指针,进行使用
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
return -1;
node->prev->next=node->next;
node->next->prev=node->prev;
if(data!=NULL)
memcpy(data,node->data,ptr->size);
free(node);
return 0;
}
void llist_travel(LLIST *p,llist_op *op)
{
struct llist_head_st *ptr=p;//将传过来的void*转化为结构体指针,进行使用
struct llist_node_st *cur;
for(cur=ptr->head.next;cur!=&ptr->head;cur=cur->next)
op(cur->data);
}
void llist_destroy(LLIST *p)
{
struct llist_head_st *ptr=p;//将传过来的void*转化为结构体指针,进行使用
struct llist_node_st *cur,*next;
for(cur=ptr->head.next;cur!=&ptr->head;cur=next)
{
next=cur->next;
free(cur);
}
free(ptr);
}
//main.c
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include "llist.h"
#define NAMESIZE 32
struct score_st
{
int id;
char name[NAMESIZE];
int math;
int chinese;
};
static void print_s(const void *record)
{
const struct score_st *r=record;
printf("%d %s %d %d\n",r->id,r->name,r->math,r->chinese);
}
static int id_cmp(const void *key,const void *record)
{
const int *k=key;
const struct score_st *r=record;
return (*k- r->id);
}
static int name_cmp(const void *key,const void *record)
{
const char *k=key;
const struct score_st *r=record;
return strcmp(k,r->name);
}
int main()
{
LLIST *handler;
struct score_st tmp;
int i,ret;
handler = llist_create(sizeof(struct score_st));
if(handler==NULL)
exit(1);
for(i=0;i<7;i++)
{
tmp.id=i;
snprintf(tmp.name,NAMESIZE,"std%d",i);
tmp.math=rand()%100;
tmp.chinese=rand()%100;
ret=llist_insert(handler,&tmp,LLIST_FORWARD);
if(ret)
break;
}
llist_travel(handler,print_s);
printf("\n");
//查找测试
#if 0
//int id=3;
int id=30;
struct score_st *data;
data=llist_find(handler,&id,id_cmp);
if(data==NULL)
printf("Can not find!\n");
else print_s(data);
#endif
//删除测试
#if 0
//int id=6;
char *del_name="std0";
ret=llist_delete(handler,del_name,name_cmp);
if(ret)
printf("llist_delete failed!\n");
llist_travel(handler,print_s);
#endif
//fetch测试
#if 1
int id=1;
struct score_st *data;
data=malloc(sizeof(struct score_st));
ret=llist_fetch(handler,&id,id_cmp,data);
if(ret)
printf("llist_fetch failed!\n");
else print_s(data);
#endif
llist_destroy(handler);
exit(0);
}