学C的第二十六天【指针的进阶(二)】

简介: 6 . 函数指针数组(1). 含义:函数指针数组 是一个数组,是用于存放 函数指针 的数组。 例如:

6 . 函数指针数组

(1). 含义:

函数指针数组 一个数组,是用于存放函数指针数组

       

例如:


7f036be3b1da4170a9e45078acef91a3.png

(2). 实例 -- 计算器(转移表的使用):

计算器加法减法乘法除法 各自定义为一个函数

因为返回int类型数据参数都是 两个整数

所以可以使用 函数指针数组 存储并调用这四个函数


(2.1). 未使用函数指针数组的效果:

自定义函数部分:

image.png

主函数部分:

image.png

对应代码:

//计算器:
#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;
}
//菜单:
void menu()
{
  printf("***************************\n");
  printf("*****  1.add   2.sub  *****\n");
  printf("*****  3.mul   4.div  *****\n");
  printf("*******   0.exit   ********\n");
  printf("***************************\n");
}
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");
      break;
    }
  } while (input);//如果input为0则退出停止循环
  return 0;
}

(2.2). 使用函数指针数组的效果 -- 转移表

           

转移表:通过函数指针数组的下标找到函数地址调用函数实现“跳转”的效果

             

自定义函数部分:

image.png

主函数部分:

减少代码冗余,之后添加算法只需要将添加添加函数加入 函数指针数组再调整些参数即可

image.png

对应代码:

//计算器:
#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;
}
//菜单:
void menu()
{
  printf("***************************\n");
  printf("*****  1.add   2.sub  *****\n");
  printf("*****  3.mul   4.div  *****\n");
  printf("*******   0.exit   ********\n");
  printf("***************************\n");
}
int main()
{
  int input = 0; //菜单选择的数
  int x = 0; //计算的第一个数
  int y = 0; //计算的第二个数
  int ret = 0; //接收函数返回值
  //使用函数指针数组:
  int (*pfArr[5])(int, int) = {NULL, Add, Sub, Mul, Div};
  //“挤一位” 下标:        0     1  2    3    4
  do
  {
    menu();
    //从键盘输入:
    printf("请选择:>");
    scanf("%d", &input);
    if (input >= 1 && input <= 4)
      //输入有效,调用函数进行计算
    {
      //输入函数的两个参数:
      printf("请输入两个操作数:");
      scanf("%d %d", &x, &y);
      //通过 函数指针数组 来调用函数:
      ret = pfArr[input](x, y);
      // pfArr[数组下标](函数参数1,函数参数2)
      //打印计算结果:
      printf("计算结果为:%d\n", ret);
    }
    else if(input == 0) //退出
    {
      printf("退出计算器\n");
    }
    else //输入错误
    {
      printf("选择错误,重新选择\n");
    }
  } while (input);//如果input为0则退出停止循环
  return 0;
}


7 . 指向函数指针数组的指针(了解)

(1). 含义:

本质上还是一个数组指针,只不过这里的数组函数指针数组

例如:

int(*pf)(int, int);  --  函数指针

int (*pfArr[4])(int, int);  --  函数指针数组

int (*(*p) [4]) (int, int) = &pfArr;  --  函数指针数组的指针


8 . 回调函数

(1). 含义:

           

回调函数就是一个通过函数指针调用的函数

如果你把函数的指针(地址)作为参数传递给另一个函数,

         

如果你把函数的指针(地址)作为参数传递给另一个函数

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

             

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

(2). 实例 -- 计算器(回调函数的使用):

编写计算器函数Calc()包含之前写的加减乘除四个函数

假如Calc() 函数通过函数指针调用了加法函数,这时加法函数就是 回调函数 了。                

使用回调函数的效果:

自定义函数部分:

image.png

主函数部分:

image.png

对应代码:

//计算器:
#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;
}
//菜单:
void menu()
{
  printf("***************************\n");
  printf("*****  1.add   2.sub  *****\n");
  printf("*****  3.mul   4.div  *****\n");
  printf("*******   0.exit   ********\n");
  printf("***************************\n");
}
void Calc(int (*pf)(int x, int y)) //使用函数指针作为形参
{
  //在该函数中调用相应函数继续计算
  int x = 0;
  int y = 0;
  int ret = 0;
  printf("请输入两个操作数:");
  scanf("%d %d", &x, &y);
  //通过形参的函数指针来调用函数 -- Calc()函数就是回调函数
  ret = pf(x, y);
  printf("ret = %d\n", ret);
}
int main()
{
  int input = 0; //菜单选择的数
  int x = 0; //计算的第一个数
  int y = 0; //计算的第二个数
  int ret = 0; //接收函数返回值
  do
  {
    menu();
    //从键盘输入:
    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);//如果input为0则退出停止循环
  return 0;
}

 

相关文章
|
5月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
5月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
5月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
5月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
5月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
5月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
48 4
|
5月前
指针进阶(3)
指针进阶(3)
41 1
|
5月前
|
C++
指针进阶(1)
指针进阶(1)
43 1
|
5月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
42 2
|
5月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
49 0