用函数指针实现一个简易计算器

51 阅读3分钟

初始代码

下面是一段用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时,程序不会立即报错。而是会继续询问“请输入两个操作数”:

image.png

当输入两个操作数后,程序会经过default后跳出:

image.png

改进思路

为了改进这一问题,我们可以把是输入操作数的代码放入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);

运行结果如下图所示:

image.png

但这样的程序明显太冗长。我们可以观察到,每个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;

		}

输出结果的逻辑也变得合理

image.png

这种改进体现出了函数指针带给程序的灵活性。了解到函数指针的作用远不止这些,我会在今后的学习中不断更新。

修改后的代码

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;
}