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

正规品牌网站设计图片微信开发者工具文档

正规品牌网站设计图片,微信开发者工具文档,城乡建设厅建设网站,下载类网站 建设方案目录 一、函数指针数组 1.1函数指针数组写法 1.2函数指针用途 二、指向函数指针数组的指针 2.1概念 三、回调函数 3.1用法 3.2qsort排序 总结 前言 我们接着上一篇的函数指针往下学习。 一、函数指针数组 1.1函数指针数组写法 我们都知道指针数组,里面可以…

目录

一、函数指针数组

1.1函数指针数组写法

 1.2函数指针用途

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

2.1概念

三、回调函数

3.1用法

3.2qsort排序

总结

前言

我们接着上一篇的函数指针往下学习。


一、函数指针数组

1.1函数指针数组写法

我们都知道指针数组,里面可以放字符指针,或者整形指针,例如:

char* arr[6];//字符指针数组int* arr[6];//整形指针数组

那么我们就可以想一想函数指针数组是否可以呢? 当然可以,写函数指针数组,需要在函数指针这个基础上进行改造:

int(*str)(const char*) = &my_strlen;int(*str[5])(const char*);

第一行 是一个函数指针,我们将my_strlen这个函数的地址赋予给它,当我们想要把前面的函数指针改成函数指针就可以在里面加上数组元素个数,其实就是在这个函数指针后面加上一个方括号再确定元素个数就可以了。

int(*)(const char*);

 我们去掉数组名和元素,剩下的就是一个函数指针,所以就是这个数组里面存放的就是这个函数的地址。我们就可以赋值,传入地址:

int(*str[5])(const char*)={ &my_strlen,.....}

 1.2函数指针用途

我们可以用一个简单的可以实现整数加减乘除的计算器。

先实现一个简单的菜单和基本逻辑的实现,重点实际是函数的编写和函数的调用(VS2022):

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void menu()
{printf("********************************************\n");printf("*********** 1.add         2.sub  ***********\n");printf("***********                      ***********\n");printf("*********** 3.mul         4.div  ***********\n");printf("***********       0.exit         ***********\n");printf("********************************************\n");}int main()
{int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:break;case 2:break;case 3:break;case 4:break;case 0:printf("退出计算器\n");break;default:printf("选择错误\n");}	} while (input);return 0;
}

这里规定的是选择1,2,3,4,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;
}

接下来实现调用:

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");}	} while (input);return 0;
}

这样一个简单的计算器就写好了,我们可以运行并且测试。但这只是这几种简单的运算,当我们如果想要拓展其它的算数方法,那么函数要写,switch里面的case也要写,那么里面就会变得非常长,这时候我们就可以优化一下。

我们知道函数的调用参数和返回值都一样,所以可以写上函数指针数组,存放函数的地址,这种叫做转移表

int (*pf[5])(int,int) = { NULL,Add,Sub,Mul,Div };

我们这里用上一个名字为pf的函数指针数组来接受这些函数的地址,每一个函数对应的下标就是菜单上规定的数字。

这时候我们就不需要用switch语句了,我们想要选择几就访问下标为几的位置。这时候我们改一下主函数:

int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;do{menu();printf("请选择:>");scanf("%d", &input);if (input == 0){printf("退出计算器\n");break;}else if (input >= 1 && input <= 4){printf("请输入两个数:>");scanf("%d %d", &x, &y);ret = pf[input](x, y);printf("结果是: %d\n", ret);}else{printf("选择错误\n");}} while (input);return 0;
}

这样未来我们想要添加功能,就只需要加上新函数的编写,剩下的只需要改一改限制条件就可以,其他都不用改动,大大改善了switch的代码量。但这个上述代码只适用两个整数之间的操作(双目操作符的运算)。

函数指针数组在动态调用函数、简化代码逻辑、扩展性和灵活性以及实现回调函数等方面具有很高的实用价值,是一种常用的编程技术。

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

2.1概念

int(*pf[5])(int,int);
ppf=&pf;

 如上述代码,pf是一个存放函数指针的一个五个元素的数组,而ppf指向这个数组,所以就是指向函数指针数组的指针。

int(*(*ppf)[5])(int,int);
int(*)(int,int);

(*ppf)代表是一个指针,(*ppf)[5]代表指向的是一个五个元素的数组,而int(*)(int,int)代表是一个函数指针,所以数组里存放的是函数指针,这个数组也就是一个函数指针数组,所以ppf就是一个指向函数指针数组的指针;

