当前位置: 首页 > news >正文

网站策划的内容wordpress3.8 中文标签

网站策划的内容,wordpress3.8 中文标签,seo优化营销专员招聘,北京网站设计 培训前言 在C语言的学习中,指针一直是一个让人又爱又恨的话题。它强大而灵活,但也容易让人陷入困惑。今天,我们就来深入探讨指针的一个重要应用——回调函数,以及基于回调函数的经典函数qsort。 一、回调函数:隐藏在背后…

前言

在C语言的学习中,指针一直是一个让人又爱又恨的话题。它强大而灵活,但也容易让人陷入困惑。今天,我们就来深入探讨指针的一个重要应用——回调函数,以及基于回调函数的经典函数qsort。

一、回调函数:隐藏在背后的英雄

先来看一个实际问题。在编写代码时,我们常常会遇到一些重复的逻辑,比如在实现一个简单的计算器程序时,输入输出的操作是重复的,只有具体的计算逻辑不同。传统的解决方法是写多个函数,每个函数都包含输入输出和计算逻辑,但这样会导致代码冗余。而回调函数的出现,就是为了解决这个问题。

1.1 回调函数是什么

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

1.2 使用回调函数改造计算器程序

一个使用回调函数改造计算器程序的例子。改造前的代码中,每个计算操作(加、减、乘、除)都需要单独写输入输出和计算逻辑,代码冗长且重复。而使用回调函数后,我们把计算逻辑的函数地址作为参数传递给一个通用的计算函数calc,这样就避免了重复代码的编写。

void calc(int(*pf)(int, int))//函数calc调用函数指针来访问对应的函数
{int ret = 0;int x, y;printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}

在main函数中,我们只需要根据用户的选择调用calc函数,并将对应的计算函数(如add、sub、mul、div)的地址传递给它即可。

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;
}

这种使用回调函数的方式,不仅让代码更加简洁,而且提高了代码的可维护性和可扩展性。当我们需要添加新的计算操作时,只需要定义一个新的计算函数,并在main函数中添加对应的分支即可,而不需要修改calc函数。
完整代码:

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 ret = 0;int x = 0;int y = 0;printf("请输入操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}
int main()
{int x = 0;int y = 0;int input = 1;int ret = 0;int(*p[5])(int x, int y) = { 0,add,sub,mul,div };do{printf("*********************\n");printf("1、 add        2、sub \n");printf("3、 mul        4、div \n");printf("0、 eixt              \n");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函数:排序界的瑞士军刀

qsort函数是C语言标准库中的一个非常强大的排序函数,它使用了快速排序算法,可以对任意类型的数据进行排序。它的强大之处在于,它允许用户自定义比较函数,通过回调函数的方式,来决定数据的排序规则。

2.1 使用qsort函数排序整型数据

首先,我们需要定义一个比较函数int_cmp,这个函数接收两个const void类型的参数,分别指向要比较的两个元素。在比较函数中,我们**需要将这两个参数强制转换为int类型,然后比较它们所指向的整数值**。

int int_cmp(const void * p1, const void * p2)
{return (*(int *)p1 - *(int *)p2);
}

然后,在main函数中,我们调用qsort函数,并将数组、数组的大小、每个元素的大小以及比较函数作为参数传递给它。

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;
}

运行程序后,我们可以看到数组被成功排序。
完整代码:

int int_cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);//转换为int* 类型再进行解引用操作
}
int main()
{int arr[] = { 1,3,5,7,9,2,4,6,8,10 };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;
}

在这里插入图片描述

2.2 使用qsort函数排序结构体数组

qsort函数不仅可以对基本数据类型进行排序,还可以对结构体数组进行排序。我们定义一个Stu结构体,包含学生的姓名和年龄。然后,我们定义了两个比较函数cmp_stu_by_age和cmp_stu_by_name,分别按照年龄和姓名对学生进行排序。

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

在test2和test3函数中,我们分别调用qsort函数,并将结构体数组、数组的大小、每个元素的大小以及对应的比较函数作为参数传递给它。

void test2()
{struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}void test3()
{struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}

通过这种方式,我们可以非常灵活地对结构体数组进行排序,而不需要自己编写复杂的排序算法。

