详解函数指针(●‘◡‘●)☞

news/2024/10/18 12:23:49/

本文紧接于http://t.csdn.cn/78wbF 这篇

一.函数指针数组\ ( >O< ) /

1.书写形式:由函数指针内部*+变量名==>*+变量名+[n];

2.使用:函数指针数组的用途:转移表

例如:模拟计算器:

#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 2:sub        \n");printf("      3:mul 4:div        \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;
}

该代码有缺陷在于case里面会写很多个重复代码当使用函数指针数组则会减少该不足将主函数修改:

int main()
{int x, y;int input = 1;int ret = 0;int (*mid[5])(int*, int*) = {add,sub,mul,div};do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf("*************************\n");printf("请选择:");scanf("%d", &input);switch (input){case 1:case 2:case 3:case 4:printf("输入操作数:");scanf("%d %d", &x, &y);ret = mid[input-1](x, y);///ret = (*mid[input - 1])(x,y);这两种使用方法都可以。printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);    return 0;
}

3.指向函数指针数组的指针

(1).书写形式:(以例说明)int (*(*p)[10])(int *,int *)=&arr;

拆分开来就是:最外层是函数指针==>内部的指针部分搞成数组指针===>再把数组指针进化成数组指针就行,一步一步来

二.回调函数。((o(^_ ^)o))

    • 书写形式:(以例说明)void(数据类型) part(函数名)(int (*pa)(int,int))里面是函数指针

    • 回调函数的意义(定义):

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个

函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数

的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进

行响应

3.回调函数的使用☞模拟qsort函数

(1).介绍qsort函数:用于比较1个数组的元素之间的大小

//void qsort(void* base, //待排序的数组的起始地址
//      size_t num,    //元素个数
//     size_t width,  //一个元素的大小
//      int (*cmp)(const void* e1, const void* e2)//两个元素的比较函数
//         );
#include<stdio.h>
#include<string.h>
struct Str { char a[10]; int b; };
struct Str s[3] = { {"zhangsan",20}, {"lisi", 50}, {"wangwu", 33} };
int  part(const void*a ,const void*b)//比较函数形式固定
{return strcmp(((struct Str*)a)->a, ((struct Str*)b)->a);}
int main()
{   int a = sizeof(s) / sizeof(s[0]);qsort(s,a,sizeof(s[0]),part);//比较字符串return 0;
}

void* 是指空数据类型,因为不知到要操作的是哪种数据类型。

qsort默认是升序排列的

注意自己写的函数开始是void*要转化成要求的类型(important)

(2).实现模拟qsort函数(注意点和解释放在代码注释中)

#include <stdio.h>
#include <string.h>//定义结构体
typedef struct student
{char name[20];int score;}student;
//自定义比较函数  使用strcmp函数比较字符串大小
int  compare_student(const void* r1, const void* r2)
{return strcmp((*((student**)r1))->name, (*((student**)r2))->name);
}
//交换函数,使用char*指针一个字节一个字节交换
void swap(char* r1, char* r2, size_t width)
{size_t  i = 0;for (i = 0; i < width; i++){char temp = 0;temp = *r1;*r1 = *r2;*r2 = temp;r1++;r2++;}
}
//自定义qsort函数的实现
void My_bubble_qsort(void* base, size_t num, size_t width, int (*compare)(const void* r1, const void* r2))
{size_t i = 0;size_t j = 0;for (i = 0; i < num - 1; i++){for (j = 0; j < num - 1 - i; j++){if (compare((char*)base + j * width, (char*)base + (j + 1) * width) > 0){swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}
int main()
{ student wangwu = { "wangwu",75 };student lisi = { "lisi",94 };student zhangsan = { "zhangsan",60 };student* arr_student[3] = { &wangwu,&lisi,&zhangsan };//定义结构体指针数组int i = 0;printf("排序前:\n");for (i = 0; i < 3; i++){  printf("%s,%d\n", arr_student[i]->name, arr_student[i]->score); }My_bubble_qsort(arr_student, sizeof(arr_student) / sizeof(arr_student[0]), sizeof(arr_student[0]), compare_student);printf("\n排序后:\n");for (i = 0; i < 3; i++){  printf("%s,%d\n", arr_student[i]->name, arr_student[i]->score); }return 0;
}

好了这就是今天的内容了,谢谢大家观看,希望大家多多指出不足。最后觉得小编写的还凑合的来个三连呀!


http://www.ppmy.cn/news/11190.html

相关文章

Visual studio C++桌面应用程序添加外部文件引用

C桌面应用程序添加外部文件引用 前言 之前对C的开发接触很少&#xff0c;本章节记录一下Visual studio开发C桌面应用程序是如何引入外部文件 ★提高阅读体验★ &#x1f449; ♠一级标题 &#x1f448; &#x1f449; ♥二级标题 &#x1f448; &#x1f449; ♥ 三级标…

【数据结构】队列详解

前言 前面我们学习了一种数据结构&#xff1a;栈&#xff0c;栈是一种只允许在一端尽进行插入删除的数据结构&#xff0c;而今天我们将学习另一种数据结构&#xff1a;队列&#xff0c;队列是一种支持在一端进行插入&#xff0c;在另一端进行删除的数据结构。 一、队列的介绍…

Esp8266学习2. Node-mcu基于Arduino IDE2.0.3设置及基本操作

Esp8266学习2. Node-mcu基于Arduino IDE2.0.3设置及基本操作一、准备工作1. 下载Aruino IDE2. 准备Node-MCU开发板二、设置1. 填写开发板网址2. 开发板设置3. 连接开发板三、测试点亮LED程序1. 加载示例程序2. 编译运行四、一些基本网络操作1. 连接到热点2. 使用WiFiClient3. 创…

mysql的binlog学习记录

文章目录什么是binlogbinlog格式StatementRowMixedbinlog使用什么是binlog MySQL Binary Log也就是常说的bin-log, ,是mysql执行改动产生的二进制日志文件。简单的来说&#xff0c;binlog日志用于记录所有更新了数据或者以及潜在更新了数据&#xff08;例如&#xff0c;没有匹…

webviz安装,docker安装可正常使用与Foxglove Studio

Foxglove Studio Foxglove Studio与webviz使用起来非常类似 去可以直接使用web也可以下载安装包 Foxglove Studio不提供源码 安装包下载地

初级开发者福音:手把手教你实现数字滚动效果~

文章目录一、前言二、背景知识三、实现方案Step 1&#xff1a;分析需求Step 2&#xff1a;实现单个数字的滚动效果Step 3&#xff1a;组件接口设计Step 4&#xff1a;完善组件一、前言 前端数字滚动显示的场景很多&#xff0c;比如抽奖的时候&#xff0c;营造一种马上公布中奖…

Linux操作系统--文件管理(保姆级教程)

文件系统类型的含义 文件系统类型式指文件在存储介质上存放及存储的组织方法和数据结构。 Linux采用虚拟文件系统技术&#xff08;virtual file system)-VFS 一个世纪的文件系统想要被Linux支持&#xff0c;就必须提供一个符合VFS标准的接口&#xff0c;才能与VFS协同工作&am…

数学建模-回归分析(Stata)

注意&#xff1a;代码文件仅供参考&#xff0c;一定不要直接用于自己的数模论文中国赛对于论文的查重要求非常严格&#xff0c;代码雷同也算作抄袭 如何修改代码避免查重的方法&#xff1a;https://www.bilibili.com/video/av59423231 //清风数学建模 一、基础知识 1.简介 …