一.知识点主要是在代码里,知识点有:循环链表,函数的接口调用, viod* 类型的函数的运用
和循环列表的增删改查 (这里有点难,主要是老师让我们假装不知链表的存储的数据类型,还有就是要我们使用函数指针来 调用函数,,一言难尽 (bug 太多了,还好在老师的帮助下修好了))
二.有6个文件
1.student.h
2.student.c
3.day03.h
4.day03.c
5.main.c
6.makefile
三.代码:
1.student.h
#ifndef __STUDENT_H__
#define __STUDENT_H__
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include"day03.h"
typedef struct student
{
char name[100];
int m_id;
int m_age;
char sex;
}stu,*pstu;
int pcmp_name(const void *x,const void *y);
int pcmp_id(const void *x,const void* y);
void student_show(const void *ptr);
void student_updata_sex1(void *data1,const void* data2);
#endif
2.student.c
/************************************************************************************************************************************************************************************************************************
*文件名:student.c
*作 者:She001
*时 间:
*版 本:
*作 用:学生的函数
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include "student.h"
#include "day03.h"
void student_updata_sex1(void* data1,const void * data2) //修改学生信息中的性别 (函数指针调用)
{
pstu ptem1= (pstu)data1;
const pstu ptem2 = (const pstu) data2;
ptem1->sex=ptem2->sex; //函数的直接赋值
}
int pcmp_name(const void *x,const void *y) //比较学生的姓名是否相同(函数指针调用)
{
if((x==NULL) || (y==NULL))
{
return -1;
}
//printf("1:%s \t 2:%s \n",((stu*)(x))->name,((stu*)(y))->name);
pstu name1 =(pstu)x;
pstu name2 =(pstu)y;
//printf("1:%s \t 2:%s \n",name1->name,name2->name);
return strcmp(name1->name,name2->name);
}
int pcmp_id(const void *x,const void* y) //比较学生的id 是否相同(函数指针调用)
{
if((x=NULL) || (y=NULL))
{
return -1;
}
pstu name1 =(pstu)x;
pstu name2 =(pstu)y;
return name1->m_id - name2->m_id;
}
void student_show(const void *ptr) //显示函数(函数指针调用)
{
if(ptr==NULL)
{
return;
}
pstu student1 =(pstu) ptr;
printf("姓名:%s\t id:%d\t 年龄:%d\t 性别:%c\n",student1->name,student1->m_id,student1->m_age,student1->sex);
}
day03.h
#ifndef __DAY03_H__
#define __DAY03_H__
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct node
{
void * data; //数据域
struct node* next; //指针域 ,指向下一个节点
struct node* prev; //指针域 ,指向上一个节点
}node_t,*pnode_t;
enum node_insert_error //共用体 为了模仿报错返回的值
{
node_insert_error0 = 0, //没错误
node_insert_error1 = 1, //链表的首地址传入错误
node_insert_error2 = 2, //链表的数据节点指针错误
node_insert_error3 = 3, //传入的位置错误
node_insert_error4 = 4, //节点申请失败
};
node_t* create_head_node(); //创建头节点的空间节点
node_t* create_node(); //创建空间节点
int node_insert_end(node_t *head ,void *data ,int size);//尾部添加节点
int node_insert_head(node_t *head ,void *data ,int size);//头部添加节点
void delete_node_head(node_t * head); //删除头部节点
void delete_node_end(node_t * head); //删除尾部节点
int insert_pos_node(node_t *head,int pos,void *data,int size);//在固定的位置增加节点
void node_update(node_t * ptr,const void *data_updata,void (*pUpdate)(void *a,const void *b )); //函数接口
void delete_pos_node(node_t* head,int pos);//在固定的位置删除节点
void delete_some_node(node_t *head);删除除了头节点之外的所有节点
bool isEmpty(node_t *head); ///判断指针是否为空
void node_show(node_t* head,void(*pshow)(const void* ptr )); //输出函数 (函数接口)
node_t* node_find(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y)); //判断查询函数 (函数接口)
void node_delete(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y)); //删除函数 (函数接口)
#endif
day03.c
/************************************************************************************************************************************************************************************************************************
*文件名:day03.c
*作 者:She001
*时 间:
*版 本:
*作 用:双向链表的建立
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include "day03.h"
#include "student.h"
/***************************
* 函数名:create_head_node
* 参数:无
*
*
* 返回值: node_t *s
* 作用:创建头节点的空间节点(x循环列表)
* *************************/
node_t* create_head_node()//创建头节点的空间节点
{
node_t* head = (node_t *)malloc(sizeof(node_t));
if(NULL==head)
{
printf("头节点申请错误!\n");
return NULL;
}
head->data =NULL;
head->next=head;
head->prev=head;
return head;
}
/***************************
* 函数名:create_node
* 参数:无
*
*
* 返回值: node_t *s
* 作用:创建的空间节点
* *************************/
node_t* create_node() //创建空间节点
{
node_t* gw = (node_t *)malloc(sizeof(node_t));
if(NULL==gw)
{
printf("空间申请错误!\n");
return NULL;
}
gw->data=NULL;
gw->next=NULL;
gw->prev=NULL;
return gw;
}
/***************************
* 函数名:node_insert_end
* 参数:node_t *head //头节点
* void *data //数据
* int size //数据大小
*
*
* 返回值: int 类型
* 作用:尾部加入节点(x循环列表)
* *************************/
int node_insert_end(node_t *head ,void *data ,int size)//尾部添加节点
{
if(NULL ==head)
{
printf("首地址错误\n");
return node_insert_error0; //首地址错误
}
if(NULL==data)
{
printf("数据指针错误!\n");
return node_insert_error2; //数据指针错误
}
//申请一个新的节点
node_t* gg=create_node();
if(NULL==gg)
{
printf("申请空间的节点失败!\n");
return node_insert_error4;
}
gg->data=malloc(size);
if(NULL==gg->data)
{
printf("申请空间的节点失败!\n");
return node_insert_error4;
}
memcpy(gg->data,data,size);
head->prev->next=gg;
gg->prev=head->prev;
head->prev=gg;
gg->next=head;
return node_insert_error0;
}
/***************************
* 函数名:node_insert_end
* 参数:node_t *head //头节点
* void *data //数据
* int size //数据大小
*
*
* 返回值: int 类型
* 作用:头部插入空间节点(x循环列表)
* *************************/
int node_insert_head(node_t *head ,void *data ,int size)//头部添加节点
{
if(NULL ==head)
{
printf("首地址错误\n");
return node_insert_error0; //首地址错误
}
if(NULL==data)
{
printf("数据指针错误!\n");
return node_insert_error2; //数据指针错误
}
//申请一个新的节点
node_t* gg=create_node();
if(NULL==gg)
{
printf("申请空间的节点失败!\n");
return node_insert_error4;
}
gg->data=malloc(size);
if(NULL==gg->data)
{
printf("申请空间的节点失败!\n");
return node_insert_error4;
}
memcpy(gg->data,data,size);
gg->next=head->next;
head->next->prev=gg;
head->next=gg;
gg->prev=head;
}
/***************************
* 函数名:isEmpty
* 参数:node_t *head //头节点
*
* 返回值: 无
* 作用:判断链表是否为空
* *************************/
bool isEmpty(node_t *head)
{
if(head==NULL)
{
return true;
}
else if(head->next==head)
{
return true;
}
else
{
return false;
}
}
/***************************
* 函数名:delete_node_end
* 参数:node_t *head //头节点
*
* 返回值: 无
* 作用:删除尾部的空间节点(x循环列表)
* *************************/
void delete_node_end(node_t * head) //删除尾部节点
{
if(isEmpty(head))
{
printf("数据为空!\n");
return;
}
if(NULL ==head)
{
printf("首地址错误\n");
printf("已经是空的!");
//return node_insert_error1; //首地址错误
return;
}
if((head->prev)==NULL)
{
printf("链表已经为空!\n");
//return node_insert_error1;
return;
}
node_t *p = head->prev;
head->prev=head->prev->prev;
head->prev->next=head;
if(p->data!=NULL)
{
free(p->data);
}
printf("删除成功!\n");
free(p);
p=NULL;
}
/***************************
* 函数名:node_insert_head
* 参数:node_t *head //头节点
*
* 返回值: void
* 作用:删除头部的空间节点(x循环列表)
* *************************/
void delete_node_head(node_t * head) //删除头部节点
{
if(isEmpty)
{
return;
}
if(NULL ==head)
{
printf("首地址错误\n");
printf("已经是空的!");
//return node_insert_error1; //首地址错误
return ;
}
if((head->next)==NULL)
{
printf("链表已经为空!\n");
//return node_insert_error1;
return;
}
node_t *p = head->next;
head->next=p->next;
p->next->prev=head;
if(p->data!=NULL)
{
free(p->data);
}
free(p);
p=NULL;
}
/***************************
* 函数名:delete_some_node
* 参数:node_t *head //头节点
*
* 返回值: void
* 作用:删除除了头部的所有空间节点(x循环列表)
* *************************/
void delete_some_node(node_t *head)
{
if(isEmpty)
{
return;
}
while(head->next!=head)
{
delete_node_head(head);
}
}
/***************************
* 函数名:delete_pos_node
* 参数:node_t *head //头节点
*
* 返回值: void
* 作用:删除固定位置的空间节点(x循环列表)
* *************************/
void delete_pos_node(node_t* head,int pos)
{
if(isEmpty)
{
return;
}
node_t* temp= head;
int i=0;
for(i=0;i<pos&& temp->next !=head;++i)
{
temp=temp->next;
}
if(i==pos)
{
temp->prev->next=temp->next;
temp->next->prev=temp->prev;
if(temp->data!=NULL)
{
free(temp->data);
}
free(temp);
temp=NULL;
}
}
/**********************
* 作用: 对某个数据更新
* 参数: ptr 需要修改数据的首地址
* data_updata 需要更新数据的指针
* pUpdate 函数指针
*
* *******************/
void node_update(node_t * ptr,const void *data_updata,void (*pUpdate)(void *a,const void *b ))
{
if(ptr==NULL || data_updata ==NULL || pUpdate==NULL)
{
return ;
}
pUpdate(ptr->data,data_updata);
}
/***************************
* 函数名:node_insert_end
* 参数:node_t *head //头节点
* void *data //数据
* int size //数据大小
* int pos //数据的位置
*
* 返回值: int 类型
* 作用:插入固定的空间节点(x循环列表)
* *************************/
int insert_pos_node(node_t *head,int pos,void *data,int size)
{
if(NULL ==head)
{
printf("首地址错误\n");
return node_insert_error0; //首地址错误
}
if(NULL==data)
{
printf("数据指针错误!\n");
return node_insert_error2; //数据指针错误
}
//申请一个新的节点
node_t* gg=create_node();
if(NULL==gg)
{
printf("申请空间的节点失败!\n");
return node_insert_error4;
}
gg->data=malloc(size);
if(NULL==gg->data)
{
printf("申请空间的节点失败!\n");
return node_insert_error4;
}
memcpy(gg->data,data,size);
int i=0;
node_t *temp =head;
for(i=0;i<pos&&temp->next!=head;i++)
{
temp=temp->next;
}
if(i==pos)
{
gg->prev=temp->prev;
temp->prev->next=gg;
gg->next=temp;
temp->prev=gg;
}
}
/***************************
* 函数名:node_show
* 参数:node_t *head //头节点
* pshow 函数指针
*
* 返回值: 无
* 作用: 打印链表所有的内容
* *************************/
void node_show(node_t* head,void(*pshow)(const void* ptr ))
{
if(head ==NULL || pshow ==NULL)
{
printf("参数错误,传入的指针为空!\n");
return;
}
node_t * temp = head->next;
while(temp->data!=NULL)
{
pshow(temp->data);
temp=temp->next;
}
}
/***************************
* 函数名:node_find
* 参数:node_t *head //头节点
* data_par 需要查找的指针数据
* pcmp 函数指针
* 返回值: int
* 作用: 在循环列表找data_par 的数据
* *************************/
node_t* node_find(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y))
{
if(head==NULL || data_par==NULL || pcmp ==NULL)
{
printf("指针错误!\n");
return NULL;
}
node_t* temp =head->next;
printf("0000000000000000000000000000000000000000\n");
while(temp->data!=NULL)
{
printf("h1:%s\n",((stu*)(temp->data))->name);
printf("h2:%s\n",((stu*)(data_par))->name);
if(pcmp(temp->data,data_par)==0)
{
return temp;
}
temp=temp->next;
printf("-=-=-=-=-=-=-=\n");
}
printf("1111111111111111111111111111111111111111111\n");
return NULL;
}
/***************************
* 函数名:node_delete
* 参数:node_t *head //头节点
* data_par 需要查找的指针数据
* pcmp 函数指针
* 返回值: void
* 作用: 在循环列表找data_par 并且删除他的数据
* *************************/
void node_delete(node_t *head ,void * data_par , int (*pcmp)(const void * x,const void *y))
{
if(head==NULL || data_par==NULL || pcmp ==NULL)
{
printf("指针错误!\n");
return ;
}
node_t* temp =head ->next;
while(temp->data!=NULL)
{
if(pcmp(data_par,temp->data)==0)
{
temp->prev->next=temp->next;
temp->next->prev=temp->prev;
return ;
}
temp=temp->next;
}
}
main.c
/************************************************************************************************************************************************************************************************************************
*文件名:main.c
*作 者:She001
*时 间:
*版 本:
*作 用:程序接口
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include "student.h"
#include "day03.h"
int main()
{
int i;
/*typedef struct student
{
char name[100];
int m_id;
int m_age;
char sex;
}stu,*pstu;*/
stu w={"123",1,1,'0'};
stu w1={"1234",12,12,'1'};
stu w2={"12345",13,13,'2'};
stu w3={"123456",14,14,'3'};
stu w4={"1234567",15,15,'4'};
stu w5={"12345678",16,16,'5'};
node_t* head=create_head_node();
node_insert_head(head ,&w ,sizeof(stu));
node_insert_head(head ,&w1 ,sizeof(stu));
node_insert_head(head ,&w2 ,sizeof(stu));
node_insert_head(head ,&w3 ,sizeof(stu));
node_insert_head(head ,&w4 ,sizeof(stu));
node_insert_head(head ,&w5 ,sizeof(stu));
node_show(head,student_show);
printf("-----------------------------------\n");
delete_node_end(head);
node_show(head,student_show);
printf("++++++++++++++++++++++++++++++++++++\n");
node_t* temp=head;
for(i=0;temp->next!=head;i++)
{
temp=temp->next;
printf("第%d个学生:\n",i+1);
printf("name:%s \n",((stu*)(temp->data))->name);
printf("id:%d\n",((stu*)(temp->data))->m_id); //temp->data 是一个 void * 因为id 是stu 类型的 所以我们需要一个 stu* 类型的指针来指向
printf("age: %d\n",((stu*)(temp->data))->m_age);
printf("sex: %c\n\n",((stu*)(temp->data))->sex);
}
printf("55555555555555555555555555555555555555555555\n");
node_t * pt =node_find(head,&w3,pcmp_name);
if(pt==NULL)
{
printf("没有找到!\n");
}
node_update(pt,&w2,student_updata_sex1);
printf("===============================\n");
node_show(head,student_show);
/*
node_t* temp=head;
for(i=0;temp->next!=head;i++)
{
temp=temp->next;
printf("第%d个学生:\n",i+1);
printf("name:%s \n",((stu*)(temp->data))->name);
printf("id:%d\n",((stu*)(temp->data))->m_id); //temp->data 是一个 void * 因为id 是stu 类型的 所以我们需要一个 stu* 类型的指针来指向
printf("age: %d\n",((stu*)(temp->data))->m_age);
printf("sex: %c\n\n",((stu*)(temp->data))->sex);
}
temp=head->next->next;
node_update(temp,&w,student_updata_sex1);
printf("==========================================================================\n");
temp=head;
for(i=0;temp->next!=head;i++)
{
temp=temp->next;
printf("第%d个学生:\n",i+1);
printf("name:%s \n",((stu*)(temp->data))->name);
printf("id:%d\n",((stu*)(temp->data))->m_id); //temp->data 是一个 void * 因为id 是stu 类型的 所以我们需要一个 stu* 类型的指针来指向
printf("age: %d\n",((stu*)(temp->data))->m_age);
printf("sex: %c\n\n",((stu*)(temp->data))->sex);
}
*/
}
makefile
node : main.o day03.o student.o
gcc -g -o node main.o day03.o student.o
main.o:main.c
gcc -g -c main.c -o main.o
day03.o:day03.c
gcc -g -c day03.c -o day03.o
student.o:student.c
gcc -g -c student.c -o student.o
4.多加 复习(读懂 函数指针)