三、回调函数

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

也就是用函数指针调用函数。

3.1用法

之前的switch,,,case语句是这样的:

            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;

我们可以看到很多都是一样的代码,那可不可以把一样的代码放在一个函数里面调用呢:

void func()
{printf("请输入两个数:>");scanf("%d %d", &x, &y);ret=Add(x, y);printf("结果是: %d\n", ret);
}case 1:func();break;
case 2:func();break;

这里就有一个问题,这里两次case都是计算加法,这时候我们就可以当我们case 1 的时候,将加法的地址传到函数中,当case 2 的时候,把减法的地址传过去:

void func(int(*p)(int,int))
{printf("请输入两个数:>");scanf("%d %d", &x, &y);ret=p(x, y);printf("结果是: %d\n", ret);
}case 1:func(Add);break;
case 2:func(Sub);break;

把函数的参数写成一个函数指针就可以,调用的时候就用指针名和传参就可以实现了。这里通过p来调用这些函数就叫做回调函数。

qsort函数就是一个典型的例子。

3.2qsort排序

这里先介绍一下这个函数:

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

这里传入的参数分别是是要排序的目标(起始位置),排序的个数,单个的大小,还有比较函数。这里的比较函数是需要自己进行编写的,并且比较函数是返回的一个数。

int compareMyType (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;
}

 这里是官方给出的代码,实际我们只需要返回一个值就可以。

下面是通过qsort函数来排序整数数组还有排序结构体:

给定一个整数数组,进行排序

//基于快速排序的stdlib库里的qsort进行排序#include<stdio.h>
#include<stdlib.h>int comper(const void*e1, const void*e2)
{return *(int*)e1 - *(int*)e2;
}int main()
{int arr[5] = { 4,6,2,3,1 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), comper);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

基于结构体按照年龄和名字来进行排序: 

//结构体排序
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Stu
{char name[20];int age;
};
//年龄排序
int comper(const void* e1, const void* e2)
{return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}//按照名字来排序
int comper1(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name) ;//按照字典序进行排序
}void test2()
{struct Stu s[3] = { {"zhangsan",30},{"lisi",50},{"wanghu",33} };int sz = sizeof(s) / sizeof(s[0]);qsort(s,sz,sizeof(s[0]),comper1);for (int i = 0; i < sz; i++){printf("%s %d\n", s[i].name, s[i].age);}
}int main()
{test2();return 0;
}


总结

这里进行了函数指针数组的用法和写法,回调函数sqsort等的知识

http://www.yayakq.cn/news/868655/

相关文章:

  • 中国建设银行网站无法访问校园网站开发的意义
  • 甘肃住房城乡建设厅网站首页支付宝网站开发流程
  • 广东平台网站建设哪家好做网站用的符号
  • 专业网站建设桂林亿星网络科技公司
  • 响应式中文网站欣赏最专业网站建设公
  • 怎么在网上接网站建设大企业网站建设方案
  • 漳州公司建设网站自己做的网站怎么赚钱吗
  • 南京网站建设方案wordpress验证码注册
  • 电子商务网站建设与管理课件中卫网站建设哪家好
  • 新风向网站建设网站广告图怎么做
  • 上线了做网站怎么样济南网站建设认可搜点网络
  • 做旅游网站宣传高校 网站建设实施方案
  • lnmp下的wordpress优化网站的步骤
  • 公司企业网站设计尺寸怎么做自己的一个网站
  • 南京网站排名外包怎么把svg做网站背景
  • 各大网站头条深圳最简单的网站建设
  • 网站建设淘宝详情页如何建学校网站
  • 服装网站建设内容手机网站建设费用价格
  • 永久免费的自建网站做名片最好的网站是哪个
  • 果园网站建设青州网站设计
  • 都安做网站怀柔高端网站建设
  • apache搭建网站北京互联网公司待遇排名
  • 无锡网站优化公司女式包包网站建设策划书
  • 做货代的有哪些网站怎样设计公司logo
  • 网站主机免备案吗wordpress 菜单消失
  • 专业网站seo优化公司中国菲律宾男篮直播
  • 广州营销型网站建设培训公司网站备案
  • 音乐网站怎么做无线增值业务哈尔滨建站的网站
  • 兰州网站开发在哪里wordpress 很差
  • 做vi 设计国外网站深圳哪个区最繁华