Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >C语言进阶-回调函数

C语言进阶-回调函数

作者头像
用户9645905
发布于 2022-11-30 00:08:56
发布于 2022-11-30 00:08:56
96100
代码可运行
举报
文章被收录于专栏:Linux学习~Linux学习~
运行总次数:0
代码可运行

目录

前言

回调函数

回调型计算器

回调冒泡排序(模拟qsort库函数)

qsort函数原型

compar参数

代码演示

 冒泡排序(bubble_sort)


前言


  • 本文主要讲解
  • 回调函数的理解
  • 回调实现计算器
  • qsort各种功能的使用
  • 冒泡排序各种功能的实现

回调函数


  • 定义

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

  • 示例1:

回调型计算器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

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 moveleft(int x, int y)
{
	return x << y;
}

int moveright(int x, int y)
{
	return x >> y;
}

int mici(int x, int y)
{
	if (y >= 2)
		return x * mici(x, y - 1);
	return x;
}

int xor(int x, int y)
{
	return x ^ y;
}
//写出相应功能的函数

void menu()
{
	printf("************************\n");
	printf("***1.add        2.sub***\n");
	printf("***3.mul        4.div***\n");
	printf("*5.moveleft 6.moveright*\n");
	printf("***7.xor       8.mici***\n");
	printf("******** 0.exit ********\n");
	printf("************************\n");
}

void cola(int (*p)(int, int))//回调函数 形参为函数指针,接受函数地址
{
	int x, y;
	printf("请输入两个操作数:\n");
	scanf("%d %d", &x, &y);
	int ret = p(x, y);//利用函数指针,即函数地址来调用相应的函数
	printf("得到结果为:%d\n", ret);
}

int main()//计算器逻辑模拟
{
	int intput = 0;
	do {
		menu();
		printf("请选择:\n");
		scanf("%d", &intput);
		switch (intput)
		{
		case 0:
			printf("退出成功!\n");
			break;
		case 1:
			cola(add);//传入的函数降维成函数地址
			break;
		case 2:
			cola(sub);
			break;
		case 3:
			cola(mul);
			break;
		case 4:
			cola(div);
			break;
		case 5:
			cola(moveleft);
			break;
		case 6:
			cola(moveright);
			break;
		case 7:
			cola(xor);
			break;
		case 8:
			cola(mici);
			break;
		default:
			printf("输入错误!\n");
			break;
		}
	} while (intput);
	return 0;
}
  • 示例2:

回调冒泡排序(模拟qsort库函数)

  • 首先演示一下qsort函数的使用

qsort函数原型

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void qsort(
    void *base,
    size_t nmemb,
    size_t size,
    int (*compar)(const void *, const void *)
    );

  •   头文件:<stdlib.h>
  •   函数功能:qsort()函数的功能是对数组进行排序,数组有nmemb个元素,每个元素大小为size
  •   参数base : base指向数组的起始地址,通常该位置传入的是一个数组名
  •   参数nmemb :nmemb表示该数组的元素个数
  •   参数size :size表示该数组中每个元素的大小(字节数)
  •   参数(*compar)(const void *, const void *):此为指向比较函数的函数指针
  •   函数返回值:无

compar参数

定义:实现比较功能的函数 注意:两个形参是const void *型(便于接收不同指针类型参数) 内部需将const void *型转换成实际类型(访问元素对应的空间大小,空类型指针无法反问)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int compar(const void *p1, const void *p2)
{
}

  •   如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面
  •   如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定
  •   如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面
  • 方法一
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 int compare (const void * a, const void * b)
 {
   if ( *(MyType*)a <  *(MyType*)b ) return -1;
   if ( *(MyType*)a == *(MyType*)b ) return 0;
   if ( *(MyType*)a >  *(MyType*)b ) return 1;
 }

注意:MyType是换成实际数组元素的类型

  • 方法二:

以实际元素是int为例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 int compare (const void * a, const void * b)
 {
     return ( *(int*)a - *(int*)b );
 }

