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

佳木斯建设工程交易中心网站在龙港网站哪里做

佳木斯建设工程交易中心网站,在龙港网站哪里做,东莞网站制作哪里好,微信上做任务让你注册彩票网站引言 在C语言中,指针和回调函数是两个非常重要的概念。指针为我们提供了直接操作内存的能力,而回调函数则为我们提供了一种灵活的编程方式,使得我们可以将函数作为参数传递给其他函数,从而实现更加模块化和可复用的代码。本文将深…

引言

在C语言中,指针和回调函数是两个非常重要的概念。指针为我们提供了直接操作内存的能力,而回调函数则为我们提供了一种灵活的编程方式,使得我们可以将函数作为参数传递给其他函数,从而实现更加模块化和可复用的代码。本文将深入探讨指针和回调函数的概念,并通过实际的代码示例来展示它们的应用。

1. 回调函数是什么?


1.1 回调函数的定义


回调函数(Callback Function)是一种通过函数指针调用的函数。简单来说,回调函数是一个在特定事件或条件发生时被调用的函数。回调函数不是由该函数的实现方直接调用,而是通过函数指针传递给另一个函数,由该函数在适当的时机调用。

1.2 回调函数的作用


回调函数的主要作用是解耦代码。通过将函数作为参数传递,我们可以将代码的逻辑分离,使得代码更加模块化和可复用。例如,在一个计算器程序中,我们可以将加法、减法、乘法、除法等操作封装成不同的函数,然后通过回调函数的方式将这些函数传递给一个统一的处理函数,从而避免重复的代码。

1.3 回调函数的示例


让我们通过一个简单的例子来理解回调函数的使用。假设我们有一个计算器程序,用户可以选择不同的操作(加法、减法、乘法、除法),程序会根据用户的选择执行相应的操作。

1.3.1 使用回调函数改造前
#include <stdio.h>int add(int a, int b) {return a + b;
}int sub(int a, int b) {return a - b;
}int mul(int a, int b) {return a * b;
}int div(int a, int b) {return a / b;
}int main() {int x, y;int input = 1;int ret = 0;do {printf("**********\n");printf(" 1:add \n");printf(" 2:sub \n");printf(" 3:mul \n");printf(" 4:div \n");printf(" 0:exit \n");printf("**********\n");printf("请选择:");scanf("%d", &input);switch (input) {case 1:printf("输入操作数:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输入操作数:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输入操作数:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输入操作数:");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;
}



在这个代码中,我们使用了switch语句来根据用户的选择调用不同的函数。虽然这个代码可以正常工作,但是它存在一个问题:每次添加一个新的操作时,我们都需要修改switch语句,这会导致代码的冗余和不易维护。

1.3.2 使用回调函数改造后


为了简化代码,我们可以使用回调函数的方式将不同的操作函数作为参数传递给一个统一的处理函数。这样,当我们添加新的操作时,只需要添加新的函数,而不需要修改switch语句。

#include <stdio.h>int add(int a, int b) {return a + b;
}int sub(int a, int b) {return a - b;
}int mul(int a, int b) {return a * b;
}int div(int a, int b) {return a / b;
}void calculate(int (*func)(int, int)) {int x, y;printf("输入操作数:");scanf("%d %d", &x, &y);int ret = func(x, y);printf("ret = %d\n", ret);
}int main() {int input = 1;do {printf("**********\n");printf(" 1:add \n");printf(" 2:sub \n");printf(" 3:mul \n");printf(" 4:div \n");printf(" 0:exit \n");printf("**********\n");printf("请选择:");scanf("%d", &input);switch (input) {case 1:calculate(add);break;case 2:calculate(sub);break;case 3:calculate(mul);break;case 4:calculate(div);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}


在这个改造后的代码中,我们定义了一个calculate函数,它接受一个函数指针作为参数。这个函数指针指向一个接受两个int参数并返回int的函数。在main函数中,我们根据用户的选择将不同的操作函数传递给calculate函数,从而实现了代码的简化和模块化。

2. qsort使用举例


2.1 qsort函数简介


qsort是C标准库中的一个函数,用于对数组进行排序。它的原型如下:

void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));


base:指向要排序的数组的第一个元素的指针。

nmemb:数组中元素的个数。

size:数组中每个元素的大小(以字节为单位)。

compar:指向比较函数的指针。这个函数用于比较两个元素的大小。

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


让我们通过一个简单的例子来演示如何使用qsort函数对整型数组进行排序。

#include <stdio.h>
#include <stdlib.h>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;
}