三、模拟实现qsort函数:深入理解回调函数与void*

在课件的最后,我们看到了一个模拟实现qsort函数的例子。这个例子不仅让我们更加深入地理解了qsort函数的工作原理,还让我们学习了如何使用回调函数和void*指针。

3.1 void*指针的作用

在C语言中,void指针是一种特殊的指针,它可以指向任意类型的数据。当我们不确定要操作的数据类型时,可以使用void指针。在模拟实现qsort函数时,我们使用void*指针来指向数组的首地址,这样就可以对任意类型的数据进行操作。

3.2 模拟实现qsort函数

在模拟实现qsort函数时,我们使用了冒泡排序算法。首先,我们定义了一个比较函数int_cmp,这个函数与前面的例子中的比较函数相同。然后,我们定义了一个_swap函数,用于交换两个元素的值。在_swap函数中,我们使用了void指针来指向要交换的两个元素,并通过强制类型转换将它们转换为char指针,然后逐字节地交换它们的值。

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;}
}

接下来,我们定义了bubble函数,这个函数实现了冒泡排序算法。在bubble函数中,我们使用了void指针来指向数组的首地址,并通过强制类型转换将它转换为char指针,然后逐个比较数组中的元素,并根据比较函数的结果交换它们的值。

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);}}}
}

最后,在main函数中,我们调用bubble函数,并将整型数组、数组的大小、每个元素的大小以及比较函数作为参数传递给它。

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;
}

通过模拟实现qsort函数,我们不仅加深了对回调函数和void*指针的理解,还学习了如何使用这些知识来解决实际问题。

四、总结

今天,我们深入探讨了指针的一个重要应用——回调函数,以及基于回调函数的经典函数qsort。我们看到了回调函数如何帮助我们简化代码,提高代码的可维护性和可扩展性。我们也看到了qsort函数的强大功能,它可以对任意类型的数据进行排序,并且允许用户自定义排序规则。最后,我们通过模拟实现qsort函数,深入理解了回调函数和void*指针的作用。

希望这篇文章能帮助你更好地理解指针和回调函数,让你在C语言的学习之路上更进一步。如果你对这篇文章感兴趣,欢迎点赞、收藏和评论,你的支持是我继续创作的动力。

http://www.dtcms.com/a/597491.html

相关文章:

  • Rust评测案例:Rust、Java、Python、Go、C++ 实现五大排序算法的执行时间效率比较(基于 OnlineGDB 平台)
  • golang redis 管道
  • go-dongle v1.2.0 发布,新增 SM2 非对称椭圆曲线加密算法支持
  • ⚡️2025-11-11GitHub日榜Top5|Go AI代理开发框架
  • 网站建设g如何做设计网站页面
  • 智能推荐助力数据驱动决策模式提升效率
  • 博客系统 wordpressseo公司怎么样
  • 网站建设与管理 期末软件库资源共享
  • NetSonar网络诊断工具的安装与基本使用
  • 各国网站域名桂林市区有什么好玩的地方景点
  • 陕西省两学一做网站深圳今天新闻头条
  • Git Commend HandBook
  • MFC:微软基础类库的全面解析
  • 郑州网站建设技术托管营销推广方法有哪些
  • Python工具将本地Embedding转换成onnx格式
  • 手机类网站设计赣州新闻综合频道回放
  • 嘉兴网站免费制作判断网站开发语言
  • JSF是什么
  • vscode 设置中文-语言
  • flutter vscode 终端无法使用fvm 版本切换、项目运行
  • 数据结构:计算机高效处理数据的核心基石
  • 网站怎么做能赚钱吗溧水做网站
  • 自己建个电影网站可以吗南海网站建设
  • 使用 C# 提取 Word 表格数据
  • 3DEXPERIENCE DELMIA Role: LTR - Lean Team Player
  • 手机网站seo教程下载wordpress获取文章图片地址
  • 网站海外推广谷歌seo方案开一个网站建设公司需要什么软件
  • 基于 Vue3 封装大华 RTSP 回放视频组件(PlayerControl.js 实现)
  • 微服务架构核心概念速查手册
  • 跨端框架对决:React Native vs Flutter深度对比