注意:如果变量 a 指向一个较小的负整型数,b指向一个较大的正整型数,(*(int*)a - *(int*)b) 表达式会计算出一个正数,因此,比较int类型元素的大小可以使用大于、小于运算符来比较

代码演示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>
#include<stdlib.h>//qasort函数头文件
#include<string.h>//strcmp函数头文件

struct stu//构建结构体,结构体同样是一种类型
{                //注意结构体类型的作用域,放在前面,后面才能使用结构体
	char name[9];
	int age;
};

int cmp_int(const void* e1, const void* e2)//要实现多功能qsort,所以传入的地址类型会有多种形式
{                                          //而void*空指针类型可以来接收不同的类型,便于保持参数一致性,构成回调函数的特点,形参和返回类型一致
	return *(int*)e1 - *(int*)e2;//知道该使用什么类型,就将其先强制转成对应类型(访问空间大小与指针类型有关),再解引用得到空间内容        
}//e1 - e2为升序,e2-e1为降序

int cmp_char(const void* e1, const void* e2)
{
	return *(char*)e1 - *(char*)e2;//字符类型直接比较,比较的是对应的ASCII码值
}

int cmp_double(const void* e1, const void* e2)
{
	return (int)(*(double*)e1 - *(double*)e2);
}

int cmp_stu_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);//name是字符串,比较需要使用strcmp函数
}//结构体指针->成员 这样访问便捷

int cmp_stu_age(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;//age为整型,直接比较
}

int main()
{
	char ch[] = { 'e','g','a','f','p','b' };
	int arr1[] = { 6,4,5,9,1,2,4,6,3 };
	double arr2[] = { 5.00,4.00,9.00,3.00,7.00 };
	struct stu s[] = { {"zhangsan",18},{"lisi",20},{"wangwu",22} };
	qsort(ch, sizeof(ch) / sizeof(ch[0]), sizeof(ch[0]), cmp_char);
	for (int i = 0; i < sizeof(ch) / sizeof(ch[0]); i++)
	{
		printf("%c ", ch[i]);
	}printf("\n");

	qsort(arr1, sizeof(arr1) / sizeof(arr1[0]), sizeof(arr1[0]), cmp_int);//最后的形参是函数,传入的是函数地址,qsort也相当于是一个回调函数
	for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
	{
		printf("%d ", arr1[i]);
	}printf("\n");

	qsort(arr2, sizeof(arr2) / sizeof(arr2[0]), sizeof(arr2[0]), cmp_double);
	for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++)
	{
		printf("%lf ", arr2[i]);
	}printf("\n");

	qsort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmp_stu_name);
	for (int i = 0; i < sizeof(s) / sizeof(s[0]); i++)
	{
		printf("%s ", s[i].name);
	}printf("\n");

	qsort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmp_stu_age);
	for (int i = 0; i < sizeof(s) / sizeof(s[0]); i++)
	{
		printf("%d ", s[i].age);
	}printf("\n");
                //qsort函数相应比较的功能函数需要自己写
	return 0;
}
  • 输出结果:

 冒泡排序(bubble_sort)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct stu
{
	char name[9] ;
	int age;
};

void sway(char* e1, char* e2,int size)//交换函数 使用char*指针指向一个字节,还需要宽度,才能将元素对应的空间完全交换,实现交换元素
{
	for (int k = 0; k < size; k++)
	{
		char temp = *e1;
		*e1 = *e2;//解引用实现内容交换
		*e2 = temp;
		e1++;//指向下一个字节空间地址
		e2++;
	}
}

void bubble_sort(void* base, int count, int size, int (*cmp)(const void*, const void*))//模拟qsort函数
{
	for (int i = 0; i < count - 1; i++)//趟数
	{
		for (int j = 0; j < count - 1 - i; j++)//一趟中相邻比较对数
		{
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//调用函数 升序
			{
				sway((char*)base + j * size, (char*)base + (j + 1) * size,size);//不符合就交换
			}
		}
	}
}

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

int cmp_char(const void* e1, const void* e2)
{
	return *(char*)e1 - *(char*)e2;
}

