深⼊理解指针(5)

1. 回调函数是什么?

回调函数就是⼀个通过函数指针调⽤的函数。
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现方直接调用,⽽是在特定的事件或条件发生时由另外的⼀⽅调用的,用于对该事件或条件进行响应
深入理解指针(4)中我们写的计算器的⼀般实现代码中是重复出现的,其中虽然执⾏计算的逻辑是区别的,但是输⼊输出操作是冗余的,有没有办法,简化⼀些呢?
只有调⽤函数的逻辑是有差异的,我们可以把调⽤的函数的地址以参数的形式传递过去,使⽤函数指针接收,函数指针指向什么函数就调⽤什么函数,这⾥其实使⽤的就是回调函数的功能。

#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 eum()
{
	printf("*******************************\n");
	printf("***1. add   2. sub   **********\n");
	printf("***3. mul   4. div   **********\n");
	printf("***     0. exit     **********\n");
	printf("*******************************\n");
}

//简易的计算器实现
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		eum();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("输入错误请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

1.1 使用回调函数修改

//使用回调函数改造后
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 eum()
{
	printf("*******************************\n");
	printf("***1. add   2. sub   **********\n");
	printf("***3. mul   4. div   **********\n");
	printf("***     0. exit     **********\n");
	printf("*******************************\n");
}

void Clcs(int (*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("输入两个操作数:>");
	scanf("%d %d", &x, &y);
	ret = (*pf)(x, y);
	printf("%d\n", ret);
}

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		eum();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			Clcs(Add);
			break;
		case 2:
			Clcs(Sub);
			break;
		case 3:
			Clcs(Mul);
			break;
		case 4:
			Clcs(Div);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("输入错误请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

2. qsort使⽤举例

C/C++函数介绍: https://legacy.cplusplus.com/
使用说明
在这里插入图片描述
这里的头文件是#include <stdlib.h>

2.1 使⽤qsort函数排序整型数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp_int(const void* p1, const void* p2)
{
	return (*(int*)p1) - (*(int*)p2);
}

void print1(int* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
}

//测试qsort排序整型结构体
void test1()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//默认是升序的
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	print1(arr, sz);
}

int main()
{
	test1();//打印整型数组
	return 0;
}

运行结果:
在这里插入图片描述

2.2 使⽤qsort排序结构数据按年龄排序

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{
	char name[20];
	int age;
};

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

cmp_stu_by_age(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

test2()
{
	struct Stu arr[] = { {"zhangsan",20},{"lisi",50},{"wangwu",18} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
	print2(arr, sz);
}

//打印结构体age
print2(struct Stu* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", (p + i)->age);
	}
}

int main()
{
	test2();//打印结构体age
	return 0;
}

运行结果:
在这里插入图片描述

2.3 使⽤qsort排序结构数据按名字排序

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_name(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->name - ((struct Stu*)p2)->name;
}

void print3(int* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s ", ((struct Stu*)p + i)->name);
	}
}

test3()
{
	struct Stu arr[3] = { {"zhangsan",18},{"wangwu",30},{"lisi",20} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, 3, sizeof(arr[0]), cmp_stu_by_name);
	print3(arr, sz);
}

//qsort使用
int main()
{	
	test3();//打印结构体name
	return 0;
}

运行结果:
在这里插入图片描述

2.4整体代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp_int(const void* a, const void* b)
{
	return *((int*)a) - *((int*)b);
}

void print1(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

test1()
{
	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]), cmp_int);
	print1(arr, sz);
}

struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_age(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

void print2(int* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", ((struct Stu*)p + i)->age);
	}
}

test2()
{
	struct Stu arr[3] = {{"zhangsan",18},{"wangwu",30},{"lisi",20}};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, 3, sizeof(arr[0]), cmp_stu_by_age);
	print2(arr, sz);
}

int cmp_stu_by_name(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->name - ((struct Stu*)p2)->name;
}

void print3(int* p, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s ", ((struct Stu*)p + i)->name);
	}
}

test3()
{
	struct Stu arr[3] = { {"zhangsan",18},{"wangwu",30},{"lisi",20} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, 3, sizeof(arr[0]), cmp_stu_by_name);
	print3(arr, sz);
}

//qsort使用
int main()
{	
	test1();//打印整型数组
	//test2();//打印结构体age
	//test3();//打印结构体name
	return 0;
}

