指针进阶(2)

6.函数指针数组

举例:模拟一个计算器实现简单的加减乘除运算

先用传统方法实现

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 menu()
{
	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
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		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;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

 用函数指针数组改进

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 menu()
{
	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;
	//当需要使用多个返回类型和参数类型相同的函数时,可以使用函数指针数组
	//函数指针数组(转移表)-通过下标找到函数地址调用函数
	int(*pfArr[5])(int, int) = { NULL,Add,Sub,Mul,Div };
	//                           0    1   2   3   4
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		if (input > 0 && input < 5)
		{
			printf("请输入两个操作数\n");
			scanf("%d %d", &x, &y);
			ret = pfArr[input](x, y);
			printf("%d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
			break;
		}
		else
			printf("选择错误,请重新选择\n");
	} while (input);

	return 0;
}

使用函数指针数组的好处

1.是当使用多个返回类型和参数类型相同的数组时,添加新的函数更方便

2.代码更简洁 

7.指向函数指针数组的指针

 

 8.回调函数

回调函数  通过 传参 接收 目标函数的指针,通过该指针访问目标函数实现功能,通过回调函数能够实现访问多个  参数类型 和  返回值类型  相同的函数,实现多种功能,具有通用性。

冒泡排序回顾

原理图:

int main()
{
	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[1]);
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
	
	for (i = 0; i < sz; i++)
		printf("%d ", arr[i]);

	return 0;
}

标准库中有一个函数qsort,是用来冒泡排序的

它的参数类型

 关于void*类型

 

 用qsort实现对整型数组的冒泡排序

#include<stdlib.h>
int cmp_int(const void* p1, const void* p2)
{
	return(*(int*)p1 - *(int*)p2);
}//不能直接解引用,需要强制转换类型
print(int arr[],int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
		printf("%d ", arr[i]);
}
test1()qsort排序整型
{
	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);//默认是升序的
	print(arr,sz);
}
int main()
{

	test1();//测试qsort排序整型

    return 0;
}

用qsort对结构体冒泡排序


#include<stdlib.h>
#include<string.h>
struct Stu
{
	char name[20];
	int age;
};
//按年龄大小排序
int cmp_stu_by_age(const void* p1 ,const void* p2)
{
	//指向结构体中的age的指针
	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
//按名字字符串长度排序
int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct Stu*)p1)->name , ((struct Stu*)p2)->name);
}
void test2()
{
	//初始化结构体
		struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 50},{"wangwu", 15} };
		int sz = sizeof(arr) / sizeof(arr[0]); 
		qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}
void test3()
{
	struct Stu arr[] = { {"zhangsan", 20}, {"lisi", 50},{"wangwu", 15} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main()
{
//	test1();//测试qsort排序整型
	test2();//排序结构体
	test3();
}

 过程中可能出现的问题

问题1: 参数只能接受整型值         解决:改用void*的指针

问题2:不同类型的数据比较的方式不同      解决:将两个元素的比较方法,以函数参数的形式传递(回调函数)

问题3:不同类型的数据比较的方式          解决:

具体实现:

比较位置数据类型大小传参时,如何表示  arr[j]  和  arr[j+1]  的地址

 base是void类型指针,不能直接加减,需要强制转换为char类型,char类型大小为1个字节,在它上面进行加减运算能够表示多种所有大小的数据类型

(char*)base 加 j * size(一个元素的大小‘字节’) 能表示第 j 个元素的位置

通过函数指针类型找到回调函数进行比较

 这里进行的是整型比较,因此将接收到的  void*  类型指针强制转换为  int*  ,然后计算

目标是升序排列,当返回值>0,则需要交换这两个这两个指针指向的值

要通过函数实现交换这两个值,只能进行逐字节交换,传递参数应该有两个值的指针, 函数的参数应该有两个char*类型指针,还需要size,也就是该类数据的大小(字节)。

利用循环实现

 

  流程图

加入结构体后的流程图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值