int cmp_double(const void* e1, const void* e2)
{
	return (int)(*(double*)e1 - *(double*)e2);
}

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

int cmp_stu_age(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age-((struct stu*)e2)->age;
}
//实现比较不同类型函数的功能

int main()
{
	char ch[] = {'e','g','a','f','p','b'};
	int arr1[] = { 6,4,5,9,1,2,4,6,3 };
	double arr2[] = { 5.00,4.00,9.00,3.00,7.00 };
	struct stu s[] = { {"zhangsan",18},{"lisi",20},{"wangwu",22} };
	bubble_sort(ch, sizeof(ch) / sizeof(ch[0]), sizeof(ch[0]), cmp_char);
	for (int i = 0; i < sizeof(ch) / sizeof(ch[0]); i++)//打印
	{
		printf("%c ", ch[i]);
	}
	printf("\n");

	bubble_sort(arr1, sizeof(arr1) / sizeof(arr1[0]), sizeof(arr1[0]), cmp_int);
	for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");

	bubble_sort(arr2, sizeof(arr2) / sizeof(arr2[0]), sizeof(arr2[0]), cmp_double);
	for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++)
	{
		printf("%lf ", arr2[i]);
	}
	printf("\n");

	bubble_sort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmp_stu_name);
	for (int i = 0; i < sizeof(s) / sizeof(s[0]); i++)
	{
		printf("%s ", s[i].name);
	}
	printf("\n");

	bubble_sort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cmp_stu_age);
	for (int i = 0; i < sizeof(s) / sizeof(s[0]); i++)
	{
		printf("%d ", s[i].age);
	}
	printf("\n");

	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
