如果你对C语言编程充满兴趣,那么构建一个简易计算器可能是一个很好的练习机会。在本文中,我们将探讨如何使用C语言实现一个基本的计算器,并分享我们在这个过程中遇到的挑战及其解决方案。
版本1.0
如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void menu()
{
printf("########################\n");
printf("#####1.Add 2.Sub ######\n");
printf("#####3.Mul 4.Div ######\n");
printf("########################\n");
}
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;
}
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);
return 0;
}
对于do…while的框架,我相信读者都已经比较熟悉了,如果还不熟悉的,可以去看看我之前的一篇关于
猜数字游戏的实现
我们放在vs2022中运行起来看一下效果:
这样一个只有加减乘除功能的简易计算器我们就实现了。这时我们发现,如果未来想要扩充这个计算器的功能,比如增加%,<< , >>, & , | , ^ 等功能,应该如何修正代码呢?
- 首先从当前的代码框架来看,我们需要修改菜单menu,添加必要的选项。
- 其次再switch中增加case5,case6…这样会导致switch过于”庞大“,逻辑不够清晰。
导致switch庞大的主要原因在于,每一个case语句中都有大量重复的语句。
- 基于此,我们将有两种优化方案,第二种涉及到回调函数的概念。请接着往下看:
版本2.0
思路:将switch语句替换成if…elseif语句
如下:(仅对主函数main修改即可)
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("请输入要计算的数字:");
scanf("%d%d",&x,&y);
ret = Add(x, y); // 此处还需要进一步处理!!!
printf("%d\n ",ret);
}
else if (input == 0)
{
printf("退出\n");
}
else
{
printf("重新输入\n");
}
} while (input);
return 0;
}
这时我们发现,if语句中只能实现一个函数功能呀,怎么解决这个问题呢?我们能否**根据输入的input的值,调用不同的函数呢?**一个最容易想到的方法是,在if语句中套用选择语句来判断(即双层if),但是这样又时代码逻辑变得不清晰起来了,这显然违背了我们的初衷。我们可以借助函数指针数组来实现这一需求,请看:
啥?什么是函数指针数组?有的小伙伴可能不清楚,那现在让我来简单画个图解释一下把:
这下应该就理清楚它们之间的关系了把。
版本2.0完整代码如下:
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
int (*p[5])(int, int)= {0,Add,Sub,Mul,Div};
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("请输入要计算的数字:");
scanf("%d%d",&x,&y);
ret = p[input](x, y);
printf("%d\n ",ret);
}
else if (input == 0)
{
printf("退出\n");
}
else
{
printf("重新输入\n");
}
} while (input);
return 0;
}
版本3.0
思路:我们依旧延用switch语句,将每一个case中的语句封装成一个函数
如下:
void Calc( int(* (*pf)[5])(int, int), int input)
{
int x = 0;
int y = 0;
int ret = 0;
printf("请输入要计算的数字:");
scanf("%d%d", &x, &y);
ret = (*pf)[input](x, y);
printf("%d\n ", ret);
}
int main()
{
int input = 0;
int (*pfarr[5])(int, int) = { 0,Add,Sub,Mul,Div };
/*int x = 0;
int y = 0;
int ret = 0;*/
do
{
menu();
printf("请输入你的选择:");
scanf("%d",&input);
switch (pfarr,input)
{
case 1:
Calc(pfarr,input);
break;
case 2:
Calc(pfarr,input);
break;
case 3:
Calc(pfarr,input);
break;
case 4:
Calc(pfarr,input);
break;
case 0:
printf("退出\n");
break;
default:
printf("输入错误,重新输入\n");
break;
}
} while (input);
return 0;
}
这样子,switch语句就不会因为增加功能而变得快速庞大了!
对于calc的第一个形参,有必要画图理解一下:
同样是3.0的思想,我们还可以在传参时稍作修改,得到下面这段代码:
void Calc(int (*pf)(int,int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("请输入要计算的数字:");
scanf("%d%d", &x, &y);
ret = pf(x, y);
printf("%d\n ", ret);
}
int main()
{
int input = 0;
int (*pfarr[5])(int, int) = { 0,Add,Sub,Mul,Div };
/*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);
通过本文的学习,我们深入了解了用C语言实现简易计算器的过程,并探讨了在这个过程中遇到的一些常见问题及其解决方案。
希望本文能够对你在C语言编程中遇到类似问题时提供一些帮助和启发。如果你对本文中提到的任何主题有兴趣或疑问,不妨深入研究,相信你会有更多收获。