初始代码
下面是一段用do while语句和switch语句编写的简单的计算器代码():
void menu()
{
printf("******************************\n");
printf("********1.Add 2.del********\n");
printf("********3.mul 4.div********\n");
printf("********0.exit ********\n");
printf("******************************\n");
}
int add(int x, int y) //包括加减乘除的运算函数
{
return x + y;
}
int del(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);
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
switch (input)
{
case 1:
ret = add(x, y);
printf("%d\n", ret);
break;
case 2:
ret = del(x, y);
printf("%d\n", ret);
break;
case 3:
ret = mul(x, y);
printf("%d\n", ret);
break;
case 4:
ret = div(x, y);
printf("%d\n", ret);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
在程序运行时,我们会发现当输入input超过4时,程序不会立即报错。而是会继续询问“请输入两个操作数”:
当输入两个操作数后,程序会经过default后跳出:
改进思路
为了改进这一问题,我们可以把是输入操作数的代码放入switch语句中,经switch判断input是否合理。
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
getchar(); //清空缓冲区
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 = del(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);
运行结果如下图所示:
但这样的程序明显太冗长。我们可以观察到,每个case中的内容都不尽相同,唯一的不同是应用的运算函数。所以我们可以把case中的内容封装成一个函数,通过传入运算函数的指针,也就是回调函数,完成计算;也解决了代码冗余的问题。
创建新函数
新函数的变量是运算函数的指针
void calc(int(*pf_t)(int, int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = (*pf_t)(x,y);
printf("%d\n", ret);
}
此时,switch中的运算过程变得简洁:
switch (input)
{
case 1:
calc(add);
break;
case 2:
calc(del);
break;
case 3:
calc(mul);
break;
case 4:
calc(div);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
输出结果的逻辑也变得合理
这种改进体现出了函数指针带给程序的灵活性。了解到函数指针的作用远不止这些,我会在今后的学习中不断更新。
修改后的代码
void menu()
{
printf("******************************\n");
printf("********1.Add 2.del********\n");
printf("********3.mul 4.div********\n");
printf("********0.exit ********\n");
printf("******************************\n");
}
int add(int x, int y)
{
return x + y;
}
int del(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 calc(int(*pf_t)(int, int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = (*pf_t)(x,y);
printf("%d\n", ret);
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
getchar();
switch (input)
{
case 1:
calc(add);
break;
case 2:
calc(del);
break;
case 3:
calc(mul);
break;
case 4:
calc(div);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}