//Take the lead in the bidirectional circular linked list (variable-length structure)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
#define NAMESIZE 24
typedef struct stuinfo{
int id;
char name[NAMESIZE];
int math;
}DATA;
static void print_s(const void *data) // data 接收地址是p->data
{
const DATA *stup = data; // 把接受到的数据放置到结构体中。
printf("%d %s %d\n",
stup->id,
stup->name,
stup->math);
}
static int IdCmp(const void *key, const void *data)
{
const int *id = key;
const DATA *stup = data;
return (*id - stup->id);
}
static int NameCmp(const void *key, const void *data)
{
const char *name = key;
const DATA *stup = data;
return strcmp(name, stup->name);
}
int main()
{
int i;
int id = 5;
char name[NAMESIZE] = "stu3";
DATA stu, *stup;
LIST handle = NULL;
handle = ListCreate(sizeof(DATA)); //handle为头节点的指针,头节点数据域大小为DATA的类型大小。
if(NULL == handle)
return -1;
for(i = 0; i < 6; i++)
{
stu.id = i + 1;
snprintf(stu.name,NAMESIZE,
"stu%d", i + 1); // int snprintf(char *str, size_t size, const char *format, ...);
stu.math = 100 - i;
//ListInsert(handle, &stu, HEADINSERT);
ListInsert(handle, &stu, TAILINSERT);
}
/*find*/
//stup = ListFind(handle, &id, IdCmp);
stup = ListFind(handle, name, NameCmp);
if(stup != NULL)
print_s(stup);
else
printf("not find\n");
ListDelete(handle, name, NameCmp);
ListDelete(handle, &id, IdCmp);
ListDisplay(handle, print_s);
ListDispose(handle);
return 0;
}
----------------------------------------------#ifndef _LIST_H__
#define _LIST_H__
#define HEADINSERT 1
#define TAILINSERT 2
struct listnode;
struct headnode;
typedef struct headnode *LIST;
typedef struct listnode *PtrNode;
typedef void print(const void *);
typedef int cmp(const void *, const void *);
LIST ListCreate(int);
int ListInsert(LIST, const void *, int);
void *ListFind(LIST, const void *, cmp *);
int ListDelete(LIST, const void *, cmp *);
int ListFetch(LIST, const void *, cmp *, void *);
void ListDisplay(LIST, print *);
void ListDispose(LIST);
struct listnode{
struct listnode *prev;
struct listnode *next;
char data[0];
};
struct headnode{
int size;
struct listnode head;
};
#endif
----------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
LIST ListCreate(int size) //LIST 说明返回值handle是struct node * 类型的
{
LIST handle = malloc(sizeof(*handle));
if(NULL == handle)
return NULL;
handle->size = size;
handle->head.next = handle->head.prev = &handle->head;
return handle;
}
int ListInsert(LIST l, const void *data, int mode)//l 为指向头节点的指针handle, data类型为const void *类型,要接受DATA类型变量stu的地址。
{
PtrNode cur = malloc(sizeof(*cur) + l->size); //cur为struct listnode *类型,分配指针域和数据域空间。
if(NULL == cur)
return -1;
memcpy(cur->data, data, l->size); //
if(mode == HEADINSERT) //先连后断
{
cur->prev = &l->head;
cur->next = l->head.next;
}
else if(mode == TAILINSERT)
{
cur->prev = l->head.prev;
cur->next = &l->head;
}
else
{
free(cur);
return -2;
}
cur->next->prev = cur;
cur->prev->next = cur;
return 0;
}
//查找数据,id或name,通过调用main中的IdCmp或NameCmp函数(函数名为函数的地址,所以加*/ cmp * funp) 而cmp表示函数的类型为参数为(const void * ,const void*)返回值为int。
static PtrNode find(LIST l, const void *key, cmp *funp)
{
PtrNode p = l->head.next;
for(; p != &l->head && funp(key,p->data); p = p->next);
return p; //查找返回值为PtrNode 类型
}
void *ListFind(LIST l, const void *key, cmp *funp) //查找数据
{
PtrNode p = find(l, key, funp);
if(p == &l->head)
return NULL;
return p->data; // 返回值为void *类型 //data本身是listnode节点的数据域data[0]的地址,p->data表示地址。
}
int ListDelete(LIST l, const void *key, cmp *funp)
{
PtrNode p = find(l, key, funp);
if(p == &l->head)
return -1;
p->next->prev = p->prev;
p->prev->next = p->next;
free(p);
return 0;
}
int ListFetch(LIST l, const void *key, cmp *funp, void *data)
{
PtrNode p = find(l, key, funp);
if(p == &l->head)
return -1;
memcpy(data, p->data, l->size);
p->next->prev = p->prev;
p->prev->next = p->next;
free(p);
return 0;
}
void ListDisplay(LIST l, print * funp)// print为返回值为void,参数为const void * 类型,函数调传地址,
{
PtrNode p = l->head.next;// p指向第一个节点
while(p != &l->head)
{
funp(p->data);
p = p->next;
}
}
void ListDispose(LIST l)
{
PtrNode p = l->head.next;
PtrNode q;
while(p != &l->head)
{
q = p;
p = p->next;
free(q);
}
free(l);
}