【C语言】15.指针(5)

🎉个人主页: 缘三水的博客
❄专栏传送门:C语言专栏(新手向)
🎀人生格言:行动是迷茫的最好解药


🚀个人介绍:


往篇回顾

【C语言】指针(1)

【C语言】指针(2)

【C语言】指针 (3)

【C语言】指针 (4)


文章目录


正文开始

(一)回调函数

定义

通过函数指针变量 中存放的地址,调用指向的函数

被调用的函数就被称为回调函数

示例

特点:回调函数不是由该函数直接调用,而是在另一方中通过函数指针间接调用

使用回调函数示例

对上一章中的计算器实现,我们还有一种优化方法,就是利用回调函数

c 复制代码
void menu()
{
	printf("*********************\n");
	printf("***1.add     2.sub***\n");
	printf("***3.mul     4.div***\n");
	printf("***0.exit         ***\n");
	printf("*********************\n");

}
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 Calc(int (*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int r = 0;
	printf("请输入两个操作数");
	scanf("%d %d", &x, &y);
	r = pf(x, y);
	printf("%d\n", r);
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请输入:>");
		scanf("%d", &input);
		switch (input)
		{
		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;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

对函数Calc
函数的参数是函数指针,可以接收不同的函数地址
接收的地址不同,调用的函数不同
这个Calc函数就能根据参数的不同完成不同的功能

(二)qsort函数

定义
qsortquick sort 简称,名为快速排序
qsort是C语言中提供的一个排序函数

是基于快速排序算法思想的一种排序算法

优势

  1. 现成的排序算法
  2. 效率 比冒泡排序
  3. qsort可以实现任意类型数据的排序

这里提供C++官网对qsort函数的解释
qsort函数

qsort对应头文件是 #include <stdlib.h>

qsort函数有四个参数

我们来对四个参数进行一一解释

c 复制代码
void qsort (void* base, //指针,指向了被排序数组的第一个元素
					size_t num,//被排序数组的元素个数
					size_t size,//被排序数组的元素的大小,单位是字节
            int (*compar)(const void*,const void*));//函数指针,指向的函数是比较被排序数组中两个元素的比较方法
            

因为不同的数据类型,排序的标准不同
所以最后一个参数是使用qsort函数的用户
根据自己需要,编写一个比较函数,比较两个元素的方法

而对于最后一个参数函数指针 指向的函数返回值类型为int 的解释
如果要排为升序

当比较两个元素时

前面的元素比后面 ,则返回-1

前面的元素与后面一样大 ,则返回0

前面的元素比后面 ,则返回1

使用示例1
给一个整型数组排序

使用示例2
给一个结构体数组排序
按年龄给结构体升序排序

结果

拓展
结构体成员访问操作符 ->

语法格式
结构体指针 -> 成员名

使用示例

特点:通过结构体指针 间接访问结构体成员变量

点操作符. 直接访问结构体成员变量

因此,比较函数还能这么写

c 复制代码
int cmp_stu_by_age(const void* p1, const void* p2)//比较函数
{
	//按年龄大小升序排结构体
	//return (*(struct stu*)p1).age - (*(struct stu*)p2).age;//直接访问
	return ((struct stu*)p1)->age - ((struct stu*)p2)->age;//间接访问

}

使用实例3
按结构体成员名字比较

拓展 strcmp函数

这里的名字是字符串

比较不能使用关系运算符

字符串的比较需要用到strcmp函数

这里提供C++官网对strcmp函数的解释
strcmp函数

strcmp函数比较字符串原理

是根据同一位上的字符对应ASCII码值 的大小比较

不是比较字符串的长度

strcmp函数头文件

c 复制代码
#include <string.h>

示例3代码实现

结果

(三)模拟实现qsort函数

我们能不能根据qsort函数为原型,自己封装一个功能相同 的函数呢?

下面是根据冒泡排序原理编写的代码

示例
排序整型数组

c 复制代码
void print_arr(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

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

void Swap(char* buf1, char* buf2, size_t width)
{
	char tmp = 0;
	for (int i = 0; i < width; i++)
	{
		tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
void bubble2_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int 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[] = { 2,4,6,8,0,1,3,5,7,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print_arr(arr, sz);
	bubble2_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print_arr(arr, sz);
	return 0;
}

示例
按照名字排序结构体数组

c 复制代码
struct stu//定义结构体
{
	char name[30];
	int age;
};
void print_arr(struct stu arr[], int sz)//打印函数
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s : %d\n", arr[i].name, arr[i].age);
	}
	printf("\n");
}

int cmp_stu_by_name(const void* p1, const void* p2)//比较函数
{
	//按名字升序排结构体
	return strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name);

}

void Swap(char* buf1, char* buf2, size_t width)
{
	char tmp = 0;
	for (int i = 0; i < width; i++)
	{
		tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
void bubble2_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* p1, const void* p2))
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int 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()
{
	struct stu arr[] = { {"zhangsan",28},{"lisi",18},{"wangwu",38} };

	int sz = sizeof(arr) / sizeof(arr[0]);
	print_arr(arr, sz);
	bubble2_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
	print_arr(arr, sz);
	return 0;
}

总结

这篇文章我们详细介绍了回调函数,qsort函数以及模拟实现qsort函数,希望能对你有帮助

有错误的地方希望可以得到大佬的指正
最后不要吝啬你的点赞,收藏和评论!!!
感谢你的观看

相关推荐
爱吃大芒果1 小时前
从零开始学 Flutter:状态管理入门之 setState 与 Provider
开发语言·javascript·flutter
清风拂山岗 明月照大江1 小时前
简单文件 IO 示例:使用系统调用读写文件
开发语言·c++·算法
技术净胜1 小时前
MATLAB文本文件读写实操fopen/fscanf/fprintf/fclose全解析
开发语言·matlab
编织幻境的妖2 小时前
Python垃圾回收机制详解
开发语言·python
BrianGriffin2 小时前
JS異步:setTimeout包裝為sleep
开发语言·javascript·ecmascript
遇印记2 小时前
javaOCA考点(基础)
java·开发语言·青少年编程
学困昇2 小时前
Linux基础开发工具(下):调试器gdb/cgdb的使用详解
linux·运维·服务器·开发语言·c++
biter down2 小时前
C++ 组合与继承:从设计本质到实战,吃透高内聚低耦合
开发语言·c++
灰灰勇闯IT2 小时前
C语言实战:字符串元音字母提取器的实现与优化
c语言·开发语言