C语言--指针进阶(二)

目录

一.函数指针数组

1.知识先知

2.实际应用

(1)普通写法

(2) 函数指针数组(转移表)写法

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

1.知识先知

(1)指向整型数组指针的数组 

2. 要点讲解

 三.回调函数

1.知识先知

2.实际应用

四.qsort()函数

1.知识先知

(1)有关qsort()函数参数及作用

(2)void*-类型的指针

2.实际应用

 (1)整型数据的比较

 (2)结构体类型数据的比较

 

一.函数指针数组

1.知识先知

函数指针--指向函数的指针--存放的是函数的地址

函数指针数组--存放函数指针的数组--数组中存放的是函数指针

#include 
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int main()
{
	int (*pf1)(int, int) = &Add;
	int (*pf2)(int, int) = ⋐
	//这里可看出pf1和pf2的类型是一样的,都为 int (*) (int ,int)
	
	//创建存放函数指针的数组 pfArr
	int (*pfArr[2])(int, int) = { &Add, &Sub};
	return 0;
}

2.实际应用

模拟实现计算器的功能

(1)普通写法

#include 
//基础写法
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 a = 0, b = 0;
	int result = 0;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个数:\n");
			scanf("%d %d", &a, &b);
			result = Add(a, b);
			printf("%d\n", result);
			break;
		case 2:
			printf("请输入两个数:\n");
			scanf("%d %d", &a, &b);
			result = Sub(a, b);
			printf("%d\n", result);
			break;
		case 3:
			printf("请输入两个数:\n");
			scanf("%d %d", &a, &b);
			result = Mul(a, b);
			printf("%d\n", result);
			break;
		case 4:
			printf("请输入两个数:\n");
			scanf("%d %d", &a, &b);
			result = Div(a, b);
			printf("%d\n", result);
			break;
		case 0:
			printf("程序退出\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
}

 缺点:随着功能的增加,case情况越来越多,代码冗余量逐渐增加

(2) 函数指针数组(转移表)写法

优化思路: 通过观察可以发现 加减乘除 四个函数的形式参数以及返回类型是一样的,而数组元素的元素类型也是相同,因此我们可以将每一个函数当成一个数组成员来处理

#include 
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 a = 0, b = 0;
	int result = 0;
	do
	{
		menu();
		printf("请选择运算方式:>\n");
		scanf("%d", &input);
		//函数指针数组
		int (*pfArr[5])(int, int) = { NULL,Add,Sub,Mul,Div };//添加NULL使下标与对应运算函数对齐

		if (input == 0)
		{
			printf("退出计算器\n");
		}
		else if (input >= 1 && input <= 4)
		{
			printf("请输入两个数:\n");
			scanf("%d %d", &a, &b);
			result = pfArr[input](a, b);
			printf("%d\n", result);
		}
		else
		{
			printf("选择错误,请重新选择!\n");
		}
	} while (input);
}

 注意:该方法使用的前提为函数的返回类型必须一致

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

 1.知识先知

(1)指向整型指针数组的指针

int a=10;
int b=20;
int c=30;
int *arr[]={&a,&b,&c};//整型指针数组

int* (*p)[3]=&arr;//p是一个指针,指向整型指针数组的指针
  •  图示

C语言--指针进阶(二)_第1张图片

2. 要点讲解

函数指针数组——数组——存放的是函数的地址
int (*pfArr[5])(int ,int)={NULL,Add,Sub,Mul,Div};//pfArr是函数指针数组

int (*(*p)[5])(int ,int))=&pfArr//p是一个指针,指向函数指针数组的指针
  •  图示

C语言--指针进阶(二)_第2张图片

 三.回调函数

 1.知识先知

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

2.实际应用

改善计算器
#include 
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 (*p)(int, int))//用函数指针接受函数的地址
{
	int a = 0, b = 0;
	int result = 0;
	printf("请输入两个数:\n");
	scanf("%d %d", &a, &b);
	result = p(a, b);
	printf("%d\n", result);
}

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;
	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);
}
  •  图示

C语言--指针进阶(二)_第3张图片

四.qsort()函数

1.知识先知

(1)有关qsort()函数参数及作用

 qsort()是一个库函数,底层使用的是快速排序的方式对数据进行排序。这个函数可以直接使用,这个函数可以用来排序任意类型的数据

 

void qsort(void* base,//待排序数组的第一个元素的地址
                  size_t num,//待排序数组的元素个数
                  size_t size,//待排序数组中一个元素的大小
                  int (*cmp)(const void*p1, const void*p2)//函数指针--cmp指向一个函数,这个函数是用来比较两个元素的
                  )

 

 cmp函数的要求
p1指向元素>p2指向元素时,返回一个大于0的数字
p1指向元素 p1指向元素 == p2指向元素时,返回0

 

(2)void*-类型的指针

1.该类型的指针不能进行解引用的操作

2.该类型的指针不能进行 + - 整数的操作

 

作用:void*类型的指针是用来存放任意类型数据的地址

int main()
{
    char c = 'a';
    char* p = &c;

    int* pc = &c;//警告:从”char *“到”int *“的类型不兼容

    void* pv = &c;//不会报警告
    return 0;
}

2.实际应用

 (1)整型数据的比较

将数组 arr[]={9,8,7,6,5,4,3,2,1,0}按照升序的方式重新排列

#include 
#include 
void print_arr(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}//打印

//构造整型数据的比较函数
int cmp_int(const void* e1, const void* e2)
{
    return *(int*)e1 - *(int*)e2;
}//构造的相关类型数据的比较函数

void test()
{
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    print_arr(arr, sz);
    qsort(arr, sz, sizeof(arr[0]), cmp_int);//快速排序函数
    print_arr(arr, sz);
}
int main()
{
    test();
    return 0;
}

 (2)结构体类型数据的比较

 结构体数据比较大小
1.按照年龄比
2.按照名字比较

  • 按照年龄比较 
//测试qsort排序结构体数据
struct Stu
{
    char name[20];
    int age;
};

//按照年龄比
int cmp_stu_by_age(const void* e1, const void* e2)
{
    return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

void test2()
{
        struct Stu  arr[] = { {"zhangsan",20},{"lisi",30},{"wangwu",12}};
        int sz = sizeof(arr) / sizeof(arr[0]);
        qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}
int main()
{
    test2();
    return 0;
}
  • 按照姓名比较 
//测试qsort排序结构体数据
struct Stu
{
    char name[20];
    int age;
};
//按照姓名比
int cmp_stu_by_name(const void* e1, const void* e2)
{
    return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);//比较字符串用strcmp
}
void test2()
{
        struct Stu  arr[] = { {"zhangsan",20},{"lisi",30},{"wangwu",12}};
        int sz = sizeof(arr) / sizeof(arr[0]);
        qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main()
{
    test2();
    return 0;
}

 

 

 

 

 

 

你可能感兴趣的:(c语言,c++,算法)