C语言.指针(4)

1.回调函数是什么?

回调函数就是一个通过函数指针调用的函数

  1. 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数
  2. 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

指针(3)中我们写的计算机的实现的代码中,有一部分代码是重复出现的,其中虽然执行计算的逻辑是区别的,但是输入输出操作是冗余的,有没有办法,简化⼀些呢?

因为在计算机的实现的代码中,只有调用函数的逻辑是有差异的,可以把调用的函数的地址以参数的形式传递过去,使用函数指针接收,函数指针指向什么函数就调用什么函数,这里其实使用的就是回调函数的功能。

//使用回调函数之前
#include<stdio.h>

//实现加法
int Add(int x, int y)
{
	return x + y;
}
//实现减法
int Sub(int x, int y)
{
	return x - y;
}
//实现乘法
int Mul(int x, int y)
{
	return x * y;
}
//实现除法
int Div(int x, int y)
{
	return x / y;
}

//菜单
void meun()
{
	printf("-------------------\n");
	printf("--- 1.Add 2.Sub ---\n");
	printf("--- 3.Mul 4.Div ---\n");
	printf("---    0.Exit   ---\n");
	printf("-------------------\n");
}

int main()
{
	int x, y = 0;
	int input = 0;
	int ret = 0;

	do
	{
		meun();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		default:
			printf("选择错误,请重新选择\n");
			break;
		case 1:
			printf("请输入两个数: ");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("请输入两个数: ");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("请输入两个数: ");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("请输入两个数: ");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("退出游戏\n");
			break;
		}
	} while (input);

	return 0;
}
//使用回调函数之后
#include<stdio.h>

//实现加法
int Add(int x, int y)
{
	return x + y;
}
//实现减法
int Sub(int x, int y)
{
	return x - y;
}
//实现乘法
int Mul(int x, int y)
{
	return x * y;
}
//实现除法
int Div(int x, int y)
{
	return x / y;
}

//菜单
void meun()
{
	printf("-------------------\n");
	printf("--- 1.Add 2.Sub ---\n");
	printf("--- 3.Mul 4.Div ---\n");
	printf("---    0.Exit   ---\n");
	printf("-------------------\n");
}

//回调函数
void calc(int (*pf)(int, int))
{
	int x, y = 0;
	int ret = 0;

	printf("请输入两个数: ");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("ret = %d\n", ret);
}

int main()
{
	int input = 0;
	
	do
	{
		meun();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		default:
			printf("选择错误,请重新选择\n");
			break;
		case 1:
			calc(Add);
			break;
		case 2:
			calc(Sub);
			break;
		case 3:
			calc(Mul);
			break;
		case 4:
			calc(Div);
			break;
		case 0:
			printf("退出游戏\n");
			break;
		}
	} while (input);

	return 0;
}

2.qsprt使用举例

2.1使用qsort函数排序整型数据

#include<stdio.h>
//qsort()函数的使用这得实现一个比较函数
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
    //比较
	qsort(arr, sz, sizeof(arr[0]), int_cmp);
	//打印
	int i = 0;
	for ( i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");//0 1 2 3 4 5 6 7 8 9

	return 0;
}

2.2使用qsort函数排序结构体数据

#include<stdio.h>
#include<string.h>

struct Stu //学生
{
	char name[10];//名字
	int age;//年龄
};

//假如按照年龄来比较
int cmp_stu_by_age(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

//假如按照名字来比较
//strcmp() - 是库函数,是专门来比较两个字符串的大小的
int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}

//假如按照年龄来比较
void test1()
{
	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}

//假如按照名字来比较
void test2()
{
	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}

int main()
{
	test1();
	test2();

	return 0;
}

3.qsort函数的模拟实现

使用回调函数,模拟实现qsort(采用冒泡的排序方式)

代码1:

//使用bubble_sort函数排序整型数据
#include<stdio.h>

int int_cmp(const void* p1, const void* p2)
{
	return ((*(int*)p1) - (*(int*)p2));
}

//交换
void Swap(void* buf1, void* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *((char*)buf1 + i);
		*((char*)buf1 + i) = *((char*)buf2 + i);
		*((char*)buf2 + i) = tmp;
	}
}
//qsort函数的模拟实现
void bubble_sort(void* base, int sz, int width, int (*cmp)(void*, void*))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//使用回调函数,模拟实现qsort
	bubble_sort(arr, sz, sizeof(arr[0]), int_cmp);
	//打印
	for (size_t i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);//0 1 2 3 4 5 6 7 8 9
	}
	printf("\n");

	return 0;
}

代码2:

//使用bubble_sort函数排序结构体数据
#include<stdio.h>
#include<string.h>

struct Stu //学生
{
	char name[10];//名字
	int age;//年龄
};

//交换
void Swap(void* buf1, void* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *((char*)buf1 + i);
		*((char*)buf1 + i) = *((char*)buf2 + i);
		*((char*)buf2 + i) = tmp;
	}
}
//qsort函数的模拟实现
void bubble_sort(void* base, int sz, int width, int (*cmp)(void*, void*))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

//假如按照年龄来比较
int cmp_stu_by_age(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

//假如按照名字来比较
//strcmp() - 是库函数,是专门来比较两个字符串的大小的
int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}

//假如按照年龄来比较
void test1()
{
	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
	int sz = sizeof(s) / sizeof(s[0]);
	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
	bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}

//假如按照名字来比较
void test2()
{
	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
	int sz = sizeof(s) / sizeof(s[0]);
	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}

int main()
{
	test1();
	test2();

	return 0;
}

相关推荐

  1. C语言--指针4

    2024-04-08 00:04:03       15 阅读
  2. C语言.指针4

    2024-04-08 00:04:03       15 阅读
  3. C语言---深入指针4

    2024-04-08 00:04:03       9 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-08 00:04:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-08 00:04:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-08 00:04:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-08 00:04:03       20 阅读

热门阅读

  1. 目标跟踪之多目标跟踪

    2024-04-08 00:04:03       13 阅读
  2. html2canvas+jspdf实现前端导出pdf时,4k屏浏览器卡死

    2024-04-08 00:04:03       15 阅读
  3. 如何启动odoo中logging 日志配置

    2024-04-08 00:04:03       13 阅读
  4. Acwing2024蓝桥杯区间合并

    2024-04-08 00:04:03       13 阅读
  5. python - Django创建项目

    2024-04-08 00:04:03       14 阅读
  6. 【云开发笔记NO.23】初步了解CODING-TSF-TKE

    2024-04-08 00:04:03       14 阅读
  7. git提交代码github

    2024-04-08 00:04:03       13 阅读
  8. [RK3566-Android11] 关于2K (2560x1440)分辨率支持问题

    2024-04-08 00:04:03       12 阅读