指针部分实现计算器

文章介绍了如何使用C语言中的函数指针和回调函数实现一个四则运算计算器,并讨论了如何通过回调简化代码结构。随后扩展功能至支持小数运算和指定小数位数,同时分析了原始版本的优缺点和改进过程。
摘要由CSDN通过智能技术生成

引言

课上所学计算器

本节主要回忆课上所讲的内容,整理思路。首先实现最简单的四则运算函数Add Sub Div Mul ,后搭建do while 加 switch框架,再通过转移表或者回调函数进行函数的调用。同时为了简化代码,后在switch语句的各个case部分使用一个封装函数,实现用户输入操作操作数的功能。

  • 普通计算器

    ​
    #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;
    }
    
    
    
    
    void menu()
    {
    	printf("#####################\n");
    	printf("###  1 sum 2 sub  ###\n");
    	printf("###  3 mul 4 div  ###\n");
    	printf("###    0 exit     ###\n");
    	printf("#####################\n");
    
    }
    
    
    int main()
    {
    	int input = 0;
    	do
    	{
    		menu();
    		printf("请选择:>");
    		scanf("%d", &input);
            int x=0,y=0,ret=0;
    		switch (input)
    		{
    		case 1:
    	        printf("请输入两个操作数:>");
    	        scanf("%d%*c%d", &x, &y);
    	        int ret = Add(x, y);
    	        printf("结果为%d\n", ret);
    			break;
    		case 2:
    			printf("请输入两个操作数:>");
    	        scanf("%d%*c%d", &x, &y);
    	        int ret = Sub(x, y);
    	        printf("结果为%d\n", ret);
    			break;
    		case 3:
    			printf("请输入两个操作数:>");
    	        scanf("%d%*c%d", &x, &y);
    	        int ret = Mul(x, y);
    	        printf("结果为%d\n", ret);;
    			break;
    		case 4:
    			printf("请输入两个操作数:>");
    	        scanf("%d%*c%d", &x, &y);
    	        int ret = Div(x, y);
    	        printf("结果为%d\n", ret);
    			break;
    		case:
    			printf("计算结束\n");
    			break;
    		default:
    			printf("您的输入有误,请重新输入\n");
    			break;
    		}
    
    
    
    	} while (input);
    
    	return 0;
    }
    
    ​

    可以看到,在case后面的代码及其冗余,从而改进使用回调函数结合函数指针如下。

  • 使用回调将函数实现

//回调函数
void Fuc(int(*calcul)(int a, int b))
{
	int x = 0;
	int y = 0;
	printf("请输入两个操作数:>");
	scanf("%d%*c%d", &x, &y);
	int ret = calcul(x, y);
	printf("结果为%d\n", ret);
}
do
{
	menu();
	printf("请选择:>");
	scanf("%d", &input);
	switch (input)
	{
	case 1:
		Fuc(Add);
		break;
	case 2:
		Fuc(Sub);
		break;
	case 3:
		Fuc(Mul);
		break;
	case 4:
		Fuc(Div);
		break;
	case:
		printf("计算结束\n");
		break;
	default:
		printf("您的输入有误,请重新输入\n");
		break;
	}

} while (input);

在使用回调函数后代码do while部分得到了简化。当一个函数的参数是另一个函数的地址,并且在特定的场景通过指针调用该函数时,这个被调用的函数叫回调函数,回调函数不是由该函数的实现直接调用,而是由另外的一方调用,用于该事件或条件进行相应。

  • 使用转移表实现

(为重点突出,只展示封装函数),该处也可以把函数指针数组设置为5个元素,将第一个元素设为0,从而可以方便主函数的相关书写。

小结

简单回忆了上课所学,并实践回调函数以及转移表的相关代码。

课后改进与实践

本节基于上课所学,实践了一种可以进行带小数的乘除,并可以指定保留几位小数位的计算器

代码如下

基于回调函数

//回调函数实现计算器(可实现小数运算,以及指定输出的小数位)

#include<stdio.h>

float Add(int a, int b,int c)
{
	return a + b;
}
float Sub(int a, int b,int c)
{
	return a - b;
}
float Div(int a, int b, int c)
{
	if (c == 0)
		return a / b;
	else
		return (a * 1.0) / b;
}
float Mul(int a, int b,int c)
{
	if (c == 0)
		return a * b;
	else
		return (a * 1.0) * b;
}

void calcu(float(* fuc)(int a, int b, int c))
{
	int decimal = 0;
	int a=0, b=0;
	printf("需要保留几位小数:>");
	scanf("%d", &decimal);
	printf("请输入操作数:>");
	scanf("%d%*c%d", &a, &b);

	float ret = fuc(a, b, decimal);
	printf("结果为%.*f\n", decimal, ret);

}


void menu()
{
	printf("**********************\n");
	printf("*** 1-Add  2-Sub   ***\n");
	printf("*** 3-Div  4-Mul   ***\n");
	printf("******  0-exit  ******\n");
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			calcu(Add);
			break;
		case 2:
			calcu(Sub);
			break;
		case 3:
			calcu(Div);
			break;
		case 4:
			calcu(Mul);
			break;
		case 0:
			printf("计算结束\n");
			break;

		default:
			printf("您的输入有误,请重新输入\n");
			break;
		}

	} while (input);


	return 0;
}

基于回调函数改进了封装函数,增加了指定小数位,通过printf函数占位符的相关知识限制输出的小数位。对加减法函数,改变了其返回类型,以及增设int c 变量用以匹配回调函数参数的指针。同时当decimal取零时,乘除函数也通过加设分支进行解决。

基于转移表

void calcul(int input)
{
	int decimal = 0;
	int a = 0, b = 0;
	//转移表
	double(*fuc[5])(int a, int b, int c) = { 0,Add ,Sub ,Div,Mul };
	printf("请输入要保留的小数位:>");
	scanf("%d", & decimal);
	printf("请输入两个操作数:>");
	scanf("%d%*c%d", &a, &b);
	double ret = (*fuc[input])(a, b, decimal);
	printf("答案为%*.f\n", decimal, ret);


}

总结

缺点,反思

  • 只能进行整数运算,不能进行小数与小数,或者小数和整数的运算
  • 不能根据要求自动保留小数位
  • 不能实现连续计算
  • 不能进行特殊数学计算
  • 不能对每个环节的输入进行查错并反馈,该问题的具体尝试过程如下

如:

无法达到想要的效果,即在输入wps时判断有误并重新运行。后尝试更改else if 和else的顺序,并验证能正常工作后,在第二次运行计算时进行非法输入如图:

可见,非法输入后出现死循环,未达到目标。而后在do while中加input = 0;进行尝试如图:

可见,未进行死循环但,仍未能达到预期结果。后将位于do while循环中input赋值为一个难以出现的值,进行部分屏蔽如图:

可见,部分达到期望效果,后欲改变else代码块中的break为continue,同样出现死循环的情况。

可能通过后续对库函数的学习,以及对C编程学习的深入能有机会解决该问题。

幸甚至哉,歌以咏志

  • 65
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值