数据结构 ——循环双链表的封装2-封装成类的实现
一、面向对象的概念
面向对象就是:把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。对同类对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口与外界发生关系,对象与对象之间通过消息进行通信。程序流程由用户在使用中决定。对象即为人对各种具体物体抽象后的一个概念,人们每天都要接触各种各样的对象,如手机就是一个对象。
二、示例
下面是采用面向对象的思想,将前面的循环双链表封装成类的实现。以项目工程的形式记录
//llist.h
#ifndef LLIST_H_
#define LLIST_H_
#define LLIST_FORWARD 1
#define LLIST_BACKWARD 2
typedef void llist_op(const void *);
typedef int llist_cmp(const void *,const void *);
struct llist_node_st
{
struct llist_node_st *prev;
struct llist_node_st *next;
char data[0];
};
//把结构体封装成类的实现
typedef struct llist_head
{
int size;
struct llist_node_st head;
//封装函数,使用函数指针实现
int (*insert)(struct llist_head *,const void *,int mode);
void *(*find)(struct llist_head *,const void *,llist_cmp *);
int (*delete)(struct llist_head *,const void *,llist_cmp *);
int (*fetch)(struct llist_head *,const void *,llist_cmp *,void *data);
void (*travel)(struct llist_head *,llist_op *);
}LLIST;
LLIST *llist_create(int initsize);
void llist_destroy(LLIST *);
#endif
//llist.c
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include "llist.h"
//将封装的函数放到.c文件中
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 *);
LLIST *llist_create(int initsize)
{
LLIST *new;
new=malloc(sizeof(*new));
if(new==NULL)
return NULL;
new->size=initsize;
new->head.prev=&new->head;
new->head.next=&new->head;
//封装函数必须初始化才能调用接口函数
new->insert=llist_insert;//将插入函数指针赋值给结构体,加括号表示调用函数
new->delete=llist_delete;
new->find=llist_find;
new->fetch=llist_fetch;
new->travel=llist_travel;
return new;
}
int llist_insert(LLIST *ptr,const void *data,int mode)
{
struct llist_node_st *newnode;
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_(LLIST *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 *ptr,const void *key,llist_cmp *cmp)
{
struct llist_node_st *node;
node=find_(ptr,key,cmp);
if(node==&ptr->head)
return NULL;
return node->data;
}
int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{
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 *ptr,const void *key,llist_cmp *cmp,void *data)
{
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 *ptr,llist_op *op)
{
struct llist_node_st *cur;
for(cur=ptr->head.next;cur!=&ptr->head;cur=cur->next)
op(cur->data);
}
void llist_destroy(LLIST *ptr)
{
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);
//调用insert方法
ret=handler->insert(handler,&tmp,LLIST_FORWARD);
if(ret)
break;
}
//llist_travel(handler,print_s);
handler->travel(handler,print_s);
printf("\n");
//查找测试
#if 0
int id=6;
struct score_st *data;
data=handler->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=handler->delete(handler,del_name,name_cmp);
if(ret)
printf("llist_delete failed!\n");
handler->travel(handler,print_s);
#endif
//fetch测试
#if 1
int id=1;
struct score_st *data;
data=malloc(sizeof(struct score_st));
ret=handler->fetch(handler,&id,id_cmp,data);
if(ret)
printf("llist_fetch failed!\n");
else print_s(data);
#endif
llist_destroy(handler);
exit(0);
}