概要:主要以c语言为例对数据结构中写一个简易的计算器(计算整数间加减乘除括号运算)的算法进行大致讲述,细说如何去实现符号优先级的比较的函数实现。
注:由于编辑器缘故,本文内我以小写x代替了*作为乘号
栈的相关内容:https://blog.csdn.net/weixin_44579240/article/details/89255974

简易计算器

  • 整体思想:首先我们需要知道,这个算法的核心问题在于计算顺序的问题,如何让我们的程序去按照正确的顺序去计算一个算术表达式。下面举个例子 【2x2+3x(2+4)-6】 这个式子对于我们来说,计算起来不难,先计算括号内的2+4=6。然后计算最左边的2x2=4。接着是3x6=18。然后4+18=22。最后22-6=16。就算完了,这是因为我们知道括号内优先,然后是乘除,接着是加减。同等级符号计算按照从左到右的顺序。所以我们会选择性的去按照既定的顺序来读取,算术,代换,再算。但计算机是不能选择性的读取的。它遵循这从左向右的读取顺序,这时候我们需要用到栈来存储暂时不用的数据与符号以及它们的顺序。等到轮到这些运算符的时候,再将它们从栈中按顺序提取出来进行运算。
  • 运算顺序思想:首先咱来看看符号运算顺序,即括号优先,其次乘除,再者加减,同级从左向右。那么既然运算的顺序和符号息息相关,我们便需要从这些符号下手来整合出一个决定运算顺序的函数了,我们先以计算机角度来阅读下上面的式子,一步步捋出应该怎么去计算,再说使用代码实现。
  • 从左向右阅读运算:还是上面那个例子【2x2+3x(2+4)-6】 ,从左向右读取,我们先读到一个数字‘2’,然后是运算符‘x’,接着是数字‘2’,这时已经有俩个数字与一个夹在中间的运算符了,那么问题来了我们该不该运算呢?显然是无法明确知道的,因为我们需要确定这个乘号直接相接的前后运算符有没有比它更优先的存在,如果有那么它所邻接的数字应该优先参与这个优先级更高的符号的运算。好,现在我们回到式子上,我们现在所读取到的乘号它之前没有运算符,所以我们需要知道它之后这个紧接的运算符与它谁的优先级高。那么继续向后读取,读到‘+’,加号优先级比乘号小。也就是说,乘号所紧接的前后符号,优先级均低于这个乘号,那么它紧接的数字就优先与它进行运算了,即我们可以计算2x2了。有人会问了,之前我们计算的时候不是最优先计算的括号内的2+4吗,为什么到这里先算了2x2,这个顺序其实并不影响我们的计算结果,因为按照之前的运算,我们算完括号内的内容后,以结果去代替原括号,加入原计算式内进行计算,所以在从左向右阅读运算中,我们只需要在读取到括号时,将其中内容作为一个完整的运算式,最优先算出其中的值,然后取代其位置即可。
  • 符号运算顺序规则 ok,以上就是我们如何在从左向右阅读顺序之下去判断一个符号该不该运算,那么我们可以初步总结出以下规则来进行计算:
  1. 读取到括号时将括号内内容优先计算出来,然后取代原括号运算式的位置。
  2. 读取到运算符时比较其与紧接的前后两个运算符的优先级,若均优先,进行计算,否则进行搁置。
  • 改版符号运算顺序规则但是又有问题了,这样的规则无法直观的转化成代码,仅供我们理解,所以我们对规则在进行一定的细致整改,并为了让计算机知道我们的运算式何时结束,我们向符号栈栈底和运算式最后面加上‘#’作为界标,当俩界标相遇表示运算结束,(所以界标‘#’优先级最低)然后编制改良后的规则:
  1. 读取到‘#’时若其紧接的前面的算术运算符为‘#’则表示结束,否则对前接符号进行出栈运算。
  2. 读取到‘+’,‘-’,若其前接运算符为‘#’则搁置入栈,否则将其前接符号弹出运算。
  3. 读取到’x’,’/’,若其前接运算符为‘x’或’/'则将其前接符号进行出栈运算,否则搁置入栈。
  4. 读取到‘(’进行直接进行搁置入栈。
  5. 读取到‘)’,若其前接符号为‘(’则将两个符号都销毁。否则将其前接符号出栈运算。
    然后根据上面的规则,我们编写一个判断运算顺序的函数:
int Preemption(char a,char b)                           //符号优先级比较,a为当前读入,b为栈顶元素
{int c;                                              //c反馈指令信息 0.结束 1.弹出 2.进栈 3.删除当前元素及栈顶元素 4.报错 switch(a){case '#':if(b=='#') c=0;else c=1;break;case '+':if(b=='#'||b=='(') c=2;else c=1;break;case '-':if(b=='#'||b=='(') c=2;else c=1;break;case '*':if(b=='*'||b=='/') c=1;else c=2;break;case '/':if(b=='*'||b=='/') c=1;else c=2;break;case '(':c=2;break;case ')':if(b=='(') c=3;else c=1;break;default :c=4;break; }return c;
}

这个函数中我使用c作为反馈指令的媒介,函数返回值为c,而c的不同值代表不同的指令情况: 0.结束运算 1.弹出符号进行运算 2.符号搁置进栈 3.删除当前元素及栈顶元素(俩括号相遇) 4.报错(读到无法识别的字符) 。只需要在主函数中使用一个switch函数接受这个指令并对应执行即可。

  • 读取字符串中的多位十进制数字由于我们输入的算术表达式是一个字符串,所以从中直接性识别出来的只能有个位数字,而且进行储存时需要对其进行这样一个运算(例如:int a,char c,a=c-‘0’;)。如果我们读取一个数字就直接用这种方式存入数字栈中,那么我们存到的一定只能是个位数字。所以我们现在需要一块代码来负责数字的读取,确保其可以读取到多位数字。我写的代码如下:
if(*p<='9'&&*p>='0') {a=a*10+(*p-'0');if(*(p+1)>'9'||*(p+1)<'0'){*p4++=a;a=0;}p++;}

其中p是指向算术表达式的指针,p4是指向数字栈的指针
ok,大致所需要注意的事项就是这些了,下面是我的完整代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int Preemption(char a,char b)                           //符号优先级比较,a为当前读入,b为栈顶元素
{int c;                                              //c反馈指令信息 0.结束 1.弹出 2.进栈 3.删除当前元素及栈顶元素 4.报错 switch(a){case '#':if(b=='#') c=0;else c=1;break;case '+':if(b=='#'||b=='(') c=2;else c=1;break;case '-':if(b=='#'||b=='(') c=2;else c=1;break;case '*':if(b=='*'||b=='/') c=1;else c=2;break;case '/':if(b=='*'||b=='/') c=1;else c=2;break;case '(':c=2;break;case ')':if(b=='(') c=3;else c=1;break;default :c=4;break; }return c;
}
int main()
{char str[50]={"\0"};char *p=str;double *p3,*p4,a=0,b=0;char *p1,*p2;char stack1[20];                      //符号栈 栈顶指针p2,栈底指针p1 double stack2[20];                       //数字栈 栈顶指针p4,栈底指针p3 p1=p2=stack1;p3=p4=stack2;*p2++='#';printf("请输入需要计算的算术表达式:");gets(str);strcat(str,"#");while(*p!='\0'){if(*p<='9'&&*p>='0') {a=a*10+(*p-'0');if(*(p+1)>'9'||*(p+1)<'0'){*p4++=a;a=0;}p++;}else{switch(Preemption(*p,*(p2-1))){case 0:printf("计算结果为:%lf\n",*p3);p++;break;case 1:b=*--p4;switch(*(--p2)){case '+':*(p4-1)=*(p4-1) + b;break;case '*':*(p4-1)=*(p4-1) * b;break;case '-':*(p4-1)=*(p4-1) - b;break;case '/':*(p4-1)=*(p4-1) / b;break;}break;case 2:*p2++=*p++;break;case 3:p++;p2--;break;case 4:printf("程序读到了无法计算的符号,出错了\n");p++;break;}} }return 0;
}

用c语言实现一个简单的计算器(数据结构)相关推荐

  1. 用C语言实现一个简单的计算器代码

    #include <stdio.h> #include <math.h> #include <stdlib.h> //预处理指令 int main(void) {d ...

  2. C语言设计一个简单的计算器,完成两个数的加、减、乘、除、取余。(根据输入的运算符,选择相应的运算,用switch语句实现。

    设计一个简单的计算器,完成两个数的加.减.乘.除.取余.(根据输入的运算符,选择相应的运算,用switch语句实现. 实验代码: #include <stdio.h> #include & ...

  3. c语言简单整数计算器代码,用c语言实现一个简单的计算器(数据结构)

    概要:主要以c语言为例对数据结构中写一个简易的计算器(计算整数间加减乘除括号运算)的算法进行大致讲述,细说如何去实现符号优先级的比较的函数实现. 注:由于编辑器缘故,本文内我以小写x代替了*作为乘号 ...

  4. 用C语言编写一个简单的“+”“”-“”*“/”计算器

    /* Note:Your choice is C IDE */ #include "stdio.h" void main() {     double a,b,d;     cha ...

  5. c语言 实现一个简单的计算器系统

    思路 1.采用多文件编程,引入自己编写的calculator.h和calculator.c 2.main函数中调用printMainMenu函数打印主菜单,并使用switch判断执行的功能.为实现重复 ...

  6. 用python语言写一个简单的计算器

    假如我们有这样一个式子: 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2 ...

  7. python123程序设计题说句心里话_用c++写一个简单的计算器程序

    // 050305.cpp : 定义控制台应用程序的入口点. // // 050304.cpp : 定义控制台应用程序的入口点. // //四则运算 #include "stdafx.h&q ...

  8. c语言12之编程设计一个简单的计算器程序,要求根据用户从键盘输入的表达式:操作数1 运算符op 操作数2 计算表达式的值,指定的运算符为加减乘除。

    题目: 设计一个简单的计算器程序,要求根据用户从键盘输入的表达式: 操作数1 运算符op 操作数2 计算表达式的值,指定的运算符为加减乘除. 源代码: #include<stdio.h> ...

  9. 【C语言】实现简单的计算器

    一.普通方法 用C语言来实现一个简单的计算器. #include <iostream> // 头文件 using namespace std; // 命名空间名称引入 // std 是 C ...

最新文章

  1. 郭为:大数据时代的企业管理挑战
  2. Ubuntu 软件安装
  3. 重磅推荐《南瓜书》:周志华《机器学习》的代码实现
  4. 无监督领域迁移及文本表示学习的相关进展
  5. kingedit 上传php_php文件上传下载实例(实现最简单的网盘功能)
  6. Gartner发布2020年十大战略科技发展趋势
  7. 为什么前端工程师很少用Visual Studio?
  8. ssis导入xml_SSIS包中的XML任务概述
  9. visual studio 2012 下配置OPENcv3.1 和CMAKE问题总结
  10. JavaScript函数setInterval()和setTimeout()正确的写法
  11. rand()函数实现原理:线性同余法
  12. 计算机用户名改成英文,win10如何把用户名改成英文
  13. 配置环境变量时Path单行显示问题
  14. l298n电机哪一端为正_L298N电机驱动模块的使用方法(干货)
  15. “非著名相声演员”郭德纲【ZZ】
  16. 真没想到,vmware进入 bios设置 的方法是这样的
  17. Newton tangent method
  18. easyui mysql 分页_Easyui 树形网格添加分页_EasyUI 教程
  19. 布袋除尘器--预喷涂
  20. c调用python第三方包_cbillington_Python包维护者_第三方库作者_PyPI项目模块Package - Python中文网...

热门文章

  1. 我们终将泄露的人脸数据,后果到底有多可怕?
  2. 【UI】产品设计之什么是色彩情绪
  3. gpio操作实现人体感应灯(一)
  4. TIN的构建、Delaunay三角网、Voronoi图
  5. JavaScript基础学习——第五天(原型、垃圾回收、数组简介)
  6. ios 动画 隐藏tabbar_ios 开发怎么隐藏tabbar
  7. Java面向对象基础呕心沥血三千字
  8. 思科access-list 1 permit 1.1.1.0 0.0.254.0 //允许第三位为奇数的路由
  9. ipadmobile通用webapp框架前哨战
  10. 怎么把图片中的文字转换成word