C语言中指针的详解(2)


回顾

字符指针就是指向字符的指针

#include <stdio.h>
int main()
{
    
    
	char ch = 'q';
	char* p = &ch;
	*p = 'a';
	return 0;
}

指针数组是用来存放指针的数组

int* arr[10];//整型指针的数组
char* arr[4];//一级字符指针的数组
char** arr[5];//二级字符指针的数组

数组指针就是能够指向数组的指针
arr表示数组首元素的地址
&arr表示数组的地址
在这里插入图片描述

函数指针就是指向函数的指针

#include <stdio.h>
void text()
{
    
    
	printf("hehe\n");
}
int main()
{
    
    
	printf("%p\n", text);
	printf("%p\n", &text);
	return 0;
}

一、函数指针数组

在之前的学习中我们已经知道了什么是指针数组
指针数组就是一个存放指针的数组

int *arr[10];

把一个函数的地址存放到一个数组中,那么这个数组就叫做函数指针数组

int (*parr1[10])();

函数指针数组的用途:转移表
例子:加法器

#include <stdio.h>
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;
}
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("请输入2个操作数");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("ret=%d\n", ret);
			break;
		case 2:
			printf("请输入2个操作数");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("ret=%d\n", ret);
			break;
		case 3:
			printf("请输入2个操作数");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("ret=%d\n", ret);
			break;
		case 4:
			printf("请输入2个操作数");
			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;
}

这个计算器我们也可以使用函数指针数组来实现:

#include <stdio.h>
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;
}
int main()
{
    
    
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
    
    
		menu();
		printf("请选择>");
		scanf("%d",&input);
		int (*pfArr[])(int, int) = {
    
    NULL, Add,Sub,Mul,Div };
		if (0 == input)
		{
    
    
			printf("退出计算器\n");
		}
		else if (input >= 1 && input<= 4)
		{
    
    
			printf("请输入2个操作数");
			scanf("%d %d", &x, &y);
			ret = pfArr[input](x, y);
			printf("ret=%d\n", ret);
		}
		else
		{
    
    
			printf("选择错误,重新选择\n");
		}
	}
	while (input);

	return 0;
}

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

指向函数指针数组的指针是一个指针,指针指向一个数组,数组的元素都是函数指针

int a=10;
int b=20;
int c=30;
int *arr[]={
    
    &a,&b,&c};//这是一个整型指针数组
int* (*p)[3]=&arr;//p是指针,是指向整型指针数组的指针
int (*pfArr[5])(int, int) = {
    
    NULL, Add,Sub,Mul,Div };//pfArr是函数指针数组
int (*(*p)[5])(int ,int )=&pfArr;//p是指针,是指向函数指针数组的指针

三、回调函数

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

接下来我们使用回调函数来实现计算器的功能:

#include <stdio.h>
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 ret = 0;
	printf("请输入2个操作数");
    scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("ret=%d\n", ret);
}
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;
}

接下来我们要使用qsort进行排序,但是在这之前我们先用冒泡排序来对一个整型数组进行升序排序

#include <stdio.h>
void print(int arr[], int sz)
{
    
    
	int i = 0;
	for (i = 0; i < sz; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void bubble_sort(int arr[],int sz)
{
    
    
	int i = 0;
	for (i = 0; i < sz; 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;
			}
		}
	}
}
int main()
{
    
    
	int arr[] = {
    
     9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(arr, sz);
	bubble_sort(arr, sz);
	print(arr, sz);
	return 0;
}

以上这个冒泡排序只适用于整型数组的排序
在用qsort排序之前我们先要了解qsort函数

 void qsort(void* base, //待排序数组的第一个元素的地址 
 	       size_t num, //待排序数组的元素个数
	       size_t size,//待排序数组中一个元素的大小
	       int (* c0mpar)(const void*, const void*)//函数指针-compar指向了一个函数,这个函数是用来比较两个元素的
//1. 排序整型数组, 两个整型可以直接使用>比较
//2. 排序结构体数组,两个结构体的数据不能直接使用>比较也就是不同类型的数据,比较出大小,方法是有差异的
//void* 类型的指针不能进行解引用操作符,也不能进行+-整数的操作
//void* 类型的指针是用来存放任意类型数据的地址
//void* 无具体类型的指针
#include <stdio.h>
#include <stdlib.h>
void print(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)//e1和e2中存放的是需要比较的两个元素的地址
{
    
    
	return *(int*)e1 - *(int*)e2;
}
//qsort排序整型数据
void text1()
{
    
    
	int arr[] = {
    
     9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(arr, sz);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	print(arr, sz);
}
int main()
{
    
    
	text1();
	return 0;
}

qsort排序结构体
按照年龄排

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

int age(const void* e1, const void* e2)
{
    
    
	return((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

void text2()
{
    
    
	struct Stu arr[] = {
    
     {
    
    "zhangsan",24},{
    
    "lisi",16},{
    
    "wangwu",30} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), age);
}

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

按照名字排

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

int name(const void* e1, const void* e2)
{
    
    
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

void text3()
{
    
    
	struct Stu arr[] = {
    
     {
    
    "zhangsan",24},{
    
    "lisi",16},{
    
    "wangwu",30} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), name);
}


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

猜你喜欢

转载自blog.csdn.net/2301_78373304/article/details/132853600