3. qsort函数的模拟实现

使⽤回调函数,模拟实现qsort(采⽤冒泡的⽅式)。
注意:这⾥使⽤的是 void ∗ \ast 的指针

3.1 整型数组的实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}

void Swap(char* buf1, char* buf2, int size)
{
	for (int i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
void bubble_sort(void* base, int num, int size, int(*cmp)(const void*, const void*))
{
	//趟数
	for (int i = 0; i < num - 1; i++)
	{
		//一趟内部比较的对数
		for (int j = 0; j < num - 1 - i; j++)
		{
			//假设需要升序cmp返回>0,交换
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//两个元素比较
			{
				//交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

void print1(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
}

void test1()
{
	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(int), int_cmp);
	print1(arr, sz);
}

int main()
{
	test1();
	return 0;
}

运行结果:
在这里插入图片描述

3.2 结构体按名字排序实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void Swap(char* buf1, char* buf2, int size)
{
	for (int i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int num, int size, int(*cmp)(const void*, const void*))
{
	//趟数
	for (int i = 0; i < num - 1; i++)
	{
		//一趟内部比较的对数
		for (int j = 0; j < num - 1 - i; j++)
		{
			//假设需要升序cmp返回>0,交换
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//两个元素比较
			{
				//交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

struct Stu
{
	int age;
	char name[10];
};

void com_name(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->name - ((struct Stu*)p2)->name;
}

void print2(struct Stu* p1, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s ", (p1 + i)->name);
	}
}

void test2()
{
	struct Stu arr[] = { {18,"zhangsan"},{30,"lisi"},{20,"wangwu"}};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), com_name);
	print2(arr, sz);
}

//qsort实现
int main()
{
	test2();//结构体打印
	return 0;
}

运行结果:
在这里插入图片描述

3.3 结构体按年龄排序实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void Swap(char* buf1, char* buf2, int size)
{
	for (int i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int num, int size, int(*cmp)(const void*, const void*))
{
	//趟数
	for (int i = 0; i < num - 1; i++)
	{
		//一趟内部比较的对数
		for (int j = 0; j < num - 1 - i; j++)
		{
			//假设需要升序cmp返回>0,交换
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//两个元素比较
			{
				//交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

struct Stu
{
	int age;
	char name[10];
};
//按年龄排序
void com_age(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
//按年龄打印
void print3(struct Stu* p1, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", (p1 + i)->age);
	}
}

void test3()
{
	struct Stu arr[] = { {18,"zhangsan"},{30,"lisi"},{20,"wangwu"} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), com_age);
	print3(arr, sz);
}

//qsort实现
int main()
{
	test3();//结构体打印age
	return 0;
}

运行结果:
在这里插入图片描述

3.4 整体代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
	return *((int*)p1) - *((int*)p2);
}

void Swap(char* buf1, char* buf2, int size)
{
	for (int i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

void bubble_sort(void* base, int num, int size, int(*cmp)(const void*, const void*))
{
	//趟数
	for (int i = 0; i < num - 1; i++)
	{
		//一趟内部比较的对数
		for (int j = 0; j < num - 1 - i; j++)
		{
			//假设需要升序cmp返回>0,交换
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//两个元素比较
			{
				//交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

void print1(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
}

void test1()
{
	int arr[] = { 7,9,3,5,4,6,2,1,0,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), int_cmp);
	print1(arr, sz);
}

struct Stu  //学生
{
	int age;//年龄
	char name[10];//名字
};
//假设按照名字来⽐较
void com_name(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->name - ((struct Stu*)p2)->name;
}

void print2(struct Stu* p1, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s ", (p1 + i)->name);
	}
}
//按照名字来排序
void test2()
{
	struct Stu arr[] = { {18,"zhangsan"},{30,"lisi"},{20,"wangwu"}};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), com_name);
	print2(arr, sz);
}

void com_age(const void* p1, const void* p2)
{
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

void print3(struct Stu* p1, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", (p1 + i)->age);
	}
}

void test3()
{
	struct Stu arr[] = { {18,"zhangsan"},{30,"lisi"},{20,"wangwu"} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), com_age);
	print3(arr, sz);
}

//qsort实现
int main()
{
	//test1();//整型打印
	//test2();//结构体打印
	test3();
	return 0;
}
  • 61
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蹋雾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值