C语言精通大牛笔记DAY5_链表与回调函数

C语言精通大牛笔记DAY5_链表与回调函数

1.链表
1.链表要素
  • 链表由节点构成
  • 每个节点由数据域指针域组成
2.数组与链表比较

在这里插入图片描述

3.链表的分类
链表分类1:
  • 静态链表 链表分配在栈上
  • 动态链表 链表分配在堆区
链表分类2:
  • 单向链表
  • 双向链表
链表分类3:
  • 单向循环链表
  • 双向循环链表
4.带头节点的链表

在这里插入图片描述

5.链表完整功能示例
#include "NodeList.h"
//初始化链表
NodeList* init_NodeList()
{
	NodeList*pHeader = malloc(sizeof(NodeList));
	if (pHeader == NULL)
	{
		return NULL;
	}
	pHeader->num = -1;
	pHeader->next = NULL;
	NodeList*pTail = pHeader;
	int in_num = 0;
	while (1)
	{
		printf("请输入链表数据,-1表示停止输入\n");
		scanf("%d", &in_num);
		if (in_num == -1)
		{
			break;
		}
		NodeList*new_Node = malloc(sizeof(NodeList));
		new_Node->num = in_num;
		new_Node->next = NULL;
		pTail->next = new_Node;
		pTail = new_Node;
	}
	return pHeader;
}

//遍历链表
void foreach_NodeList(NodeList*pHeader)
{
	NodeList*nextNode = pHeader->next;
	while(nextNode!=NULL)
	{
		printf("%d\n", nextNode->num);
		nextNode = nextNode->next;
	}
}

//链表的插入
void insert_NodeList(NodeList*pHeader, int old_val, int new_val)
{
	NodeList*cur_node = pHeader->next;
	NodeList*prv_node = pHeader;
	while (cur_node!=NULL)
	{
		if (cur_node->num == old_val)
		{
			break;
		}
		prv_node = cur_node;
		cur_node = cur_node->next;
	}
	NodeList*new_node = malloc(sizeof(NodeList));
	new_node->num = new_val;
	new_node->next = cur_node;
	prv_node->next = new_node;
}

//删除节点
void delete_NodeList(NodeList*pHeader, int val)
{
	NodeList*cur_node = pHeader->next;
	NodeList*prv_node = pHeader;
	while (cur_node!=NULL)
	{
		if (cur_node->num == val)
		{
			prv_node->next = cur_node->next;
			free(cur_node);
			break;
		}
		prv_node = cur_node;
		cur_node = cur_node->next;
	}
	if (cur_node==NULL)
	{
		//printf("未找到想要删除的数据\n");
	}
	return;
}

//清空链表
void clean_NodeList(NodeList*pHeader)
{
	NodeList*cur_node = pHeader;
	NodeList*next_node = NULL;
	while (cur_node!=NULL)
	{
		next_node = cur_node->next;
		free(cur_node);
		cur_node = next_node;
	}
	pHeader->next = NULL;
}

//销毁链表
void free_NodeList(NodeList*pHeader)
{
	NodeList*cur_node = pHeader;
	NodeList*next_node = NULL;
	while (cur_node!=NULL)
	{
		next_node = cur_node->next;
		free(cur_node);
		cur_node = next_node;
	}
}	
2.函数指针
1.函数指针
  • 指向函数入口地址的指针
2.函数名
  • 函数的入口地址
3.函数指针的写法
void function(int a)
{
    printf("hello world\n");
}

void(*pFunc)(int) = function;
//返回值类型 + (指针变量名)(形参列表)
4.函数指针的定义方式
void func(int a,char b)
{
    printf("hello world\n");
}

void test01()
{
    //先定义出函数的类型,再通过类型定义函数指针变量
    typedef void(FUNC_TYPE)(int,char);//定义出一个函数类型,返回值是void,形参列表(int,char)
    FUNC_TYPE * pFunc = func;
    pFunc(10,'a');
}

void test02()
{
    //先定义出函数指针的类型,通过类型定义函数指针变量
    typedef void(*FUNC_TYPE)(int,char);
    FUNC_TYPE pFunc = func;
    pFunc(20,'a');
}

void test03()
{
    //直接定义函数指针变量
    void(*pFunc)(int,char) = func;
    pFunc(20,'a');
}

//函数指针数组
void func1()
{
    printf("func1的调用\n");
}
void func2()
{
    printf("func2的调用\n");
}
void func3()
{
    printf("func3的调用\n");
}

void test04()
{
    void(*fun_arr[3])();
    fun_arr[0] = func1;
    fun_arr[1] = func2;
    fun_arr[2] = func3;
    for(int i = 0; i < 3; i++)
    {
        fun_arr[i]();
    }
}
3.函数指针做函数参数 — 回调函数
1.少废话,先举例
#include<stdio.h>

int Callback_1(int x) // Callback Function 1
{
    printf("Hello, this is Callback_1: x = %d ", x);
    return 0;
}

int Callback_2(int x) // Callback Function 2
{
    printf("Hello, this is Callback_2: x = %d ", x);
    return 0;
}

int Callback_3(int x) // Callback Function 3
{
    printf("Hello, this is Callback_3: x = %d ", x);
    return 0;
}

int Handle(int y, int (*Callback)(int))
{
    printf("Entering Handle Function. ");
    Callback(y);
    printf("Leaving Handle Function. ");
}

int main()
{
    int a = 2;
    int b = 4;
    int c = 6;
    printf("Entering Main Function. ");
    Handle(a, Callback_1);
    Handle(b, Callback_2);
    Handle(c, Callback_3);
    printf("Leaving Main Function. ");
    return 0;
}
2.回调函数的思考

引用

主要还是方便应用程序的开发吧,有点像考试填空的感觉,一般api的提供者做好了大部分必要的工作,剩下需要程序员自己写的代码就是具体应用所需要的代码,举个例子,假设操作系统(或者某框架)提供了执行程序的方法:
void execute()
{
  init(); //初始化必要的资源
  dosomething(); //由程序员自己填写的代码,即回调函数
  destory(); //释放使用到的资源
}
其中第一步和第三步已经实现了,需要程序员根据实际的情况来填写第二步到底要做什么事情,这就是回调函数的典型应用场景.
在高级语言中,回调函数也就是观察者模式的一种应用.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值