c语言qsort函数的模拟实现
回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 这样讲也许会有点抽象,等下面讲到实际案例时再具体介绍:>
用户11029269
2024/03/19
900
c语言qsort函数的模拟实现
[C语言]指针进阶(Pointer to the advanced)
本质:const char * pstr = "hello world";本质是把字符串hello world,首字符的地址放到了pstr中.
IT编程爱好者
2023/04/12
5130
[C语言]指针进阶(Pointer to the advanced)
【C】指针进阶
这里需要注意,常量字符串“abcdef”时存放在只读数据区中的,可以读取,但不能更改,所以我们使用const来修饰,防止通过p修改字符串 const char ps = “abcdef”;//这里的ps指向的是字符串的首字符 要想修改字符串中的内容需要用到数组:
阿伟@t
2023/10/10
2030
【C】指针进阶
【C指针进阶】(C精髓)——对指针的更进一步深入剖析(图文近2w详解)
本文承接了上文:初阶指针——全面了解指针,在此基础上对指针进行更深一步的剖析,相信我,也请相信你自己!
诺诺的包包
2023/02/17
5860
【C指针进阶】(C精髓)——对指针的更进一步深入剖析(图文近2w详解)
C语言进阶——指针进阶
指针就是地址,而凡是存储在内存中的值都会有属于自己的地址,指针指向地址,这样我们就能通过指针间接操作变量。我们在指针初阶中介绍了指针的基本概念:如指针大小、野指针问题、指针间的关系运算等,在我们的指针进阶中,将会对指针进行进一步剖析,见识更深的指针!🎊🎊
北 海
2023/07/01
1700
C语言进阶——指针进阶
C语言进阶——指针
str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域, 当几个指针,指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4值相同,地址不同
小李很执着
2024/06/15
1290
C语言进阶——指针
qsort函数的应用以及模拟实现
strcmp函数用于比较字符串的,它的比较方式是比较字符的ASCII码值,并不是长度,后续在库函数模拟篇会讲到.
初阶牛
2023/03/08
6160
qsort函数的应用以及模拟实现
【指针进阶三】实现C语言快排函数qsort&回调函数
因为cmp比较函数需要使用者自行设计,所以对于不同的使用者在qsort函数里传给cmp函数的参数类型可能是任何类型的指针,所以在cmp比较函数内得用void*类型的指针来接收,使用时只需将void* 类型的指针做出相应的强转即可。
MicroFrank
2023/01/16
4980
c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
大家好!上篇文章(c语言进阶部分详解(指针进阶2)_总之就是非常唔姆的博客-CSDN博客)我已经对回调函数进行了初步的讲解和一个简单的使用事例,鉴于篇幅有限没有进行更加详细的解释,今天便来补上。
是Nero哦
2024/01/18
1580
c语言进阶部分详解(经典回调函数qsort()详解及模拟实现)
C语言学习系列-->【关于qsort函数的详解以及它的模拟实现】
对数组的元素进行排序 对数组中由 指向的元素进行排序,每个元素字节长,使用该函数确定顺序。 此函数使用的排序算法通过调用指定的函数来比较元素对,并将指向它们的指针作为参数。
南桥
2024/01/26
1490
C语言学习系列-->【关于qsort函数的详解以及它的模拟实现】
C语言指针深度解剖
指针是C语言的灵魂,深入理解指针,是学好学会C语言的重要前提。因此,本文将重点讲解C语言指针的深度内容。
二肥是只大懒蓝猫
2023/03/30
4850
C语言指针深度解剖
【C语言】指针进阶知识终章
其实这看起来是难以理解的,所以我们可以用typedf(起别名)来简化一下,更加容易认识代码:
平凡的人1
2022/11/15
5070
【C语言】指针进阶知识终章
【C语言】手把手带你拿捏指针(4)(含qsort函数详解)
什么是回调函数?    回调函数就是⼀个通过函数指针调用的函数。    如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发⽣时由另外的一方调用的,用于对该事件或条件进行响应    可能这么说着有些抽象,我们还是举一个例子,比如上一篇文章我们讲到的计算器,我们当时为了解决代码冗余,使用了转移表,也就是函数指针数组,那么是否还有其它方法呢?比如我坚持使用Switch语句,而不使用if语句    这个内容就涉及到我们的回调函数,回调函数简单地说就是将函数指针传给另一个函数,通过这个函数来使用传过来的函数    我们可以将之前冗余的部分包装成函数,最大的冗余就是那个Switch语句,我们来看看冗余部分:
TANGLONG
2024/10/15
980
【C语言】手把手带你拿捏指针(4)(含qsort函数详解)
【C语言篇】深入理解指针4(模拟实现qsort函数)
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。
半截诗
2024/10/09
790
【C语言篇】深入理解指针4(模拟实现qsort函数)
C语言——I /深入理解指针(四)
回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。
用户11015888
2024/03/11
1120
C语言-qsort函数的使用与实现
认识一个新的函数,我们就应该知道它的参数与返回,我们可以通过MSDN去查找相关信息
HABuo
2024/11/19
750
C语言-qsort函数的使用与实现
今天发疯,写一下学校的数组作业
如果是对10个数字进行冒泡排序,那么需要进行9轮比较,每轮比较需要进行9+8+...+1次比较
用户11039545
2024/03/28
860
今天发疯,写一下学校的数组作业
指针进阶(2)
那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
用户10923087
2024/01/23
950
指针进阶(2)
【C语言】qsort函数介绍
讲这个东西之前我们来认识一下回调函数,回调函数就是一个通过函数指针调用的函数。 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数 时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
用户11290673
2024/09/25
790
【C语言】qsort函数介绍
【C语言】C语言数组和指针
---- 友情提醒:本文可能是全csdn最详细的指针内容了,希望你能用心读下去💪💪 前言 接下来的讲解部分是指针的进阶,包含多种指针以及对应的数组,这部分章节对我们来说很重要,也是c语言中的重点模块儿,重要性不言而喻 我们直接进入正题,开始我们今天重要的学习旅程吧😎😎😎 一、指针部分 1.字符指针: 在字符指针使用时,我们通常有两种使用的方式,前者是一般使用方式,后者是我们今天重点所讲部分 int main() { char ch = 'w'; char *pc = &ch; *p
举杯邀明月
2023/04/12
65.1K0
【C语言】C语言数组和指针
相关推荐
c语言qsort函数的模拟实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验