回调函数的应用

回调函数的应用

1. 回调函数 — 用函数指针重构计算器

1.1 什么是回调函数

回调函数:把一个函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这个函数是回调函数。

换句话说:你不是直接调用函数,而是把函数指针传进去另一个函数,让别人在合适的时机帮你调用。

#include<stdio.h>voidprint(){printf("hehe\n");}voidtest(void(*p)())//2)接收print函数的地址{p();//3)指向的是print函数}intmain(){test(print);//1)把print函数地址传参return0;}

输出:hehe

1.2 传统写法的问题

之前我们写了一个简单的计算器,用switch-case调用对应的加减乘除函数:

// 运算函数intadd(inta,intb){returna+b;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}intdiv(inta,intb){returna/b;}intmain(){intx,y;intinput=1;intret=0;do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf("*************************\n");printf("请选择:");scanf("%d",&input);switch(input){case1:printf("请输入两个操作数:");scanf("%d %d",&x,&y);ret=add(x,y);printf("ret = %d\n",ret);break;case2:printf("请输入两个操作数:");scanf("%d %d",&x,&y);ret=sub(x,y);printf("ret = %d\n",ret);break;case3:printf("请输入两个操作数:");scanf("%d %d",&x,&y);ret=mul(x,y);printf("ret = %d\n",ret);break;case4:printf("请输入两个操作数:");scanf("%d %d",&x,&y);ret=div(x,y);printf("ret = %d\n",ret);break;case0:printf("退出程序\n");break;default:printf("输入错误\n");break;}}while(input);return0;}

痛点:每个case分支里的操作几乎一模一样(提示输入 → 读取操作数 → 调用函数 → 打印结果),大量冗余代码。

1.3 回调函数改造 — 抽离公共逻辑

把"提示输入 + 调用函数 + 输出结果"这个通用流程抽成一个calc函数:

#include<stdio.h>intadd(inta,intb){returna+b;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}intdiv(inta,intb){returna/b;}// 回调函数的核心:用函数指针作为参数//calc函数相当于一个中转站,我只需要给他一个函数地址,就能在calc函数调用这个函数,避免重复代码voidcalc(int(*pf)(int,int))//假设接收add函数地址{intret=0;intx,y;printf("请输入两个操作数:");scanf("%d %d",&x,&y);ret=pf(x,y);//pf指的是add函数,完成加法printf("ret = %d\n",ret);}intmain(){intinput=1;do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf("*************************\n");printf("请选择:");scanf("%d",&input);switch(input){case1:calc(add);// 把 add 传进去 → add 就是回调函数break;case2:calc(sub);// sub 是回调函数break;case3:calc(mul);// mul 是回调函数break;case4:calc(div);// div 是回调函数break;case0:printf("退出程序\n");break;default:printf("输入错误\n");break;}}while(input);return0;}

对比总结

维度传统写法回调函数写法
重复代码每个 case 都写一遍"提示→输入→调用→输出"公共逻辑抽离到calc
可维护性改输出格式要改 4 处只需改calc一处
核心思想直接调用把函数当参数传

核心理解calc接收一个int(*pf)(int, int)类型的函数指针,通过pf(x, y)来回调。这样add/sub/mul/div都成了回调函数。