数组指针、函数指针使用2

函数指针、数组指针的理解

数组指针

函数指针

函数指针数组

函数指针数组的指针

回调函数

qsort函数排序

数组指针

介绍数组指针之前,我们先考虑一个问题----数组指针是指针还是数组?

答案是指针。

定义:数组指针是指向数组的指针,数组指针中存放的是数组的地址。
数组指针的使用:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#define ROW 2
#define COL 3
void print_arr1(int arr[2][3], int row,int col)
{
	assert(arr);
	int i = 0;
	int j = 0;
	for (;i< row; i++)
	{
		for (j=0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
	}
	printf("\n");
}

void print_arr2(int (*arr)[3], int row, int col)
{
	assert(arr);
	int i = 0;
	int j = 0;
	for (; i < row; i++)
	{
		for (j=0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
	}
	printf("\n");
}

int main()
{
	int arr[ROW][COL] = { {1,2,3},{4,5,6} };
	print_arr1(arr,ROW,COL);
	print_arr2(arr, ROW, COL);
	system("pause");
	return 0;
}

由此代码可知,无论是几维数组在传参时均会降维为指向其内部元素类型的指针。二维数组传参时临时变量为数组指针,可省略靠近数组名[]里的数字,其余均不可省略;二维数组的首元素是二维数组的第一行。

函数指针

为什么要有函数指针?

原因是函数也是代码,也是有地址的,函数名/取地址函数名代表其入口地址。

#include<stdio.h>
#include<windows.h>
#include<assert.h>
void test()
{
	;
}
int main()
{
	test();
	printf("%p\n", test);
	printf("%p\n", &test);
	system("pause");
	return 0;
}

定义:是保存函数地址的指针。(4个字节)
void (*test)();//函数指针

函数指针数组

定义:存放函数指针的数组就叫函数指针数组。
void (*test[])();//函数指针数组
函数指针数组的使用:转移表(计算器)
//一般做法
#include<stdio.h>
#include<windows.h>
//#include<assert.h>
void menu()
{
	printf("**************************\n");
	printf("****欢迎来到计算器页面****\n");
	printf("**** 1.add    2.mul  *****\n");
	printf("*****3.sub    4.div1 *****\n");
	printf("*****0.exit          *****\n");
	printf("**************************\n");
}

int add(int x, int y)
{
	return x + y;
}

int mul(int x, int y)
{
	return x * y;
}

int sub(int x, int y)
{
	return x - y;
}

int div1(int x, int y)
{
	return x / y;
}

int main()
{
	int n = 1;
	menu();
	while (n)
	{
		printf("请输入选项:\n");
		scanf("%d", &n);
		int x = 0, y = 0;
		/*printf("请输入两个整数!\n");
		scanf("%d%d", &x, &y);*/    
        //若将两个数字输入放在此处会出现输入错误时不能退出系统,而是显示“输入两个整数”的提示
		switch (n)
		{
		case 1:
			printf("请输入两个整数!\n");
			scanf("%d%d", &x, &y);
			printf("%d\n", add(x, y));
			break;
		case 2:
			printf("请输入两个整数!\n");
			scanf("%d%d", &x, &y);
			printf("%d\n", mul(x, y));
			break;
		case 3:
			printf("请输入两个整数!\n");
			scanf("%d%d", &x, &y);
			printf("%d\n", sub(x, y));
			break;
		case 4:
			printf("请输入两个整数!\n");
			scanf("%d%d", &x, &y);
			printf("%d\n", div1(x, y));
			break;
		case 0:
			printf("退出计算器!\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
		}
	}
}


//使用函数指针数组解决计算器问题

#include<stdio.h>
#include<windows.h>
//#include<assert.h>

void menu()
{
	printf("**************************\n");
	printf("****欢迎来到计算器页面****\n");
	printf("**** 1.add    2.mul  *****\n");
	printf("*****3.sub    4.div1 *****\n");
	printf("*****0.exit          *****\n");
	printf("**************************\n");
}

int add(int x, int y)
{
	return x + y;
}

int mul(int x, int y)
{
	return x * y;
}

int sub(int x, int y)
{
	return x - y;
}

int div1(int x, int y)
{
	return x / y;
}

int main()
{
	int n = 1;
	menu();
	while (n)
	{
		printf("请输入选项:\n");
		scanf("%d", &n);
		int(*arr[5])() = { 0,add,mul,sub,div1 };//转移表
        //定义一个函数指针数组,存放函数地址
		if (n >= 0 && n < 5)
		{
			int x = 0, y = 0;
			printf("请输入两个整数:>\n");
			scanf("%d%d", &x, &y);
			printf("%d\n", (*arr[n])(x,y));//输出结果
		}
		else
		{
			printf("输入有误,请重新输入!\n");
			scanf("%d", &n);
		}
	}
	system("pause");
	return 0;
}

两种方法相比而言,一般方法代码相似度较高,有大量冗余代码;用函数指针数组能减少代码冗余,代码看起来更简洁直观,提高运行速率。

函数指针数组的指针

定义:是指向函数指针数组的指针,数组的元素是函数指针。
void (*(*test)[]))();//函数指针数组的指针

回调函数

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

qsort排序整形数组(冒泡排序)

#include<stdio.h>
#include<windows.h>
#include<assert.h>
int MathCom(const void *x, const void *y)//回调函数MathCom比较相邻元素大小
{
	assert(x);
	assert(y);
	int *x_ = (int *)x;
	int *y_ = (int *)y;
	if (*x_ > *y_)
	{
		return 1;
	}
	else if (*x_ < *y_)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}
void DisplayArr(int arr[], int sz)//打印数组
{
	assert(arr);
	int i = 0;
	for (; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = { 1,4,5,6,958,67,-2,56,3 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:");
	DisplayArr(arr, sz);
	qsort(arr, sz, sizeof(int), MathCom);
	printf("排序后:");
	DisplayArr(arr, sz);
	system("pause");
	return 0;
}

qsort排序字符串

#include<stdio.h>
#include<windows.h>
#include<stdlib.h>   //qsort头文件
#include<search.h>   //qsort头文件
#include<assert.h>
int StringCom(const void *x_, const void *y_)
{
	assert(x_);
	assert(y_);
	char **x = (char **)x_;   // 原数组为char *的数组,其地址为char **类型
	char **y = (char **)y_;
	return strcmp(*x, *y);
}
int main()
{
	char* arr[] = { "dddd","fff","bb","aaaa" };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(char*), StringCom);
	int i = 0;
	for (; i < sz; i++)
	{
		printf("%s\n", arr[i]);
	}	
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42617262/article/details/84405016