在这个例子中,我们定义了一个int_cmp函数,用于比较两个整型数的大小。然后我们使用qsort函数对数组arr进行排序。qsort函数会根据int_cmp函数的返回值来决定元素的顺序。

2.3 使用qsort排序结构数据


qsort函数不仅可以用于排序基本数据类型,还可以用于排序结构体数据。让我们通过一个例子来演示如何使用qsort函数对结构体数组进行排序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct Stu {char name[20];int age;
};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);
}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);for (int i = 0; i < sz; i++) {printf("%s %d\n", s[i].name, s[i].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);for (int i = 0; i < sz; i++) {printf("%s %d\n", s[i].name, s[i].age);}
}int main() {test2();test3();return 0;
}


在这个例子中,我们定义了一个Stu结构体,包含学生的姓名和年龄。我们定义了两个比较函数cmp_stu_by_age和cmp_stu_by_name,分别用于按照年龄和姓名对学生进行排序。然后我们使用qsort函数对结构体数组进行排序,并输出排序后的结果。

3. qsort函数的模拟实现

3.1 冒泡排序简介


冒泡排序是一种简单的排序算法。它重复地遍历要排序的数组,比较相邻的两个元素,如果它们的顺序错误就交换它们。遍历数组的工作会重复进行,直到没有需要交换的元素为止。

3.2 使用回调函数模拟实现qsort


我们可以使用冒泡排序的思想来模拟实现qsort函数。为了支持不同类型的数组,我们需要使用void *指针和回调函数。

#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函数,它接受一个void *指针作为数组的基地址,数组的元素个数,每个元素的大小,以及一个比较函数。bubble函数使用冒泡排序算法对数组进行排序。为了支持不同类型的数组,我们使用void *指针和_swap函数来交换元素。

4. 总结


通过本文的学习,我们深入理解了指针和回调函数的概念,并通过实际的代码示例展示了它们的应用。回调函数为我们提供了一种灵活的编程方式,使得我们可以将函数作为参数传递给其他函数,从而实现更加模块化和可复用的代码。qsort函数是C标准库中的一个强大的排序函数,它通过回调函数的方式支持对不同类型的数据进行排序。我们还通过模拟实现qsort函数,进一步加深了对指针和回调函数的理解。

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

相关文章:

  • 工具收集 - ContextMenuManager 右键管理
  • 【软件设计师中级】计算机组成与结构(六):系统性能评测与可靠性基础 - 衡量计算机的“尺子“与“保险“
  • 当游戏NPC有了“灵魂”,网易伏羲解码游戏智能交互场景新实践
  • 热更新:移动应用的“空中加油”技术-详解什么是热更新?-优雅草卓伊凡卓伊凡的挑战
  • 【GD32】软、硬件I2C对比
  • YMODEM 协议介绍以及通信流程分析和Lua语言实现
  • 视频直播点播平台EasyDSS如何助力餐饮行业实现“明厨亮灶”直播?
  • 通过网站做外贸广告公司有哪些
  • 关于网站建设的好处seo搜索优化邵阳
  • 百家号淄博圻谷网站建设做网站页面一般用什么软件
  • CCF-GESP 等级考试 2024年3月认证C++三级真题解析
  • 本地部署 DeepSeek 私有助手:从零到上线的完整方案
  • CTF攻防世界WEB精选基础入门:weak_auth
  • 石家庄网站建设蓝点公路建设网站
  • 免费制作网页的网站企业app定制开发公司
  • 若依框架Springboot开发开放接口供他人调用
  • 在Centos上安装Python指定版本
  • 体育赛事 APP 开发:从技术到体验的全方位突破
  • 【阿里云】记一次oss攻击
  • MySQL高效备份实战指南
  • OpenBLT移植教程
  • 怎样做站长建网站荥阳市建设局网站
  • 虚拟仿真实训:打破时空界限,重塑未来技能,引领教育新变革
  • MySQL字符集配置全攻略:告别乱码
  • 「机器学习笔记10」贝叶斯学习——从逆向思维到简化现实的强大武器
  • 01-Python简介与环境搭建-教程
  • 高端设计网站都有哪些微信公众号推广赚钱
  • 数字化转型:概念性名词浅谈(第七十二讲)
  • 济南网站建设泉诺上海手机网站哪家最好
  • 鸿蒙Next文件上传下载:全场景高效数据传输方案