文章来源本人的博客:http://codelifeliwan.github.io/ 转载请注明出处
本代码和语言参考 李先静《系统程序员成长计划》。
回调函数就是由内部实现统一接口,由调用者来决定调用哪一个函数,是对C语言函数指针的一个高级应用。比如我们在Linux内核里面,在设备驱动里面,例如有两个不一样的字符设备。那么对这个设备执行刷新操作(不管是否有刷新操作,这里只举例)需要调用一定的函数,这两个设备所执行的函数一定是不同的。但是,上层的管理数据结构是一样的,在管理数据结构里面分别存入两个刷新操作的函数指针,那么在调用的时候就可以直接用统一接口来执行刷新操作即可。这就是回调函数的一个例子,他实现了传说中的Write Once,Run Anywhere.同时维护起来跟其他的相比更简单。
那么就看看书上的例子:实现一个双向链表(通用链表),它有遍历链表、统计链表中最大值和链表值求和的功能。这三个功能可以写成三个不同也不相关的函数,但是我们可以想到,这三个函数都有着相同的操作,那就是依次遍历。那么就可以将这个遍历抽出来(代码中的dlist_foreach函数),然后根据这三个函数的各自的功能来实现较少重复的代码。 具体代码请看下面:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct _DListNode{
struct _DListNode *prev;
struct _DListNode *next;
void *data;
}DListNode;
typedef void (*DListFunc)(void *ctx,void *data);
void add_dlist_node_int(DListNode *root,DListNode *p){
if(root==NULL)return;
if(p==NULL)return;
p->next=root->next;
p->prev=root;
root->next=p;
}
void delete_dlist_node(DListNode *d){
if(NULL==d)return;
print_int(NULL,d);
d->prev->next=d->next;
d->next->prev=d->prev;
free(d->data);
free(d);
d=NULL;
}
void init(DListNode **root){
int i=0;
int *tmp=NULL;
*root=(DListNode*)(malloc(sizeof(DListNode)));
(*root)->data=(int *)(malloc(sizeof(int)));
*((int *)(*root)->data)=-1;
(*root)->next=(*root)->prev=*root;
for(i=0;i<10;i++){
DListNode *p=(DListNode *)(malloc(sizeof(DListNode)));
tmp=(int *)(malloc(sizeof(int)));
*tmp=i;
p->data=tmp;
add_dlist_node_int(*root,p);
}
}
void dlist_foreach(DListNode *thiz,DListFunc visit,void *context){
DListNode *iter=NULL;
if(NULL==thiz)return;
iter=thiz->next;
while(iter!=NULL&&iter!=thiz){
visit(context,iter);
iter=iter->next;
}
}
void print_int(void *thiz,DListNode *d){
printf("======%d\n",*((int *)(d->data)));
}
void sum_cb(void *thiz,DListNode *d){
(*(int *)(thiz))+=*((int *)(d->data));
}
void find_max(void *thiz,DListNode *d){
int a1=*((int *)(thiz));
int a2=*((int *)(d->data));
if(a1<a2){
*((int *)thiz)=a2;
}
}
void destroy(DListNode **root){
DListNode *iter1=NULL,*iter2=NULL;
if(NULL==(*root))return;
iter1=*root;
while(iter1!=NULL){
iter2=iter1->next;
if(iter2==iter1)iter2=NULL;
delete_dlist_node(iter1);
iter1=iter2;
}
}
int main()
{
DListNode *root=NULL;
int tmp=0;
init(&root);
if(root==NULL){
printf("Root id NULL!\n");
}
dlist_foreach(root,print_int,&tmp);
tmp=0;
dlist_foreach(root,sum_cb,&tmp);
printf("SUB IS: %d\n",tmp);
tmp=0;
dlist_foreach(root,find_max,&tmp);
printf("MAX IS: %d\n",tmp);
destroy(&root);
}
网友评论