首页 > 其他分享 >C语言深入理解指针4

C语言深入理解指针4

时间:2024-09-08 21:53:59浏览次数:7  
标签:arr return 函数 int void C语言 深入 printf 指针

1.回调函数

回调函数是通过函数指针调用的函数
将函数指针作为参数传递给另一个函数,当这个函数指针被用来调用其所指向的函数时,被调用的函数就是回调函数,回调函数不是应该由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应

//改造前-无回调函数
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("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("%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");

}
void calc(int(*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入两个操作数:>");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%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;
}

解释:只有调⽤函数的逻辑是有差异的,我们可以把调⽤的函数的地址以参数的形式传递过去,使⽤函数指针接收,函数指针指向什么函数就调⽤什么函数,这⾥其实使⽤的就是回调函数的功能,可以避免一些代码的冗余。

2.qsort使用

语法

void qsort(void* base,//base指向待排序的第一个元素
	size_t num,//待排序个数
	size_t size,//待排序的数组元素的大小,单位字节
	int(*compar)(const void*, const void*)
	//compar是函数指针,指向函数能比较两个元素
);
//4个参数
//void*是一种指针类型

#include<stdlib.h>
#include <stdio.h>
//qosrt函数的使⽤者得实现⼀个⽐较函数
int int_cmp(const void * p1, const void * p2)
{
 return (*( int *)p1 - *(int *) p2);
}
int main()
{
 int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
 int i = 0;
 
 qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
 for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
 {
 printf( "%d ", arr[i]);
 }
 printf("\n");
 return 0;
}

运行结果
在这里插入图片描述
解释:qsort的参数分别是,待排序数组,数组元素的个数,每个元素大小,比较函数。通过比较函数进行比较,将两个指向常量类型的指针,转换成整形指针解引用,返回差值,如果第一个元素小于第二个元素,返回负数,相等返回0,大于返回正数

3.qsort函数模拟实现

使用回调函数,模拟实现qsort, 采用冒泡方式

#include <stdio.h>
int int_cmp(const void * p1, const void * p2)
{
 return (*( int *)p1 - *(int *) p2);
}
void _swap(void *p1, void * p2, int size)
{
 int i = 0;
 for (i = 0; i< size; i++)
 {
 char tmp = *((char *)p1 + i);
 *(( char *)p1 + i) = *((char *) p2 + i);
 *(( char *)p2 + i) = tmp;
 }
}
void bubble(void *base, int count , int size, int(*cmp )(void *, void *))
{
 int i = 0;
 int j = 0;
 for (i = 0; i< count - 1; i++)
 {
 for (j = 0; j<count-i-1; j++)
 {
 if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)
 {
 _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);
 }
 }
 }
}
int main()
{
 int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
 int i = 0;
 bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
 for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
 {
 printf( "%d ", arr[i]);
 }
 printf("\n");
 return 0;
}

运行结果
在这里插入图片描述
解释:bubble函数参数分别是待排序数组,数组元素个数,每个元素大小,比较函数
调用bubble, 比较相邻元素大小随着外层循环排序次数的减小,内层循环的待比较元素向后移动进行比较,比较整型数时调用int_cmp函数,返回差值,小于0,第一个元素小于第二个元素,等于0相等,大于0,第一个元素大于第二个元素,当返回值大于0时,调用交换函数_swap进行交换,该函数可以处理任何类型的数据,通过遍历每个字节,进行交换

标签:arr,return,函数,int,void,C语言,深入,printf,指针
From: https://blog.csdn.net/weixin_65793499/article/details/141995796

相关文章

  • 鹏哥C语言自定义笔记重点(44-)
    44.不能给地址复制,strcpy拷贝过去连带着\045.46. 47. 48.strstr   //查找子串的一个函数49.strtok  //切割字符串 50.strerror   //返回错误码,所对应的错误信息 检查的是文件51.如果不正确则返回0  52.memcpy负责拷贝两块独立空间......
  • 20240909_011725 c语言 预处理
    在C语言中,第一行#include<stdio.h>是一个预处理指令,用于包含(或说,导入)标准输入输出库(StandardInputOutputLibrary)的头文件。这个库提供了进行输入输出操作的函数,比如printf()用于在屏幕上显示输出,scanf()用于从键盘读取输入等。具体来说:#include是一个预处理指令,告诉编译器......
  • 20240909_021725 c语言 骨架结构
    关注骨架结构明确intmainreturn0的意义与功能......
  • c语言第五章循环1.0
    #define_CRT_SECURE_NO_WARNINGS循环结构例1.11到100求和#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>intmain(){   intsum=0;   for(inti=1;i<=100;i++){      sum=sum+i;   }   printf("%d",sum);   return......
  • JAVA代理-----详细深入介绍
    什么是代理(定义)定义:给目标对象提供一个代理对象,并且由代理对象控制对目标对象的引用为什么要使用JAVA代理(目的)1.功能增强:通过代理业务对原有业务进行增强2.控制访问通过代理对象的方式间接的范文目标对象,防止直接访问目标对象给系统带来不必要的复杂性。例:银行转账的系统......
  • Linux和C语言(Day08)
    一、周练习1.题目一:(25分)1.题目描述:输入终值,输出所有能被7整除的数值及其和              2.评分要求根据接收值准确定义变量类型(2分)提示并输入终值(2分)阅读题目确定循环要素:起始值、终值、步长(3分)循环判断指定范围内能被7整除的数值并输出(5分)核......
  • C语言的动态内存管理
    ......
  • 深入理解指针(一)
    1.内存和地址1.1内存在讲内存和地址之前,我们想有个生活中的案例:假设有一栋宿舍楼,把你放在楼里,楼上有100个房间,但是房间没有编号,你的一个朋友来找你玩儿,如果想找到你,就得安一个房子去找,这样效率很低。但是我们如果根据楼层和楼层的房间情况,应每个房间边上号有的房间号,如果你......
  • 深入解析多智能体强化学习算法的训练效率
    深入解析多智能体强化学习算法的训练效率在多智能体强化学习(MARL)领域,不同算法的训练效率和最终性能差异显著。本文将深入分析几种主流MARL算法的训练特性,探讨影响其效率的关键因素。1.算法概览我们将讨论以下几种典型的MARL算法:VDN(ValueDecompositionNetworks)QM......
  • 深入理解线程池的运行流程
    序言:这篇文章主要记录了java线程池在一些特殊场景出现的奇怪问题。场景核心线程数量为2,最大线程数量为4,生存时间60s,任务队列大小为4。每次向线程池中提交8个任务执行。那么,这个线程池能否正常运行呢?1demo我们可以根据这个要求写一个demo出来publicclassDemo{stati......